Skip to main content

Sending GSO packets with AF_PACKET

Have you ever wanted to inject a GSO packet into the Linux kernel from userspace but been foiled by the lack of example code? I have good news!

I have been poking at the innards of the Linux kernel's network offload/acceleration code. I've blogged about a previous aspect - GSO_BY_FRAGS - before. To recap: modern network cards have the ability to take a long data buffer (bigger than the MTU of the link) and segment it in hardware, sticking a set of common headers on the front of each segment. In Linux, GSO - Generic Segmentation Offload - provides a lot of software infrastructure for this sort of offload.

Now normally all of this works automatically at the kernel level, without user intervention.

However, for testing, it can be helpful to be able to construct your own GSO packets. The AF_PACKET socket type allows you to insert GSO packets from userspace using infrastructure from virtio_net. However, I was unable to find any example code on the internet that showed how to actually use an AF_PACKET socket to send a GSO buffer. So after reading a lot of kernel source, I have put together a complete, working example of getting GSO packets from an AF_PACKET socket, into the kernel, and out to the network.

There's a lot more I am hoping to get into that repository soon, but in the short term I'm looking at what the kernel calls GSO_DODGY: GSO packets from an untrusted source, such as userspace. These packets have caused a lot of strife recently as it turns out they're not validated especially well: see e.g. d0c081b49137 ("flow_dissector: properly cap thoff field") and 7c68d1a6b4db ("net: qdisc_pkt_len_init() should be more robust"). I want to explore that a bit more, because the qdisc patch is blocking some other work I want to do. Stay tuned!

Comments

Post a Comment

Popular posts from this blog

Connecting to a wifi network with netplan

How do you connect to a a wifi network with netplan? I hang out on the #netplan IRC channel on Freenode, and this comes up every so often. netplan - the default network configuration tool in Ubuntu 17.10 onwards - currently supports WPA2 Personal networks, and open (unencrypted) networks only. If you need something else, consider using NetworkManager directly, or falling back to ifupdown and wpa_supplicant for a little longer. Without further ado, here are tested, working YAML files for connection to my local WPA2 and unencrypted network. The only things that have been changed are the SSIDs and password. Both networks have a router providing dhcp4. In both cases I assume there's only one wifi device in the system - if this is not true, replace match: {} with something more specific. You can drop these in  /etc/netplan and run netplan generate; netplan apply  and things should work. The network will also be brought up on subsequent boots. Note that, as always in YAML...

Anonymous bridges in netplan

netplan is the default network configuration system for new installs of Ubuntu 18.04 (Bionic). Introduced as the default in Artful, it replaces /etc/network/interfaces . One question that gets asked repeatedly is: "How do I set up an anonymous bridge in netplan?" (An anonymous bridge, I discovered, is one where the bridge doesn't have an IP address; it's more akin to a switch or hub.) It's been approached on  Launchpad , and comes up on the IRC channel. If you're trying to create a bridge without an IP address, the obvious first thing to try is this: network: version: 2 ethernets: ens8: match: macaddress: 52:54:00:f9:e9:dd ens9: match: macaddress: 52:54:00:56:0d:ce bridges: br0: interfaces: [ens8, ens9] This is neat, plausible, and wrong - the bridge will be created but will stay 'down'. Per ip a : 5: br0: <BROADCAST,MULTICAST> mtu 15...

Painless powerpc cross-compiling

As an ex-IBMer, I'm still quite fond of POWER/ppc64 processors, and occasionally cross-compile kernels for 64-bit little-endian PowerPC (ppc64el/ppc64le) from my amd64 system. It's not immediately obvious what the simplest way to do this is. On Ubuntu (and I'm told, Debian) it is really very simple. Installation sudo apt install gcc-powerpc64le-linux-gnu Congrats, you now have a ppc64le cross-compiling toolchain installed! If you need other languages, g++/gccgo/gfortran/gnat/gobjc-powerpc64le-linux-gnu are also available. Kernel cd your/linux/source make ARCH=powerpc CROSS_COMPILE=powerpc64le-linux-gnu- <your usual kernel build commands here> That's it. Userspace It depends a bit on the build system. Here's how to build, for example, sed , which uses autotools ( ./configure and friends). ./configure --host powerpc64le-linux-gnu make That's it.  For a dynamically linked binary, you only need the headers for any library depende...