当前的UDP宿/源块使用GNURadio向/从NIC发送数据包。它使用boost asio进行发送/接收。我需要修改这些UDP接收器/源块来处理现有功能的UDP和IP,以通过1 1GB的nic,以及添加boost原始套接字/协议,以便我们可以在没有IP地址的10G nic上发送无IP的layer2数据包(接收器是具有自定义错误检查/恢复等功能的FPGA )。
仅使用C语言,我就有了测试程序,在这些程序中,我可以按照自己的需要制作数据包,然后在另一端发送和接收。它们来自:
Create a layer 2 / ethernet socket with boost asio raw socket (in C++) http://qiita.com/kadopoly/items/acafa01945e5cfe39270
因为GNURadio在C++中,所以我需要修改boost套接字/协议设置,以适应udp_sink_impl.cc和udp_sink_impl.h文件,这样我就可以发送数据包。
堆栈溢出链接似乎是最直接的(我不是一个有经验的程序员),我能够将它添加到我的GNURadio块中并进行传输。它不能正确地发送transmitbuffer2缓冲区(发送了一个包,但内容错误),但确实发送了Hello World!streambuf buffer是否正确,所以我不知道。它不能处理0x00,所以我不能用它来测试发送的MAC地址。
这是我目前所拥有的:
udp_sink_impl.h代码片段:
char tmpHeaderBuff[12]; // 32-bit sync word (0xFFFFFFFF), 32-bit sequence num and 32-bit data size
unsigned char custom_type[2] = {0x82,0x00};
unsigned char ethHeader[12] = {0x00,0x0c,0x29,0x05,0x0d,0x15,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
unsigned char mac_str[6];
unsigned char dstMAC[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
unsigned char srcMAC[6];
/* 1G management stuff */
boost::asio::io_service d_io_service;
boost::asio::ip::udp::endpoint d_endpoint;
boost::asio::ip::udp::socket *udpsocket;
/* 1G management stuff */
/* 10G raw socket stuff */
typedef boost::asio::generic::raw_protocol raw_protocol_t;
typedef boost::asio::generic::basic_endpoint<raw_protocol_t> raw_endpoint_t;
boost::asio::io_service d_io_service10;
raw_protocol_t::socket *d_socket10;
/* 10G raw socket stuff */udp_sink_impl.cc代码片段:
getMACAddress(d_send_iface,srcMAC);
/* Begin 1G management connection */
std::string s__port = (boost::format("%d") % port).str();
std::string s__host = host.empty() ? std::string("localhost") : host;
boost::asio::ip::udp::resolver resolver(d_io_service);
boost::asio::ip::udp::resolver::query query(s__host, s__port,
boost::asio::ip::resolver_query_base::passive);
d_endpoint = *resolver.resolve(query);
udpsocket = new boost::asio::ip::udp::socket(d_io_service);
udpsocket->connect(d_endpoint);
/* End 1G management connection */
/* Begin 10G management connection */
sockaddr_ll sockaddr;
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sll_family = PF_PACKET;
sockaddr.sll_protocol = htons(ETH_P_ALL);
sockaddr.sll_ifindex = if_nametoindex(send_iface.c_str());
sockaddr.sll_hatype = 1;
raw_protocol_t::socket d_socket10(d_io_service10, raw_protocol_t(PF_PACKET, SOCK_RAW)); /* Needs root or cap_net_raw permissions */
d_socket10.bind(raw_endpoint_t(&sockaddr, sizeof(sockaddr)));
/* End 10G management connection */
/* This currently does not work for unknown reason. Transmitted packet does NOT match buffer contents expected. But the streambuf seems to work. */
std::vector<boost::asio::const_buffer> transmitbuffer2;
transmitbuffer2.clear();
transmitbuffer2.push_back(boost::asio::buffer((const void *)srcMAC, sizeof(srcMAC)));
transmitbuffer2.push_back(boost::asio::buffer((const void *)dstMAC, sizeof(dstMAC)));
transmitbuffer2.push_back(boost::asio::buffer((const void *)custom_type, sizeof(custom_type)));
d_socket10.send(boost::asio::buffer(transmitbuffer2));
/* for testing */
boost::asio::streambuf buffer;
std::ostream stream( &buffer );
unsigned char const deadbeef[] = { 0xde, 0xad, 0xbe, 0xef }; // can't handle 0x00
stream << "Hello, World!!!"
<< reinterpret_cast< char const * >( deadbeef );
d_socket10.send(buffer.data());
} // Close constructor
.
.
.
udp_sink_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
.
.
.
udpsocket->send_to(transmitbuffer,d_endpoint);最后,在udp_sink_impl::work函数中,我想替换现有的UDP调用:
udpsocket->send_to(transmitbuffer,d_endpoint); 使用类似这样的东西:
d_socket10->send(transmitbuffer);目前,当我这样做时,没有数据包被发送,似乎崩溃或退出程序,而不是连续发送数据,所以我认为这是某种类型的崩溃。
有人能给我解释一下如何在C++中为UDP Sink/Source块实现简单堆栈溢出的指针示例或日本标记化的原始套接字示例吗?Sink (发送)当前是我优先于Source (接收)的优先级。
非常提前谢谢你。任何帮助或建议都是非常感谢的。
发布于 2017-09-20 01:45:18
在scatter-gather io上的boost doc中,我认为send的语法应该是:
d_socket10.send(transmitbuffer2); // don't add the extra boost::asio::buffer()我找不到任何使用缓冲区向量的boost::asio::buffer的例子,所以我不确定到底发生了什么(可能有一些我看不到的隐式转换)。
对于流测试,当您使用write成员函数而不是operator<<在流中插入时,必须手动指定大小。类似于:
unsigned char const deadbeef[5] = { 0x00, 0xde, 0xad, 0xbe, 0xef };
stream.write(reinterpret_cast<const char*>(&deadbeef[0]), 5);这样,您就可以处理发送空字符。
你能展示一下transmitbuffer是如何构建的吗?它是否与transmitbuffer2相同
编辑
段错误表明您试图以非法的方式访问内存。仅从您的代码片段进行调试有些困难,但我会首先检查您发送的缓冲区是否仍然有效。boost::asio::buffer不会复制底层内存,当您准备发送时,它需要保持有效。
您还会在代码片段中混合使用指针和对象,因此请确保没有任何悬空指针,并且在调用send之前,每个人都处于有效状态
编辑2
在头文件中,声明一个名为d_socket10的成员指针,该成员指针从不在构造函数中分配或创建。第147行上的此调用:
raw_protocol_t::socket d_socket10(d_io_service10, raw_protocol_t(PF_PACKET, SOCK_RAW));创建一个与成员指针同名的对象,当您退出构造函数的作用域时,该对象将被销毁。稍后,您使用未分配任何内容的成员指针调用send,因此出现了segfault。
要修复它,您需要创建它并以与udpsocket相同的方式管理它的生命周期
d_socket10 = new raw_protocol_t::socket(d_io_service10, raw_protocol_t(PF_PACKET, SOCK_RAW));并在不再需要delete时调用它。
https://stackoverflow.com/questions/46290909
复制相似问题