Close

Berkeley Packet Filter (BPF)

A project log for Linux-ESPNOW

An attempt at implementing a direct link between a linux station and an ESP module using ESPNOW protocol for real time robot control

thomas-flayolsThomas Flayols 03/05/2019 at 13:010 Comments

Project status: The code is now able te send arbitrary ESPNOW data to a chosen MAC address.

What we need now is an efficient way to filter incoming packet. This is possible by software in the user space via a simple function that check the destination MAC, the type frame and some ESP now specific filed. But there is a better solution called Berkeley Packet Filter (BPF).

BPF can be attached to a socket. A filter is a program that will analyse any incoming packets and return True or False whether the packet should be accepted or rejected. This program is executed in kernel space in a virtual machine (after some analysis of the code). How cool is that?

To program a BPF, we have to write the filter with assembly, given a specific instruction set.

An exemple can be found here https://gist.github.com/oro350/8269805

In this example, we can see how a filter looks like:

static struct sock_filter bpfcode[6] = {
	{ OP_LDH, 0, 0, 12          },	// ldh [12]
	{ OP_JEQ, 0, 2, ETH_P_IP    },	// jeq #0x800, L2, L5
	{ OP_LDB, 0, 0, 23          },	// ldb [23]
	{ OP_JEQ, 0, 1, IPPROTO_TCP },	// jeq #0x6, L4, L5
	{ OP_RET, 0, 0, 0           },	// ret #0x0
	{ OP_RET, 0, 0, -1,         },	// ret #0xffffffff
};

Writing this program from scratch can be a bit tricky, if we need to adapt it to non fixed length header, compare a full MAC, etc.. 

But tcpdump can generate this for us with the -dd option.

Going further...

So now we have a hint for filtering packet in the kernel. But we can do better! The BPF could be done directly at the reception of incoming packet in the MAC80211, before the radiotap header is calculated etc..

This is not officially implemented in the current MAC80211 driver yet, but here is a patch and discussion about it

https://patchwork.kernel.org/patch/9679455/ 

I must admit that I never thought I would have to go so deep into linux for this project, but it's quite fun.

Discussions