Skip to content

Commit 46fde69

Browse files
committed
Use bpftool instead of iproute2 to load eBPF and XDP maps.
Signed-off-by: fruffy <fruffy@nyu.edu>
1 parent 6a17f8b commit 46fde69

File tree

14 files changed

+135
-205
lines changed

14 files changed

+135
-205
lines changed

backends/ebpf/CMakeLists.txt

+4-4
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,17 @@ if(NOT APPLE)
2121
set(FETCHCONTENT_QUIET OFF)
2222
fetchcontent_declare(
2323
bpfrepo
24-
URL https://github.com/libbpf/libbpf/archive/refs/tags/v1.4.1.tar.gz
25-
URL_HASH SHA256=cc01a3a05d25e5978c20be7656f14eb8b6fcb120bb1c7e8041e497814fc273cb
26-
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/runtime/contrib/libbpf
24+
URL https://github.com/libbpf/bpftool/releases/download/v7.5.0/bpftool-libbpf-v7.5.0-sources.tar.gz
25+
# URL_HASH SHA256=cc01a3a05d25e5978c20be7656f14eb8b6fcb120bb1c7e8041e497814fc273cb
26+
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/runtime/contrib/bpftool
2727
USES_TERMINAL_DOWNLOAD TRUE
2828
GIT_PROGRESS TRUE
2929
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
3030
)
3131
fetchcontent_makeavailable(bpfrepo)
3232
set(FETCHCONTENT_QUIET ${FETCHCONTENT_QUIET_PREV})
3333
# Check if we have already built the libbpf library.
34-
find_library(LIBBPF NAMES bpf HINTS "${CMAKE_CURRENT_SOURCE_DIR}/runtime/usr/lib64/")
34+
find_library(LIBBPF NAMES bpf HINTS "${CMAKE_CURRENT_SOURCE_DIR}/runtime/install/libbpf/")
3535
if (NOT LIBBPF)
3636
message("Building libbpf...")
3737
execute_process(

backends/ebpf/build_libbpf

+15-12
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1111
# See the License for the specific language governing permissions and
1212
# limitations under the License.
13-
""" This programs builds a libbpf static library and places it in the runtime
13+
""" This programs builds a bpftool binary and the libbpf static library and places it in the runtime
1414
folder. The library and its headers are required by the kernel target.
1515
"""
1616

@@ -31,21 +31,24 @@ def main() -> int:
3131
level=logging.WARN,
3232
filemode="w",
3333
)
34-
libbpf_dir = FILE_DIR.joinpath("runtime/contrib/libbpf")
35-
libbpf_src_dir = libbpf_dir.joinpath("src")
36-
libbpf_build_dir = libbpf_src_dir.joinpath("build")
37-
libbpf_target_dir = FILE_DIR.joinpath("runtime")
38-
# Create the libbpf build directory
39-
testutils.check_and_create_dir(libbpf_build_dir)
40-
# Build libbpf
41-
mk_cmd = f"make -C {libbpf_src_dir} install "
34+
bpftool_dir = FILE_DIR.joinpath("runtime/contrib/bpftool")
35+
bpftool_src_dir = bpftool_dir.joinpath("src")
36+
bpftool_build_dir = bpftool_src_dir.joinpath("build")
37+
bpftool_target_dir = FILE_DIR.joinpath("runtime/install/")
38+
bpftool_target_dir.mkdir(parents=True, exist_ok=True)
39+
# Create the bpftool build directory
40+
testutils.check_and_create_dir(bpftool_build_dir)
41+
# Build bpftool
42+
mk_cmd = f"make -C {bpftool_src_dir} install "
43+
mk_cmd += f"OUTPUT={bpftool_target_dir}/ "
4244
mk_cmd += "BUILD_STATIC_ONLY=y "
43-
mk_cmd += f"OBJDIR={libbpf_build_dir} "
44-
mk_cmd += f"DESTDIR={libbpf_target_dir} "
45+
mk_cmd += f"OBJDIR={bpftool_build_dir} "
46+
mk_cmd += f"DESTDIR={bpftool_target_dir} "
4547
mk_cmd += "EXTRA_CFLAGS=-fPIE"
48+
print(mk_cmd)
4649
result = testutils.exec_process(args=mk_cmd)
4750
if result.returncode != testutils.SUCCESS:
48-
testutils.log.error("Could not build libbpf")
51+
testutils.log.error("Could not build bpftool")
4952
return result.returncode
5053

5154

backends/ebpf/run-ebpf-test.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,9 @@ def __init__(self):
123123
self.replace = False # Replace previous outputs.
124124
self.target = "test" # The name of the target compiler.
125125
# Actual location of the test framework.
126-
self.testdir = str(FILE_DIR)
126+
self.testdir = FILE_DIR
127127
# The location of the eBPF runtime, some targets may overwrite this.
128-
self.runtimedir = str(FILE_DIR.joinpath("runtime"))
128+
self.runtimedir = FILE_DIR.joinpath("runtime")
129129
self.extern = "" # Path to C file with extern definition.
130130

131131

backends/ebpf/runtime/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
install
+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
libbpf
2+
bpftool

backends/ebpf/runtime/ebpf_kernel.h

+50-127
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,14 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
1817
/// This file contains all functions and definitions necessary for the kernel target C
1918
/// code to compile. It must be included with any file generated by the p4c-ebpf kernel
2019
/// compiler.
2120
#ifndef BACKENDS_EBPF_RUNTIME_EBPF_KERNEL_H_
2221
#define BACKENDS_EBPF_RUNTIME_EBPF_KERNEL_H_
2322

2423
#include "ebpf_common.h"
25-
26-
#include <bpf/bpf_endian.h> // definitions for bpf_ntohs etc...
24+
#include "install/libbpf/include/bpf/bpf_endian.h" // definitions for bpf_ntohs etc...
2725

2826
#undef htonl
2927
#undef htons
@@ -35,158 +33,83 @@ limitations under the License.
3533
#define bpf_htonll(x) htonll(x)
3634
#endif
3735

38-
#define load_byte(data, b) (*(((u8*)(data)) + (b)))
39-
#define load_half(data, b) bpf_ntohs(*(u16 *)((u8*)(data) + (b)))
40-
#define load_word(data, b) bpf_ntohl(*(u32 *)((u8*)(data) + (b)))
41-
#define load_dword(data, b) bpf_be64_to_cpu(*(u64 *)((u8*)(data) + (b)))
36+
#define load_byte(data, b) (*(((u8 *)(data)) + (b)))
37+
#define load_half(data, b) bpf_ntohs(*(u16 *)((u8 *)(data) + (b)))
38+
#define load_word(data, b) bpf_ntohl(*(u32 *)((u8 *)(data) + (b)))
39+
#define load_dword(data, b) bpf_be64_to_cpu(*(u64 *)((u8 *)(data) + (b)))
4240

4341
/// If we operate in user space we only need to include bpf.h and
4442
/// define the userspace API macros.
4543
/// For kernel programs we need to specify a list of kernel helpers. These are
46-
/// taken from here: https://github.com/torvalds/linux/blob/master/tools/lib/bpf/bpf_helpers.h
44+
/// taken from here: https://github.com/libbpf/libbpf/blob/master/src/bpf_helpers.h
4745

48-
#ifdef CONTROL_PLANE // BEGIN EBPF USER SPACE DEFINITIONS
46+
#ifdef CONTROL_PLANE // BEGIN EBPF USER SPACE DEFINITIONS
4947

50-
#include <bpf/bpf.h> // bpf_obj_get/pin, bpf_map_update_elem
48+
#include "install/libbpf/include/bpf/bpf.h" // bpf_obj_get/pin, bpf_map_update_elem
5149

52-
#define BPF_USER_MAP_UPDATE_ELEM(index, key, value, flags)\
50+
#define BPF_USER_MAP_UPDATE_ELEM(index, key, value, flags) \
5351
bpf_map_update_elem(index, key, value, flags)
5452
#define BPF_OBJ_PIN(table, name) bpf_obj_pin(table, name)
5553
#define BPF_OBJ_GET(name) bpf_obj_get(name)
5654

57-
#else // BEGIN EBPF KERNEL DEFINITIONS
55+
#else // BEGIN EBPF KERNEL DEFINITIONS
5856

57+
// These files are provided by the system, not libbpf.
58+
#include <linux/bpf.h> // BPF_ANY,
5959
#include <linux/pkt_cls.h> // TC_ACT_OK, TC_ACT_SHOT
60-
#include "linux/bpf.h" // types, and general bpf definitions
6160
// This file contains the definitions of all the kernel bpf essentials
62-
#include <bpf/bpf_helpers.h>
63-
64-
/// A helper structure used by an eBPF C program
65-
/// to describe map attributes for the elf_bpf loader
66-
/// FIXME: We only need this because we are loading with iproute2
67-
struct bpf_elf_map {
68-
__u32 type;
69-
__u32 size_key;
70-
__u32 size_value;
71-
__u32 max_elem;
72-
__u32 flags;
73-
__u32 id;
74-
__u32 pinning;
75-
__u32 inner_id;
76-
__u32 inner_idx;
77-
};
61+
#include "install/libbpf/include/bpf/bpf_helpers.h"
7862

7963
/// Simple descriptor which replaces the kernel sk_buff structure.
8064
#define SK_BUFF struct __sk_buff
8165

82-
/// From iproute2, annotate table with BTF which allows to read types at runtime.
83-
#define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \
84-
struct ____btf_map_##name { \
85-
type_key key; \
86-
type_val value; \
87-
}; \
88-
struct ____btf_map_##name \
89-
__attribute__ ((section(".maps." #name), used)) \
90-
____btf_map_##name = {};
91-
9266
#define REGISTER_START()
93-
#ifndef BTF
94-
/// Note: pinning exports the table name globally, do not remove.
95-
#define REGISTER_TABLE(NAME, TYPE, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES) \
96-
struct bpf_elf_map SEC("maps") NAME = { \
97-
.type = TYPE, \
98-
.size_key = sizeof(KEY_TYPE), \
99-
.size_value = sizeof(VALUE_TYPE), \
100-
.max_elem = MAX_ENTRIES, \
101-
.pinning = 2, \
102-
.flags = 0, \
103-
};
104-
#define REGISTER_TABLE_INNER(NAME, TYPE, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES, ID, INNER_IDX) \
105-
struct bpf_elf_map SEC("maps") NAME = { \
106-
.type = TYPE, \
107-
.size_key = sizeof(KEY_TYPE), \
108-
.size_value = sizeof(VALUE_TYPE), \
109-
.max_elem = MAX_ENTRIES, \
110-
.pinning = 2, \
111-
.flags = 0, \
112-
.id = ID, \
113-
.inner_idx = INNER_IDX, \
114-
};
115-
#define REGISTER_TABLE_OUTER(NAME, TYPE, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES, INNER_ID, INNER_NAME) \
116-
struct bpf_elf_map SEC("maps") NAME = { \
117-
.type = TYPE, \
118-
.size_key = sizeof(KEY_TYPE), \
119-
.size_value = sizeof(VALUE_TYPE), \
120-
.max_elem = MAX_ENTRIES, \
121-
.pinning = 2, \
122-
.flags = 0, \
123-
.inner_id = INNER_ID, \
124-
};
125-
#define REGISTER_TABLE_FLAGS(NAME, TYPE, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES, FLAGS) \
126-
struct bpf_elf_map SEC("maps") NAME = { \
127-
.type = TYPE, \
128-
.size_key = sizeof(KEY_TYPE), \
129-
.size_value = sizeof(VALUE_TYPE), \
130-
.max_elem = MAX_ENTRIES, \
131-
.pinning = 2, \
132-
.flags = FLAGS, \
133-
};
134-
#else
13567
#define REGISTER_TABLE(NAME, TYPE, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES) \
136-
struct { \
137-
__uint(type, TYPE); \
138-
KEY_TYPE *key; \
139-
VALUE_TYPE *value; \
140-
__uint(max_entries, MAX_ENTRIES); \
141-
__uint(pinning, LIBBPF_PIN_BY_NAME); \
142-
} NAME SEC(".maps");
68+
struct { \
69+
__uint(type, TYPE); \
70+
KEY_TYPE *key; \
71+
VALUE_TYPE *value; \
72+
__uint(max_entries, MAX_ENTRIES); \
73+
} NAME SEC(".maps");
14374
#define REGISTER_TABLE_FLAGS(NAME, TYPE, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES, FLAGS) \
144-
struct { \
145-
__uint(type, TYPE); \
146-
KEY_TYPE *key; \
147-
VALUE_TYPE *value; \
148-
__uint(max_entries, MAX_ENTRIES); \
149-
__uint(pinning, LIBBPF_PIN_BY_NAME); \
150-
__uint(map_flags, FLAGS); \
151-
} NAME SEC(".maps");
75+
struct { \
76+
__uint(type, TYPE); \
77+
KEY_TYPE *key; \
78+
VALUE_TYPE *value; \
79+
__uint(max_entries, MAX_ENTRIES); \
80+
__uint(map_flags, FLAGS); \
81+
} NAME SEC(".maps");
15282
#define REGISTER_TABLE_INNER(NAME, TYPE, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES, ID, INNER_IDX) \
153-
struct NAME { \
154-
__uint(type, TYPE); \
155-
KEY_TYPE *key; \
156-
VALUE_TYPE *value; \
157-
__uint(max_entries, MAX_ENTRIES); \
158-
} NAME SEC(".maps");
83+
struct NAME { \
84+
__uint(type, TYPE); \
85+
KEY_TYPE *key; \
86+
VALUE_TYPE *value; \
87+
__uint(max_entries, MAX_ENTRIES); \
88+
} NAME SEC(".maps");
15989
#define REGISTER_TABLE_OUTER(NAME, TYPE, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES, INNER_ID, INNER_NAME) \
160-
struct { \
161-
__uint(type, TYPE); \
162-
KEY_TYPE *key; \
163-
VALUE_TYPE *value; \
164-
__uint(max_entries, MAX_ENTRIES); \
165-
__uint(pinning, LIBBPF_PIN_BY_NAME); \
166-
__array(values, struct INNER_NAME); \
167-
} NAME SEC(".maps");
90+
struct { \
91+
__uint(type, TYPE); \
92+
KEY_TYPE *key; \
93+
VALUE_TYPE *value; \
94+
__uint(max_entries, MAX_ENTRIES); \
95+
__array(values, struct INNER_NAME); \
96+
} NAME SEC(".maps") = {.values = {&INNER_NAME}};
16897
#define REGISTER_TABLE_NO_KEY_TYPE(NAME, TYPE, KEY_SIZE, VALUE_TYPE, MAX_ENTRIES) \
169-
struct { \
170-
__uint(type, TYPE); \
171-
__uint(key_size, KEY_SIZE); \
172-
VALUE_TYPE *value; \
173-
__uint(max_entries, MAX_ENTRIES); \
174-
__uint(pinning, LIBBPF_PIN_BY_NAME); \
175-
} NAME SEC(".maps");
176-
#endif
98+
struct { \
99+
__uint(type, TYPE); \
100+
__uint(key_size, KEY_SIZE); \
101+
VALUE_TYPE *value; \
102+
__uint(max_entries, MAX_ENTRIES); \
103+
} NAME SEC(".maps");
177104
#define REGISTER_END()
178105

179-
#define BPF_MAP_LOOKUP_ELEM(table, key) \
180-
bpf_map_lookup_elem(&table, key)
181-
#define BPF_MAP_UPDATE_ELEM(table, key, value, flags) \
182-
bpf_map_update_elem(&table, key, value, flags)
183-
#define BPF_MAP_DELETE_ELEM(table, key) \
184-
bpf_map_delete_elem(&table, key)
185-
#define BPF_USER_MAP_UPDATE_ELEM(index, key, value, flags)\
186-
bpf_update_elem(index, key, value, flags)
106+
#define BPF_MAP_LOOKUP_ELEM(table, key) bpf_map_lookup_elem(&table, key)
107+
#define BPF_MAP_UPDATE_ELEM(table, key, value, flags) bpf_map_update_elem(&table, key, value, flags)
108+
#define BPF_MAP_DELETE_ELEM(table, key) bpf_map_delete_elem(&table, key)
109+
#define BPF_USER_MAP_UPDATE_ELEM(index, key, value, flags) bpf_update_elem(index, key, value, flags)
187110
#define BPF_OBJ_PIN(table, name) bpf_obj_pin(table, name)
188111
#define BPF_OBJ_GET(name) bpf_obj_get(name)
189112

190-
#endif // END EBPF KERNEL DEFINITIONS
113+
#endif // END EBPF KERNEL DEFINITIONS
191114

192115
#endif // BACKENDS_EBPF_RUNTIME_EBPF_KERNEL_H_

backends/ebpf/runtime/kernel.mk

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ ROOT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
33
# Argument for the CLANG compiler
44
LLC ?= llc
55
CLANG ?= clang
6-
override INCLUDES+= -I$(ROOT_DIR) -I$(ROOT_DIR)usr/include/ -I$(ROOT_DIR)contrib/libbpf/include/uapi/
6+
override INCLUDES+= -I$(ROOT_DIR)
77
override LIBS+=
88
# Optimization flags to save space
99
override CFLAGS+= -O2 -g -c -D__KERNEL__ -D__ASM_SYSREG_H \

backends/ebpf/target.cpp

-9
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ void KernelSamplesTarget::emitTableDecl(Util::SourceCodeBuilder *builder, cstrin
9898
flags);
9999
}
100100
builder->newline();
101-
annotateTableWithBTF(builder, tblName, keyType, valueType);
102101
}
103102

104103
void KernelSamplesTarget::emitTableDeclSpinlock(Util::SourceCodeBuilder *builder, cstring tblName,
@@ -131,14 +130,12 @@ void KernelSamplesTarget::emitMapInMapDecl(Util::SourceCodeBuilder *builder, cst
131130
builder->appendFormat(registerInnerTable, innerName, kind, innerKeyType, innerValueType,
132131
innerSize, innerMapIndex, innerMapIndex);
133132
builder->newline();
134-
annotateTableWithBTF(builder, innerName, innerKeyType, innerValueType);
135133

136134
kind = getBPFMapType(outerTableKind);
137135
cstring keyType = outerTableKind == TableArray ? "__u32"_cs : outerKeyType;
138136
builder->appendFormat(registerOuterTable, outerName, kind, keyType, "__u32", outerSize,
139137
innerMapIndex, innerName);
140138
builder->newline();
141-
annotateTableWithBTF(builder, outerName, keyType, "__u32"_cs);
142139
}
143140

144141
void KernelSamplesTarget::emitLicense(Util::SourceCodeBuilder *builder, cstring license) const {
@@ -202,12 +199,6 @@ void KernelSamplesTarget::emitTraceMessage(Util::SourceCodeBuilder *builder, con
202199
builder->newline();
203200
}
204201

205-
void KernelSamplesTarget::annotateTableWithBTF(Util::SourceCodeBuilder *builder, cstring name,
206-
cstring keyType, cstring valueType) const {
207-
builder->appendFormat("BPF_ANNOTATE_KV_PAIR(%v, %v, %v)", name, keyType, valueType);
208-
builder->newline();
209-
}
210-
211202
//////////////////////////////////////////////////////////////
212203
void XdpTarget::emitResizeBuffer(Util::SourceCodeBuilder *builder, cstring buffer,
213204
cstring offsetVar) const {

backends/ebpf/target.h

-3
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,6 @@ class KernelSamplesTarget : public Target {
195195
cstring sysMapPath() const override { return "/sys/fs/bpf/tc/globals"_cs; }
196196

197197
cstring packetDescriptorType() const override { return "struct __sk_buff"_cs; }
198-
199-
void annotateTableWithBTF(Util::SourceCodeBuilder *builder, cstring name, cstring keyType,
200-
cstring valueType) const;
201198
};
202199

203200
class P4TCTarget : public KernelSamplesTarget {

backends/ebpf/targets/ebpfenv.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def ns_proc_append(self, proc: subprocess.Popen, cmd: str) -> int:
9696
def ns_proc_close(self, proc: subprocess.Popen, **extra_args: Any) -> int:
9797
"""Close and actually run the process in the namespace. Returns the
9898
exit code."""
99-
testutils.log.info("Executing command: %s", proc)
99+
testutils.log.info("Executing command: %s", proc.args)
100100
result = testutils.run_process(proc, timeout=testutils.TIMEOUT, **extra_args)
101101
if result.returncode != testutils.SUCCESS:
102102
testutils.log.error(
@@ -109,7 +109,7 @@ def _configure_bridge(self, br_name: str) -> int:
109109
avoid ICMPv6 spam."""
110110
# We do not care about failures here
111111
self.ns_exec(f"ip link set dev {br_name} up")
112-
self.ns_exec(f"ip link set dev {br_name} mtu 9000")
112+
self.ns_exec(f"ip link set dev {br_name} mtu 1500")
113113
# Prevent the broadcasting of ipv6 link discovery messages
114114
self.ns_exec("sysctl -w net.ipv6.conf.all.disable_ipv6=1")
115115
self.ns_exec("sysctl -w net.ipv6.conf.default.disable_ipv6=1")
@@ -130,7 +130,7 @@ def _configure_bridge_port(self, port_name: str) -> int:
130130
result = self.ns_exec(cmd)
131131
if result != testutils.SUCCESS:
132132
return result
133-
cmd = f"ip link set dev {port_name} mtu 9000"
133+
cmd = f"ip link set dev {port_name} mtu 1500"
134134
return self.ns_exec(cmd)
135135

136136
def attach_interfaces(self, num_ifaces: int) -> int:

0 commit comments

Comments
 (0)