From 2214635f05b664af7d5cde440a747b770541a755 Mon Sep 17 00:00:00 2001 From: Ric Li Date: Fri, 26 Jan 2024 14:56:54 +0800 Subject: [PATCH] manager: use built-in xdp prog Signed-off-by: Ric Li --- manager/gen_skel.sh | 7 ++++ manager/manager.xdp.c | 70 +++++++++++++++++++++++++++++++++++++++ manager/meson.build | 13 ++++++-- manager/mtl_interface.hpp | 50 ++++++++++++++++------------ 4 files changed, 115 insertions(+), 25 deletions(-) create mode 100644 manager/gen_skel.sh create mode 100644 manager/manager.xdp.c diff --git a/manager/gen_skel.sh b/manager/gen_skel.sh new file mode 100644 index 000000000..d0b6cb878 --- /dev/null +++ b/manager/gen_skel.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +cp $1/manager.xdp.c . + +clang -g -O2 -target bpf -c manager.xdp.c -o manager.xdp.o +llvm-strip -g manager.xdp.o +bpftool gen skeleton manager.xdp.o > xdp.skel.h diff --git a/manager/manager.xdp.c b/manager/manager.xdp.c new file mode 100644 index 000000000..0985ecf76 --- /dev/null +++ b/manager/manager.xdp.c @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + * Copyright(c) 2023 Intel Corporation + */ + +//clang-format off +#include +//clang-format off + +#include +#include +#include + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 65536); + __type(key, int); + __type(value, int); +} udp4_dp_filter SEC(".maps"); + +#define DEFAULT_QUEUE_IDS 64 + +struct { + __uint(type, BPF_MAP_TYPE_XSKMAP); + __uint(key_size, sizeof(int)); + __uint(value_size, sizeof(int)); + __uint(max_entries, DEFAULT_QUEUE_IDS); +} xsks_map SEC(".maps"); + +volatile int refcnt = 1; + +static int __always_inline lookup_udp4_dp(int dp) { + int* value; + + value = bpf_map_lookup_elem(&udp4_dp_filter, &dp); + if (value && *value != 0) return 1; + return 0; +} + +SEC("xdp") +int xsk_def_prog(struct xdp_md* ctx) { + if (!refcnt) return XDP_PASS; + + void* data_end = (void*)(long)ctx->data_end; + void* data = (void*)(long)ctx->data; + + struct hdr_cursor nh; + struct ethhdr* eth; + int eth_type; + + nh.pos = data; + eth_type = parse_ethhdr(&nh, data_end, ð); + if (eth_type != bpf_htons(ETH_P_IP)) return XDP_PASS; + + struct iphdr* iphdr; + int ip_type; + ip_type = parse_iphdr(&nh, data_end, &iphdr); + if (ip_type != IPPROTO_UDP) return XDP_PASS; + + struct udphdr* udphdr; + int ret; + ret = parse_udphdr(&nh, data_end, &udphdr); + if (ret < 0) return XDP_PASS; + + int dst_port = bpf_ntohs(udphdr->dest); + if (lookup_udp4_dp(dst_port) == 0) return XDP_PASS; + + return bpf_redirect_map(&xsks_map, ctx->rx_queue_index, XDP_PASS); +} diff --git a/manager/meson.build b/manager/meson.build index be1bf6db0..6370246f4 100644 --- a/manager/meson.build +++ b/manager/meson.build @@ -1,7 +1,7 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright 2023 Intel Corporation -project('mtl_manager', 'cpp', default_options: ['buildtype=release', 'cpp_std=c++17']) +project('mtl_manager', 'cpp', default_options: ['buildtype=release', 'cpp_std=c++17'], version: '0.2.0') exec_env = host_machine.system() set_variable('is_windows', exec_env == 'windows') @@ -15,8 +15,6 @@ message('BUILD Environment: ' + exec_env) cpp_c = meson.get_compiler('cpp') -sources = ['mtl_manager.cpp'] - cpp_args = ['-std=c++17', '-Wall'] link_cpp_args = ['-lstdc++fs'] @@ -41,6 +39,15 @@ else message('libxdp and libbpf not found, no af_xdp backend') endif +# Generate XDP prog code +gen_skel = find_program('gen_skel.sh') +sekl = custom_target('skeleton', + output : ['xdp.skel.h'], + input : ['manager.xdp.c'], + command : [gen_skel] + meson.current_source_dir()) + +sources = ['mtl_manager.cpp', sekl] + executable('MtlManager', sources, cpp_args: cpp_args, link_args: link_cpp_args, diff --git a/manager/mtl_interface.hpp b/manager/mtl_interface.hpp index bceb8203c..cfc3ab701 100644 --- a/manager/mtl_interface.hpp +++ b/manager/mtl_interface.hpp @@ -9,6 +9,8 @@ #include #include #include + +#include "xdp.skel.h" #endif #include @@ -136,34 +138,39 @@ int mtl_interface::clear_flow_rules() { #ifdef MTL_HAS_XDP_BACKEND int mtl_interface::load_xdp() { - /* get xdp prog path from env or use manager default path */ - std::string xdp_prog_path; - char* xdp_prog_path_env = getenv("MTL_XDP_PROG_PATH"); - if (xdp_prog_path_env != nullptr) { - xdp_prog_path = xdp_prog_path_env; - } else { - xdp_prog_path = "/tmp/imtl/xdp_prog.o"; - } + /* get customized xdp prog path from env */ + std::string xdp_prog_path = getenv("MTL_XDP_PROG_PATH"); if (!std::filesystem::is_regular_file(xdp_prog_path)) { log(log_level::WARNING, - "Fallback to use libxdp default prog for " + xdp_prog_path + " is not valid."); + "Fallback to use built-in prog for " + xdp_prog_path + " is not valid."); } else { xdp_prog = xdp_program__open_file(xdp_prog_path.c_str(), NULL, NULL); if (libxdp_get_error(xdp_prog)) { - log(log_level::WARNING, - "Fallback to use libxdp default prog for " + xdp_prog_path + " cannot load."); + log(log_level::WARNING, "Fallback to use built-in prog prog for " + xdp_prog_path + + " cannot be loaded."); xdp_prog = nullptr; - } else { - if (xdp_program__attach(xdp_prog, ifindex, XDP_MODE_NATIVE, 0) < 0) { - log(log_level::WARNING, - "Failed to attach XDP program with native mode, try skb mode."); - if (xdp_program__attach(xdp_prog, ifindex, XDP_MODE_SKB, 0) < 0) { - log(log_level::ERROR, "Failed to attach XDP program " + xdp_prog_path); - xdp_program__close(xdp_prog); - return -1; - } - } + } + } + + if (xdp_prog == nullptr) { + /* load built-in xdp prog from skeleton */ + xdp_prog_path = ""; + struct manager_xdp* skel = manager_xdp__open(); + if (!skel) { + log(log_level::ERROR, "Failed to open built-in xdp prog skeleton"); + return -1; + } + xdp_prog = xdp_program__from_bpf_obj(skel->obj, "xdp"); + } + + if (xdp_program__attach(xdp_prog, ifindex, XDP_MODE_NATIVE, 0) < 0) { + log(log_level::WARNING, + "Failed to attach XDP program with native mode, try skb mode."); + if (xdp_program__attach(xdp_prog, ifindex, XDP_MODE_SKB, 0) < 0) { + log(log_level::ERROR, "Failed to attach XDP program " + xdp_prog_path); + xdp_program__close(xdp_prog); + return -1; } } @@ -183,7 +190,6 @@ int mtl_interface::load_xdp() { return -1; } - if (xdp_prog == nullptr) xdp_prog_path = ""; log(log_level::INFO, "Loaded xdp prog " + xdp_prog_path); return 0; }