The current GNURadio UDP Sink/Source blocks use UDP to send packets in/out of the NIC. It uses boost asio for the sending/receiving. I need to modify these UDP sink/source blocks to handle both UDP with IP for the existing functionality to go over a 1GB nic as well as add boost raw socket/protocol so that we can send layer2 packets without IP over a 10G nic that does NOT have IP addresses (receiver is an FPGA with custom error checking/recovery, etc).
Using just C, I have test programs where I can craft the packet as I want and send it out and receive it on the other side. They came from:
Create a layer 2 / ethernet socket with boost asio raw socket (in C++) http://qiita.com/kadopoly/items/acafa01945e5cfe39270
Since GNURadio is in C++, I need to modify the boost socket/protocol setup to fit into the udp_sink_impl.cc and udp_sink_impl.h files so I can send out the packets.
The Stack Overflow link seemed to be the most straight forward (I am not an experienced coder) and I was able to add it into my GNURadio block and have it transmit. It doesn't send the transmitbuffer2 buffer correctly (a packet is sent, but with wrong contents), but does send the Hello World! streambuf buffer correctly, so that is unknown to me. It doesn't handle 0x00 though, so I couldn't use that to test MAC address being sent.
Here is what I currently have:
udp_sink_impl.h snippet:
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 snippet:
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);
Ultimately, in the udp_sink_impl::work function I want to replace the existing UDP call:
udpsocket->send_to(transmitbuffer,d_endpoint);
with something like:
d_socket10->send(transmitbuffer);
Currently, when I do that, no packet is sent and seems to crash or exit the program instead of continuously sending data, so I take that to be a crash of some sort.
Can someone explain to me how to implement the pointer for simple Stack Overflow example or the japanese tokenized raw socket example in C++ for the UDP Sink/Source blocks? Sink (sending) is currently my priority over Source (receiving).
Thanks very much in advance. Any help or suggestions are much appreciated.