Skip to content

Commit

Permalink
Revert.
Browse files Browse the repository at this point in the history
Signed-off-by: fruffy <[email protected]>
  • Loading branch information
fruffy committed Dec 24, 2024
1 parent fbc2432 commit 990a11b
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 58 deletions.
2 changes: 1 addition & 1 deletion backends/ebpf/ebpfProgram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ void EBPFProgram::emitC(CodeBuilder *builder, const std::filesystem::path &heade
if (model.arch == ModelArchitecture::XdpSwitch)
builder->target->emitCodeSection(builder, "xdp"_cs);
else
builder->target->emitCodeSection(builder, "prog"_cs);
builder->target->emitCodeSection(builder, "tc"_cs);
builder->emitIndent();
builder->target->emitMain(builder, functionName, model.CPacketName.toString());
builder->blockStart();
Expand Down
50 changes: 31 additions & 19 deletions backends/ebpf/runtime/ebpf_kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License.
*/


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

#include "ebpf_common.h"

#include "install/libbpf/include/bpf/bpf_endian.h" // definitions for bpf_ntohs etc...

#undef htonl
Expand All @@ -33,83 +35,93 @@ limitations under the License.
#define bpf_htonll(x) htonll(x)
#endif

#define load_byte(data, b) (*(((u8 *)(data)) + (b)))
#define load_half(data, b) bpf_ntohs(*(u16 *)((u8 *)(data) + (b)))
#define load_word(data, b) bpf_ntohl(*(u32 *)((u8 *)(data) + (b)))
#define load_dword(data, b) bpf_be64_to_cpu(*(u64 *)((u8 *)(data) + (b)))
#define load_byte(data, b) (*(((u8*)(data)) + (b)))
#define load_half(data, b) bpf_ntohs(*(u16 *)((u8*)(data) + (b)))
#define load_word(data, b) bpf_ntohl(*(u32 *)((u8*)(data) + (b)))
#define load_dword(data, b) bpf_be64_to_cpu(*(u64 *)((u8*)(data) + (b)))

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

#ifdef CONTROL_PLANE // BEGIN EBPF USER SPACE DEFINITIONS
#ifdef CONTROL_PLANE // BEGIN EBPF USER SPACE DEFINITIONS

#include "install/libbpf/include/bpf/bpf.h" // bpf_obj_get/pin, bpf_map_update_elem

#define BPF_USER_MAP_UPDATE_ELEM(index, key, value, flags) \
#define BPF_USER_MAP_UPDATE_ELEM(index, key, value, flags)\
bpf_map_update_elem(index, key, value, flags)
#define BPF_OBJ_PIN(table, name) bpf_obj_pin(table, name)
#define BPF_OBJ_GET(name) bpf_obj_get(name)

#else // BEGIN EBPF KERNEL DEFINITIONS
#else // BEGIN EBPF KERNEL DEFINITIONS

// These files are provided by the system, not libbpf.
#include <linux/bpf.h> // BPF_ANY,
#include <linux/bpf.h> // BPF_ANY,
#include <linux/pkt_cls.h> // TC_ACT_OK, TC_ACT_SHOT
// This file contains the definitions of all the kernel bpf essentials
#include "install/libbpf/include/bpf/bpf_helpers.h"
#include "install/libbpf/include/bpf/btf.h"

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


#define REGISTER_START()
#define REGISTER_TABLE(NAME, TYPE, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES) \
struct { \
__uint(type, TYPE); \
KEY_TYPE *key; \
VALUE_TYPE *value; \
__uint(pinning, LIBBPF_PIN_BY_NAME); \
__uint(max_entries, MAX_ENTRIES); \
} NAME SEC(".maps");
} NAME SEC(MAPS_ELF_SEC);
#define REGISTER_TABLE_FLAGS(NAME, TYPE, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES, FLAGS) \
struct { \
__uint(type, TYPE); \
KEY_TYPE *key; \
VALUE_TYPE *value; \
__uint(max_entries, MAX_ENTRIES); \
__uint(pinning, LIBBPF_PIN_BY_NAME); \
__uint(map_flags, FLAGS); \
} NAME SEC(".maps");
} NAME SEC(MAPS_ELF_SEC);
#define REGISTER_TABLE_INNER(NAME, TYPE, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES, ID, INNER_IDX) \
struct NAME { \
__uint(type, TYPE); \
KEY_TYPE *key; \
VALUE_TYPE *value; \
__uint(max_entries, MAX_ENTRIES); \
} NAME SEC(".maps");
} NAME SEC(MAPS_ELF_SEC);
#define REGISTER_TABLE_OUTER(NAME, TYPE, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES, INNER_ID, INNER_NAME) \
struct { \
__uint(type, TYPE); \
KEY_TYPE *key; \
VALUE_TYPE *value; \
__uint(max_entries, MAX_ENTRIES); \
__uint(pinning, LIBBPF_PIN_BY_NAME); \
__array(values, struct INNER_NAME); \
} NAME SEC(".maps") = {.values = {&INNER_NAME}};
} NAME SEC(MAPS_ELF_SEC) = {.values = {&INNER_NAME}};
#define REGISTER_TABLE_NO_KEY_TYPE(NAME, TYPE, KEY_SIZE, VALUE_TYPE, MAX_ENTRIES) \
struct { \
__uint(type, TYPE); \
__uint(key_size, KEY_SIZE); \
VALUE_TYPE *value; \
__uint(pinning, LIBBPF_PIN_BY_NAME); \
__uint(max_entries, MAX_ENTRIES); \
} NAME SEC(".maps");
} NAME SEC(MAPS_ELF_SEC);
#define REGISTER_END()

