Introduction of load_byte/load_half/load_word functions commonly used in ebpf programs

Preface

When reading the source code of some network-related ebpf programs, you may find that some of them use the functions load_byte, load_half and load_word to assist in parsing network packets.

So what exactly are the functions of these functions? And what is their respective use scenarios, how to know which function to use? This article will document the various functions of these functions and the use of scenarios.

load_byte

Function Definition

The load_byte function is defined as follows:

unsigned long long load_byte(void *skb,
                          unsigned long long offset) asm("llvm.bpf.load.byte");

Function Features

This function reads 8-bits of data from the offset position of the packet pointer pointed to by skb. This is the same as the __builtin_bpf_load_byte function in gcc.

Usage Scene

When you want to read the value of a field of data type 8-bits (1 byte) from struct __sk_buff *skb, you can use load_byte to read the corresponding data directly from the pointer.

for example:

__u8 protocol = load_byte(skb, ETH_HLEN + offsetof(struct iphdr, protocol));

load_half

Function Definition

The load_half function is defined as follows:

unsigned long long load_half(void *skb,
                         unsigned long long offset) asm("llvm.bpf.load.half");

Function Features

This function reads 16-bits of data from the offset position in the packet pointer pointed to by skb. This is the same as the __builtin_bpf_load_half function in gcc.

Usage Scene

When you want to read the value of a field of data type 16-bits (2 bytes) from struct __sk_buff *skb, you can use load_half to read the corresponding data directly from the pointer.

for example:

__u16 h_proto = load_half(skb, offsetof(struct ethhdr, h_proto));

load_word

Function Definition

The load_word function is defined as follows:

unsigned long long load_word(void *skb,
                         unsigned long long offset) asm("llvm.bpf.load.word");

Function Features

This function reads 32-bits of data from the offset position in the packet pointer pointed to by skb. This is the same as the __builtin_bpf_load_word function in gcc.

Usage Scene

When you want to read the value of a field of data type 32-bits (4 bytes) from struct __sk_buff *skb, you can use load_word to read the corresponding data directly from the pointer.

for example:

__u32 saddr = load_word(skb, ETH_HLEN + offsetof(struct iphdr, saddr));

Alternative Functions

If you do not want to rely on llvm to implement the functions provided by these functions, you can use the bpf_skb_load_bytes function provided in bpf-helpers to implement similar functions.

For example, the previous examples can be rewritten as :

// __u8 protocol = load_byte(skb, ETH_HLEN + offsetof(struct iphdr, protocol));
__u8 protocol;
if (bpf_skb_load_bytes(skb, ETH_HLEN + offsetof(struct iphdr, protocol), &protocol, sizeof(protocol)) < 0)
    return 0;


// __u16 h_proto = load_half(skb, offsetof(struct ethhdr, h_proto));
__u16 raw_h_proto;
if (bpf_skb_load_bytes(skb, offsetof(struct ethhdr, h_proto), &raw_h_proto, sizeof(raw_h_proto)) < 0)
    return 0;
__u16 h_proto = bpf_ntohs(raw_h_proto);


// __u32 saddr = load_word(skb, ETH_HLEN + offsetof(struct iphdr, saddr));
__u32 saddr;
if (bpf_skb_load_bytes(skb, ETH_HLEN + offsetof(struct iphdr, saddr), &saddr, sizeof(saddr)) < 0)
    return 0;

Comments