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");