#define BPF_MAP_LOOKUP_ELEM(table, key) bpf_map_lookup_elem(&table, key)
#define BPF_MAP_UPDATE_ELEM(table, key, value, flags) bpf_map_update_elem(&table, key, value, flags)
#define BPF_MAP_DELETE_ELEM(table, key) bpf_map_delete_elem(&table, key)
#define BPF_USER_MAP_UPDATE_ELEM(index, key, value, flags) bpf_update_elem(index, key, value, flags)
#define BPF_MAP_LOOKUP_ELEM(table, key) \
bpf_map_lookup_elem(&table, key)
#define BPF_MAP_UPDATE_ELEM(table, key, value, flags) \
bpf_map_update_elem(&table, key, value, flags)
#define BPF_MAP_DELETE_ELEM(table, key) \
bpf_map_delete_elem(&table, key)
#define BPF_USER_MAP_UPDATE_ELEM(index, key, value, flags)\
bpf_update_elem(index, key, value, flags)
#define BPF_OBJ_PIN(table, name) bpf_obj_pin(table, name)
#define BPF_OBJ_GET(name) bpf_obj_get(name)

#endif // END EBPF KERNEL DEFINITIONS
#endif // END EBPF KERNEL DEFINITIONS

#endif // BACKENDS_EBPF_RUNTIME_EBPF_KERNEL_H_
97 changes: 65 additions & 32 deletions backends/ebpf/targets/kernel_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,43 +122,76 @@ def _kill_processes(self, procs) -> None:
# kill process, 15 is SIGTERM
os.kill(proc.pid, 15)

def _attach_filters(self, bridge: Bridge, proc: subprocess.Popen) -> int:
# Is this a XDP or TC (ebpf_filter) program?
p_result = testutils.exec_process(f"objdump -hj xdp {self.template}.o").returncode
is_xdp = p_result == testutils.SUCCESS

def _load_filter(self, bridge, proc, port_name):
# Load the specified eBPF object to "port_name" egress
# As a side-effect, this may create maps in /sys/fs/bpf/
# Get the command to load eBPF code to all the attached ports
result = bridge.ns_proc_write(proc, f"mount -t bpf none {self.EBPF_PATH}")
if result != testutils.SUCCESS:
return result
result = bridge.ns_proc_append(proc, f"mkdir -p {self.ebpf_map_path}")
if result != testutils.SUCCESS:
return result
load_type = "xdp" if is_xdp else "tc"
cmd = f"{self.bpftool} prog load {self.template}.o {self.EBPF_PATH}/ebpf_filter pinmaps {self.ebpf_map_path} type {load_type}"
result = bridge.ns_proc_append(proc, cmd)
if result != testutils.SUCCESS:
return result

