1- // SPDX-License-Identifier: Apache-2.0
2- //
31// Copyright 2025 SCION Association
2+ //
3+ // SPDX-License-Identifier: Apache-2.0
44
55//go:build ignore
66
1111#include <linux/udp.h>
1212#include "bpf_helpers.h"
1313
14- // This tells our bpf program which address/port(s) goes to the AF_PACKET socket
15- // and therefore not to the kernel.
14+ // kfilter: the kernel-side filter. The purpose of this program is to prevent the traffic that goes
15+ // to the AF_PACKET socket from getting to the regular kernel networking stack as well. If it did,
16+ // the kernel would expand resources processing the traffic, generating ICMP responses AND sending
17+ // them!
1618//
17- // This is a set of (address/port) pairs. Ports must be in network byte order.
19+ // This is still not ideal because I have yet to find a way to dispatch traffic before it is cloned
20+ // for AF_PACKET handling but after it is turned into an SKB. To solve that problem we would need to
21+ // go to XDP.
1822//
19- // The same port numbers are used by sockfilter to perform the opposite filtering. We may have many
20- // addrPorts to filter for a given interface. We could have several one-addrPort filters in series,
21- // we would easily exceed the number of filters that can be attached to an interface (not
22- // mentionning this would be inefficient). So we need a map with multiple ports.
23+ // This might not be as bad as it looks though: traffic is cloned via c-o-w and it might even not be
24+ // cloned until the AF_PACKET tap has made a drop/keep decision. The traffic that we keep is
25+ // definitely cloned; so... dear cow, a third swiss industry is now counting on you.
2326
2427typedef struct {
2528 __u8 ip_addr [16 ];
@@ -28,28 +31,23 @@ typedef struct {
2831 __u8 padding ; // just to make it clear what the real size of the struct is.
2932} addrPort ;
3033
34+ // k_map_flt tells our bpf program which address/port(s) go to the AF_PACKET socket and therefore
35+ // not to the kernel. Ports must be in network byte order.
36+ //
37+ // The same data is used by sockfilter to perform the opposite filtering. We may have many
38+ // pairs to filter for a given interface. We could have several one-addrPort filters in series,
39+ // but we would easily exceed the number of filters that can be attached to an interface (not
40+ // mentionning this would be inefficient). So we need a map with multiple pairs.
3141struct {
3242 __uint (type , BPF_MAP_TYPE_HASH );
3343 __type (key , addrPort ); // An IP address and a port number.
3444 __type (value , __u8 ); // Nothing. The map is just a set of keys.
3545 __uint (max_entries , 64 );
3646} k_map_flt SEC (".maps" );
3747
38- // The traffic that goes to the AF_PACKET socket, must not get to the regular kernel networking
39- // stack; else it will expand resources processing it, generating ICMP responses AND sending them!
40- // That is the purpose of this program.
41- //
4248// This is a very simple classifier type of filter: it looks at the packet's protocol and dest
4349// port. If it is UDP and if the port is found in sock_map_filt, then the packet is dropped (because
4450// the AF_PACKET socket will get and process it).
45- //
46- // This is not ideal because I have yet to find a way to dispatch traffic before it is cloned
47- // for AF_PACKET handling but after it is turned into an SKB. To solve that problem we need to go to
48- // XDP.
49- //
50- // This might not be as bad as it looks though: traffic is cloned via c-o-w and it might even not be
51- // cloned until the AF_PACKET tap has made a drop/keep decision. The traffic that we keep is
52- // definitely cloned; so... dear cow, a third swiss industry is now counting on you.
5351SEC ("tcx/ingress" )
5452int bpf_k_filter (struct __sk_buff * skb )
5553{
0 commit comments