clatd bpf - add try_make_readable() of the ethernet/ip header
We now rely on the skb->mark = 0xDeadC1a7 setting side effect
for non offloadable packets, but for this to work reliably,
we *must* be able to read the ip header.
Test: TreeHugger, and on a gs101-based pixel
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: Ic2b15335099404047d136a92ce7aeeb1f11ccfa3
diff --git a/bpf_progs/clatd.c b/bpf_progs/clatd.c
index 55165b1..8971f6b 100644
--- a/bpf_progs/clatd.c
+++ b/bpf_progs/clatd.c
@@ -46,18 +46,24 @@
DEFINE_BPF_MAP_GRW(clat_ingress6_map, HASH, ClatIngress6Key, ClatIngress6Value, 16, AID_SYSTEM)
static inline __always_inline int nat64(struct __sk_buff* skb, bool is_ethernet) {
- const int l2_header_size = is_ethernet ? sizeof(struct ethhdr) : 0;
- void* data = (void*)(long)skb->data;
- const void* data_end = (void*)(long)skb->data_end;
- const struct ethhdr* const eth = is_ethernet ? data : NULL; // used iff is_ethernet
- const struct ipv6hdr* const ip6 = is_ethernet ? (void*)(eth + 1) : data;
-
// Require ethernet dst mac address to be our unicast address.
if (is_ethernet && (skb->pkt_type != PACKET_HOST)) return TC_ACT_PIPE;
// Must be meta-ethernet IPv6 frame
if (skb->protocol != htons(ETH_P_IPV6)) return TC_ACT_PIPE;
+ const int l2_header_size = is_ethernet ? sizeof(struct ethhdr) : 0;
+
+ // Not clear if this is actually necessary considering we use DPA (Direct Packet Access),
+ // but we need to make sure we can read the IPv6 header reliably so that we can set
+ // skb->mark = 0xDeadC1a7 for packets we fail to offload.
+ try_make_readable(skb, l2_header_size + sizeof(struct ipv6hdr));
+
+ void* data = (void*)(long)skb->data;
+ const void* data_end = (void*)(long)skb->data_end;
+ const struct ethhdr* const eth = is_ethernet ? data : NULL; // used iff is_ethernet
+ const struct ipv6hdr* const ip6 = is_ethernet ? (void*)(eth + 1) : data;
+
// Must have (ethernet and) ipv6 header
if (data + l2_header_size + sizeof(*ip6) > data_end) return TC_ACT_PIPE;
@@ -214,13 +220,16 @@
DEFINE_BPF_PROG("schedcls/egress4/clat_rawip", AID_ROOT, AID_SYSTEM, sched_cls_egress4_clat_rawip)
(struct __sk_buff* skb) {
+ // Must be meta-ethernet IPv4 frame
+ if (skb->protocol != htons(ETH_P_IP)) return TC_ACT_PIPE;
+
+ // Possibly not needed, but for consistency with nat64 up above
+ try_make_readable(skb, sizeof(struct iphdr));
+
void* data = (void*)(long)skb->data;
const void* data_end = (void*)(long)skb->data_end;
const struct iphdr* const ip4 = data;
- // Must be meta-ethernet IPv4 frame
- if (skb->protocol != htons(ETH_P_IP)) return TC_ACT_PIPE;
-
// Must have ipv4 header
if (data + sizeof(*ip4) > data_end) return TC_ACT_PIPE;