attach_type = "xdp" if is_xdp else "tcx_egress"
ports = bridge.br_ports if is_xdp else bridge.edge_ports
if len(ports) > 0:
for port_name in ports:
result = bridge.ns_proc_append(
proc,
f"{self.bpftool} net attach {attach_type} pinned {self.EBPF_PATH}/ebpf_filter dev {port_name}",
)
if result != testutils.SUCCESS:
return result
# Is this a XDP or TC (ebpf_filter) program?
result = testutils.exec_process(f"objdump -hj xdp {self.template}.o")
if result.returncode == testutils.SUCCESS:
# NB: XDP programs attach to the Rx end (but TC below attaches to Tx).
cmd = f"ip link set br_{port_name} xdpgeneric obj {self.template}.o sec xdp"
else:
# No ports attached (no pcap files), load to bridge instead
result = bridge.ns_proc_append(
proc,
f"{self.bpftool} net attach {attach_type} pinned {self.EBPF_PATH}/ebpf_filter dev {bridge.br_name}",
# Add the qdisc. MUST be clsact layer.
bridge.ns_exec(f"tc qdisc add dev {port_name} clsact")
cmd = (
f"tc filter add dev {port_name} egress"
f" bpf da obj {self.template}.o section tc verbose "
)
return bridge.ns_proc_write(proc, cmd)

return result
def _attach_filters(self, bridge, proc):
# Get the command to load eBPF code to all the attached ports
if len(bridge.edge_ports) > 0:
for port in bridge.edge_ports:
result = self._load_filter(bridge, proc, port)
bridge.ns_proc_append(proc, "")
else:
# No ports attached (no pcap files), load to bridge instead
result = self._load_filter(bridge, proc, bridge.br_name)
bridge.ns_proc_append(proc, "")
if result != testutils.SUCCESS:
return result
return testutils.SUCCESS

# def _attach_filters(self, bridge: Bridge, proc: subprocess.Popen) -> int:
# # Is this a XDP or TC (ebpf_filter) program?
# p_result = testutils.exec_process(f"objdump -hj xdp {self.template}.o").returncode
# is_xdp = p_result == testutils.SUCCESS
# # Load the specified eBPF object to "port_name" egress
# # As a side-effect, this may create maps in /sys/fs/bpf/
# # Get the command to load eBPF code to all the attached ports
# result = bridge.ns_proc_write(proc, f"mount -t bpf none {self.EBPF_PATH}")
# if result != testutils.SUCCESS:
# return result
# result = bridge.ns_proc_append(proc, f"mkdir -p {self.ebpf_map_path}")
# if result != testutils.SUCCESS:
# return result
# load_type = "xdp" if is_xdp else "tc"
# cmd = f"{self.bpftool} prog load {self.template}.o {self.EBPF_PATH}/ebpf_filter pinmaps {self.ebpf_map_path} type {load_type}"
# result = bridge.ns_proc_append(proc, cmd)
# if result != testutils.SUCCESS:
# return result

# attach_type = "xdp" if is_xdp else "tcx_egress"
# ports = bridge.br_ports if is_xdp else bridge.edge_ports
# if len(ports) > 0:
# for port_name in ports:
# result = bridge.ns_proc_append(
# proc,
# f"{self.bpftool} net attach {attach_type} pinned {self.EBPF_PATH}/ebpf_filter dev {port_name}",
# )
# if result != testutils.SUCCESS:
# return result
# else:
# # No ports attached (no pcap files), load to bridge instead
# result = bridge.ns_proc_append(
# proc,
# f"{self.bpftool} net attach {attach_type} pinned {self.EBPF_PATH}/ebpf_filter dev {bridge.br_name}",
# )

# return result

def _run_tcpdump(self, bridge, filename, port):
cmd = f"{bridge.get_ns_prefix()} tcpdump -w {filename} -i {port}"
Expand All @@ -184,7 +217,7 @@ def _run_in_namespace(self, bridge):
if result != testutils.SUCCESS:
return result
# Finally, append the actual runtime command to the process
result = bridge.ns_proc_append(proc, self._get_run_cmd())
result = bridge.ns_proc_write(proc, self._get_run_cmd())
if result != testutils.SUCCESS:
return result
# Execute the command queue and close the process, retrieve result
Expand Down
7 changes: 1 addition & 6 deletions tools/ci-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,7 @@ function build_ebpf() {
iproute2 \
iptables \
net-tools"

if [[ "${DISTRIB_RELEASE}" == "18.04" || "${DISTRIB_RELEASE}" == "20.04" ]] ; then
P4C_EBPF_DEPS+=" libllvm-12-ocaml-dev libllvm12 llvm-12 llvm-12-dev llvm-12-doc llvm-12-examples llvm-12-runtime clang-12 clang-tools-12 clang-12-doc libclang-common-12-dev libclang-12-dev clang-format-12 clang-tidy-12 "
else
P4C_EBPF_DEPS+=" llvm clang "
fi
P4C_EBPF_DEPS+=" llvm clang "
sudo apt-get install -y --no-install-recommends ${P4C_EBPF_DEPS}
}

Expand Down

0 comments on commit 990a11b

Please sign in to comment.