From 90b81ac174111790dd7af5a018e0b03b8bfbbbe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Sun, 7 Mar 2021 06:48:26 -0800 Subject: [PATCH] ebpf offload - beginnings of xdp implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test: TreeHugger Signed-off-by: Maciej Żenczykowski Change-Id: I6956e78bd325b63dc6dc813440f9f80c29aada36 --- Tethering/bpf_progs/offload.c | 50 ++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/Tethering/bpf_progs/offload.c b/Tethering/bpf_progs/offload.c index 4ca1b5735a..7f9754d896 100644 --- a/Tethering/bpf_progs/offload.c +++ b/Tethering/bpf_progs/offload.c @@ -755,27 +755,69 @@ DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_upstream4_ether$stub", AID_ROOT, AID DEFINE_BPF_MAP_GRW(tether_xdp_devmap, DEVMAP_HASH, uint32_t, uint32_t, 64, AID_NETWORK_STACK) +static inline __always_inline int do_xdp_forward6(struct xdp_md *ctx, const bool is_ethernet, + const bool downstream) { + return XDP_PASS; +} + +static inline __always_inline int do_xdp_forward4(struct xdp_md *ctx, const bool is_ethernet, + const bool downstream) { + return XDP_PASS; +} + +static inline __always_inline int do_xdp_forward_ether(struct xdp_md *ctx, const bool downstream) { + const void* data = (void*)(long)ctx->data; + const void* data_end = (void*)(long)ctx->data_end; + const struct ethhdr* eth = data; + + // Make sure we actually have an ethernet header + if ((void*)(eth + 1) > data_end) return XDP_PASS; + + if (eth->h_proto == htons(ETH_P_IPV6)) + return do_xdp_forward6(ctx, /* is_ethernet */ true, downstream); + if (eth->h_proto == htons(ETH_P_IP)) + return do_xdp_forward4(ctx, /* is_ethernet */ true, downstream); + + // Anything else we don't know how to handle... + return XDP_PASS; +} + +static inline __always_inline int do_xdp_forward_rawip(struct xdp_md *ctx, const bool downstream) { + const void* data = (void*)(long)ctx->data; + const void* data_end = (void*)(long)ctx->data_end; + + // The top nibble of both IPv4 and IPv6 headers is the IP version. + if (data_end - data < 1) return XDP_PASS; + const uint8_t v = (*(uint8_t*)data) >> 4; + + if (v == 6) return do_xdp_forward6(ctx, /* is_ethernet */ false, downstream); + if (v == 4) return do_xdp_forward4(ctx, /* is_ethernet */ false, downstream); + + // Anything else we don't know how to handle... + return XDP_PASS; +} + #define DEFINE_XDP_PROG(str, func) \ DEFINE_BPF_PROG_KVER(str, AID_ROOT, AID_NETWORK_STACK, func, KVER(5, 9, 0))(struct xdp_md *ctx) DEFINE_XDP_PROG("xdp/tether_downstream_ether", xdp_tether_downstream_ether) { - return XDP_PASS; + return do_xdp_forward_ether(ctx, /* downstream */ true); } DEFINE_XDP_PROG("xdp/tether_downstream_rawip", xdp_tether_downstream_rawip) { - return XDP_PASS; + return do_xdp_forward_rawip(ctx, /* downstream */ true); } DEFINE_XDP_PROG("xdp/tether_upstream_ether", xdp_tether_upstream_ether) { - return XDP_PASS; + return do_xdp_forward_ether(ctx, /* downstream */ false); } DEFINE_XDP_PROG("xdp/tether_upstream_rawip", xdp_tether_upstream_rawip) { - return XDP_PASS; + return do_xdp_forward_rawip(ctx, /* downstream */ false); } LICENSE("Apache 2.0");