1

Background: I'm a fourth year computer engineering major at UCSB. I've taken networking and operating systems courses. I created a program in userspace that broadcasts UDP packets onto the subnet and receives UDP packets in an adhoc network. What I'm trying to accomplish is to convert this program into a kernel module that will work on an ARM embedded system with Angstrom Linux, kernel version 2.6.39 (the x86 to ARM architecture cross compilation is an issue for another day). The reason for this move to the kernel is to shed some of the overhead of userspace functions and to make the sending and receiving part as quick as possible.

I've never done anything like this before in any of the courses I've taken, so please tell me if anything I am saying is incorrect, useless or inefficient!

After research with Google, I've concluded the typical way is to do away with sockets entirely and work with the sockbuf structure and fill in the necessary headers myself. Would this have an effect on the ability to broadcast packets on the subnet? I am currently trying to follow the code here: UDP packet send with linux-kernel module without using sockets

I've figured out the reasoning behind most of the code, but the last part is what confuses me:

eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
skb_reset_mac_header(skb);
skb->protocol = eth->h_proto = htons(ETH_P_IP);
memcpy(eth->h_source, dev->dev_addr, ETH_ALEN);
memcpy(eth->h_dest, remote_mac, ETH_ALEN);

skb->dev = dev;


dev_queue_xmit(skb);
  • All of the ethernet header seems to be constructed purely out of headers defined in the kernel besides the source MAC address, is this correct? I am going to be broadcasting my packets, so what exactly should be put into the destination MAC address field?
  • More importantly, what is dev in the skb->dev = dev; line? From my investigation, it is a pointer to the device driver it is associated with. From my understanding, I would want this to point to the wireless chip device driver as I am using 802.11 to communicate. Do I have to create my own dev struct for the wireless driver? If so, there any guidance on how to accomplish this? If not, how can I access the existing device driver and use this in a kernel module?

I've tried commenting out the dev line and running the code but unsurprisingly I get a kernel panic once it executes dev_queue_xmit(skb);.

Again, I've never done anything like this before, so any advice would be helpful, even if it means changing my approach entirely! I also understand that this could be a niche of a question, but any sort of guidance is appreciated!

Thank you in advance!

Community
  • 1
  • 1
Steven Guan
  • 13
  • 1
  • 4
  • The source mac address field should have the same information as usual: the address of the device, as in your example, is correct. Put the ethernet broadcast address (FF:FF:FF:FF:FF:FF) in the destination mac address field. I think you use an existing device driver structure and put it in skb so the dev_queue_xmit method will know what driver to send the packet on; not sure about that, though. – Warren Dew Feb 21 '14 at 05:32
  • Thanks for the feedback. What you said makes sense. Though it looks like we both don't know much about device drivers! I appreciate the help though :) – Steven Guan Feb 22 '14 at 18:50
  • I would say, rather, that device drivers are highly dependent on the device and platform. – Warren Dew Feb 23 '14 at 01:53
  • Is there any specific platform/device in which you have more knowledge of? – Steven Guan Feb 23 '14 at 03:52
  • The last time I worked with networks at the device level was over a decade ago; most of the code was on an i960 embedded system but we had a test harness written for NT 4. On the embedded system incoming bytes were written to a set of buffers that we processed and outgoing packets were constructed into a buffer that was basically handed back; I think there must have been buffer flags indicating whether the buffers had been processed but I could be wrong. On NT, I believe we copied the data into or out of the device buffers, though I wasn't the one who did the coding for that. – Warren Dew Feb 23 '14 at 07:04
  • Incidentally, I second the idea of using sockets unless and until you have concrete evidence that the marginal gain from coding your own partial IP stack will make or break the product. – Warren Dew Feb 23 '14 at 07:05
  • Possible duplicate of [Sending UDP packets from the Linux Kernel](https://stackoverflow.com/q/10499865/608639), [Sending UDP packet in Linux Kernel](https://stackoverflow.com/q/1814485/608639), [Sending a UDP packet within a kernel module](https://stackoverflow.com/q/21925879/608639), [Sending small UDP packets from the Linux Kernel to LOOPBACK](https://stackoverflow.com/q/18339174/608639), etc. – jww May 13 '18 at 02:41

1 Answers1

2

The best way is not to interfere with the protocol if you are not trying to modify one. Work on a higher (socket) layer. This API can be found in net/socket.c

This will help: (open in new browser tab/window to zoom) Linux Kernel Network Flow

user31986
  • 1,558
  • 1
  • 14
  • 29
  • Thanks! That picture was extremely helpful in understanding the program flow of things. Do you really think I should go back up to the socket layer? I am trying to reduce as much latency in sending/receiving packets as possible (I am currently in the sub milliseconds level). If you think there is not enough benefit to go deeper, then I will try the socket implementation. Thank you! – Steven Guan Feb 22 '14 at 18:57
  • Yes, being at socket layer is better, because otherwise you might mess up with the protocol. You can use to kernel sockets to get appropriate payload (ethernet, ip, etc.). Also, there is no big advantage by reducing a couple of function calls. The overhead would be negligible, since you are already inside the kernel (unlike reducing system calls). If the answer was helpful, please mark it correct and +1, so that it is helpful to others to through searches. – user31986 Feb 24 '14 at 09:26