I'm attaching an eBPF packet filter declared as:
int sock_peek_packet(struct __sk_buff *skb);
Using the python bcc
library, as so:
interface = 'wg0' # or 'eth0'
b = bcc.BPF(src_file=src_path, debug=0)
fn = b.load_func('sock_peek_packet', bcc.BPF.SOCKET_FILTER)
bcc.BPF.attach_raw_socket(dev=interface, fn=fn)
When attaching to eth0
, the contents of skb
is an L2 ethernet frame (i.e. starts with a struct ethhdr
, like how you find on examples all over the internet).
However, when attaching to wg0
, the contents of skb
is an L3 (IP) packet, (i.e, starts with a struct iphdr
) with no proceeding ethernet header.
How can I determine at runtime which type of packet I'm getting? (in my final program I will be attaching to all interfaces on the host). skb->protocol
and skb->pkt_type
do not change between eth0 and wg0.
Note: currently testing on Linux-6.1.0-21-amd64
but have observed the same behavior on all other versions tested
You cannot choose. This comes down to the device type. The eth0
devices is L2 aware because it actually sends out packets over the wire. But a device like wg0
is virtual, L3 packets go in, and L3 packets come out.
As far as I know, the way you can tell before hand is to see if the device has a MAC address when you inspect it via ip l
. If a device has no MAC, it is an L3 device.