Packets processing

Runtime

At runtime, the BPF programs have access to a 512 bytes stack. bpfilter will use the stack to store runtime data, such as the program’s argument, the packet size…

bf_runtime defines the layout of the data stored on the stack of the BPF program and simplifies its access.

This header can be included into C stubs to be integrated into the generated BPF programs.

Defines

BF_L2_SLICE_LEN

Size of the L2 dynamic pointer slice buffer.

Only Ethernet is supported at L2, so the buffer should be as big as the Ethernet header.

BF_L3_SLICE_LEN

Size of the L3 dynamic pointer slice buffer.

The buffer should be able to contain the largest supported L3 protocol header among:

  • IPv4: 20 bytes (ignoring the options)

  • IPv6: 40 bytes (ignoring the extension headers)

BF_L4_SLICE_LEN

Size of the L4 dynamic pointer slice buffer.

The buffer should be able to contain the largest supported L4 protocol header among:

  • UDP: 8 bytes

  • TCP: 20 bytes

  • ICMP: 8 bytes (ignoring the payload)

  • ICMPV6: 4 bytes (ignoring the body)

BF_PROG_CTX_OFF(field)

Return the offset of a field in the runtime context, from BPF_REG_10.

Parameters:
  • field – Field to get the offset of.

Returns:

Offset of field in the runtime context based on BPF_REG_10.

BF_PROG_SCR_OFF(index)

Return the offset of an index in the scratch area, from BPF_REG_10.

Parameters:
  • index – Index of the scratch area entry to get the offset of.

Returns:

Offset of index in the scratch area based on BPF_REG_10.

bf_aligned(x)

Functions

void *bpf_dynptr_slice(const struct bpf_dynptr*, __u32, void*, __u32)
int bpf_dynptr_from_xdp(struct xdp_md*, __u64, struct bpf_dynptr*)
struct bf_ip4_lpm_key
#include <bpfilter/cgen/runtime.h>

Public Members

__u32 prefixlen
__u32 data
struct bf_ip6_lpm_key
#include <bpfilter/cgen/runtime.h>

Public Members

__u32 prefixlen
__u8 data[16]
struct bf_runtime
#include <bpfilter/cgen/runtime.h>

Runtime stack layout for the generated BPF programs.

This runtime context is located at r10 - sizeof(struct bf_runtime), it is valid during the whole lifetime of the BPF program.

Access to the packet data is performed through a BPF dynamic pointer, this pointer is stored in the runtime context, as well as the scratch areas used to store the header slices.

Each slice storage area is big enough to store the largest protocol header for a given layer. The BPF subsystem might copy the requested data into the slice storage area or not. In any case, a pointer to the data is returned, this pointer is stored in the runtime context and will be used to access the data.

L3 and L4 protocol identifiers are used to check which matcher should be applied to a given packet. They can’t be stored in the runtime context as the verifier might not be able to keep track of them, leading to verification failures.

Warning

Not all the BPF verifier versions are born equal, as older ones might require stack access to be 8-bytes aligned to work properly. Hence, all fields of the runtime context are aligned to 8 bytes, and bf_runtime size must be a multiple of 8.

Public Members

void *arg

Argument passed to the BPF program, its content depends on the BPF program flavor:

  • BF_FLAVOR_XDP: struct xdp_md *

  • BF_FLAVOR_TC: struct struct __sk_buff *

  • BF_FLAVOR_CGROUP: struct __sk_buff *

  • BF_FLAVOR_NF: struct bpf_nf_ctx *

struct bpf_dynptr dynptr

BPF dynamic pointer to access the packet data. Dynamic pointers are used with for program flavor.

__u64 pkt_size

Total size of the packet.

__u32 l3_offset

Offset of the layer 3 protocol header.

__u32 l4_offset

Offset of the layer 4 protocol header.

__u32 ifindex

On ingress, index of the input interface. On egress, index of the output interface.

void *l2_hdr

Pointer to the L2 protocol header (in a dynamic pointer slice).

void *l3_hdr

Pointer to the L3 protocol header (in a dynamic pointer slice).

void *l4_hdr

Pointer to the L4 protocol header (in a dynamic pointer slice).

__u8 l2[14]

Layer 2 header.

__u8 l3[40]

Layer 3 header.

__u8 l4[20]

Layer 4 header.

__u8 scratch[64]

Scratch area.

Matchers

Matchers are criteria used to match a network packet against a specific rule. For example, a matcher could be used to match the destination IP field of an IPv4 packet to a specific IP address.

Matchers are composed of:

  • A type, defining which data in the network packet to match the payload against. In the example about, the type would be related to IPv4 destination address field.

  • An operator, to know how to compare the data in the packet defined by the type to the payload contained in the matcher. For example, we want the matcher to match when the IPv4 destination address is equal to the IP address in the payload.

  • A payload, which is compared to the similar value in the network packet.

Defines

_free_bf_matcher_

Automatically destroy bf_matcher objects going out of the scope.

Enums

enum bf_matcher_type

Matcher type.

The matcher type define which header/field of a packet is to be used to match against the payload.

Values:

enumerator BF_MATCHER_META_IFINDEX

Matches the packet’s network interface index. On ingress it represents the input interface, on egress the output interface.

enumerator BF_MATCHER_META_L3_PROTO

Matches the L3 protocol.

enumerator BF_MATCHER_META_L4_PROTO

Matches the L4 protocol, idependently from the L3 protocol.

enumerator BF_MATCHER_META_PROBABILITY

Matches packets based on a random probability.

enumerator BF_MATCHER_META_SPORT

Matches the source port for UDP and TCP packets.

enumerator BF_MATCHER_META_DPORT

Matches the destination port for UDP and TCP packets.

enumerator BF_MATCHER_IP4_SADDR

Matches IPv4 source address.

enumerator BF_MATCHER_IP4_SNET

Matches IPv4 source network.

enumerator BF_MATCHER_IP4_DADDR

Matches IPv4 destination address.

enumerator BF_MATCHER_IP4_DNET

Matches IPv4 destination network.

enumerator BF_MATCHER_IP4_PROTO

Matches against the IPv4 protocol field.

enumerator BF_MATCHER_IP6_SADDR

Matches IPv6 source address.

enumerator BF_MATCHER_IP6_SNET

Matches IPv6 source network.

enumerator BF_MATCHER_IP6_DADDR

Matches IPv6 destination address.

enumerator BF_MATCHER_IP6_DNET

Matches IPv6 destination network.

enumerator BF_MATCHER_TCP_SPORT

Matches against the TCP source port.

enumerator BF_MATCHER_TCP_DPORT

Matches against the TCP destination port.

enumerator BF_MATCHER_TCP_FLAGS

Matchers against the TCP flags.

enumerator BF_MATCHER_UDP_SPORT

Matches against the UDP source port.

enumerator BF_MATCHER_UDP_DPORT

Matches against the UDP destination port.

enumerator BF_MATCHER_SET_SRCIP6PORT

Matches the source (IPv6, port) tuple against a set.

enumerator BF_MATCHER_SET_SRCIP6

Matches the source IPv6 address against a set.

enumerator BF_MATCHER_ICMP_TYPE

Matches against the ICMP type.

enumerator BF_MATCHER_ICMP_CODE

Matches against the ICMP code.

enumerator BF_MATCHER_ICMPV6_TYPE

Matches against the ICMPv6 type.

enumerator BF_MATCHER_ICMPV6_CODE

Matches against the ICMPv6 code.

enumerator _BF_MATCHER_TYPE_MAX
enum bf_matcher_tcp_flag

Define the TCP flags values as number of shifts of 1.

Values:

enumerator BF_MATCHER_TCP_FLAG_FIN = 0
enumerator BF_MATCHER_TCP_FLAG_SYN = 1
enumerator BF_MATCHER_TCP_FLAG_RST = 2
enumerator BF_MATCHER_TCP_FLAG_PSH = 3
enumerator BF_MATCHER_TCP_FLAG_ACK = 4
enumerator BF_MATCHER_TCP_FLAG_URG = 5
enumerator BF_MATCHER_TCP_FLAG_ECE = 6
enumerator BF_MATCHER_TCP_FLAG_CWR = 7
enumerator _BF_MATCHER_TCP_FLAG_MAX
enum bf_matcher_op

Matcher comparison operator.

The matcher comparison operator defines the type of comparison to operator for a specific matcher.

Values:

enumerator BF_MATCHER_EQ

Test for equality.

enumerator BF_MATCHER_NE

Test for inequality.

enumerator BF_MATCHER_ANY

Test for partial subset match.

enumerator BF_MATCHER_ALL

Test for complete subset match.

enumerator BF_MATCHER_IN

Test if the value is in a set.

enumerator BF_MATCHER_RANGE

Test if the value is in a range.

enumerator _BF_MATCHER_OP_MAX

Functions

int bf_matcher_new(struct bf_matcher **matcher, enum bf_matcher_type type, enum bf_matcher_op op, const void *payload, size_t payload_len)

Allocate and initalise a new matcher.

Parameters:
  • matcher – Matcher object to allocate and initialise. Can’t be NULL. On success, contain a pointer to the matcher object, unchanged on error.

  • type – Matcher type.

  • op – Comparison operator.

  • payload – Payload of the matcher, its content and size depends on type . Can be NULL but only if payload_len is 0, in which case there is no payload.

  • payload_len – Length of the payload.

Returns:

0 on success, or negative errno value on failure.

int bf_matcher_new_from_marsh(struct bf_matcher **matcher, const struct bf_marsh *marsh)

Allocate a new matcher and initialise it from serialised data.

Parameters:
  • matcher – On success, points to the newly allocated and initialised matcher. Can’t be NULL.

  • marsh – Serialised data to use to initialise the matcher.

Returns:

0 on success, or negative errno value on failure.

void bf_matcher_free(struct bf_matcher **matcher)

Deinitialise and deallocate a matcher.

Parameters:
  • matcher – Matcher. Can’t be NULL.

int bf_matcher_marsh(const struct bf_matcher *matcher, struct bf_marsh **marsh)

Serialise a matcher.

Parameters:
  • matcher – Matcher object to serialise. Can’t be NULL.

  • marsh – On success, contains the serialised matcher. Can’t be NULL.

void bf_matcher_dump(const struct bf_matcher *matcher, prefix_t *prefix)

Dump a matcher.

Parameters:
  • matcher – Matcher to dump.

  • prefix – Prefix for each printed line.

const char *bf_matcher_type_to_str(enum bf_matcher_type type)

Convert a matcher type to a string.

Parameters:
Returns:

String representation of the matcher type.

int bf_matcher_type_from_str(const char *str, enum bf_matcher_type *type)

Convert a string to the corresponding matcher type.

Parameters:
  • str – String containing the name of a matcher type.

  • type – Matcher type value, if the parsing succeeds.

Returns:

0 on success, or negative errno value on failure.

const char *bf_matcher_op_to_str(enum bf_matcher_op op)

Convert a matcher operator to a string.

Parameters:
  • op – The matcher operator to convert. Must be a valid bf_matcher_op

Returns:

String representation of the matcher operator.

int bf_matcher_op_from_str(const char *str, enum bf_matcher_op *op)

Convert a string to the corresponding matcher operator.

Parameters:
  • str – String containing the name of a matcher operator.

  • op – Matcher operator value, if the parsing succeeds.

Returns:

0 on success, or negative errno value on failure.

const char *bf_matcher_tcp_flag_to_str(enum bf_matcher_tcp_flag flag)

Convert a TCP flag to a string.

Parameters:
  • flag – TCP flag to convert.

Returns:

String representation of the TCP flag.

int bf_matcher_tcp_flag_from_str(const char *str, enum bf_matcher_tcp_flag *flag)

Convert a string to the corresponding TCP flag.

Parameters:
  • str – String containing the name of the TCP flag.

  • flag – TCP flag value, if the parsing succeeds.

Returns:

0 on success, or negative errno value on failure.

struct bf_matcher_ip4_addr
#include <core/matcher.h>

Defines the structure of the payload for bf_matcher’s BF_MATCHER_IP4_SADDR and BF_MATCHER_IP4_DADDR types.

Public Members

uint32_t addr
uint32_t mask
struct bf_matcher_ip6_addr
#include <core/matcher.h>

Defines the payload for the IPv6 address matcher.

Public Members

uint8_t addr[16]

128-bits IPv6 address.

uint8_t mask[16]

128-bits IPv6 mask.

struct bf_matcher
#include <core/matcher.h>

Matcher definition.

Matchers are criterias to match the packet against. A set of matcher defines what a rule should match on.

Public Members

enum bf_matcher_type type

Matcher type.

enum bf_matcher_op op

Comparison operator.

size_t len

Total matcher size (including payload).

uint8_t payload[0]

Payload to match the packet against (if any).