Add a new BPF kfunc, bpf_skb_rx_checksum(), that allows TC and other
skb-attached BPF programs to read the skb->ip_summed field and
associated checksum metadata. This is needed because the existing
bpf_csum_level() helper only distinguishes CHECKSUM_UNNECESSARY
from all other states, making it unsuitable when the caller needs
to differentiate CHECKSUM_NONE from CHECKSUM_COMPLETE (e.g. after
XDP_PASS where the driver may have set either).
The kfunc writes two output values:
- ip_summed: the raw skb->ip_summed value
(CHECKSUM_NONE=0, CHECKSUM_UNNECESSARY=1,
CHECKSUM_COMPLETE=2, CHECKSUM_PARTIAL=3)
- csum_meta: CHECKSUM_COMPLETE -> hardware checksum (skb->csum)
CHECKSUM_UNNECESSARY -> checksum level (skb->csum_level)
otherwise -> 0
Signed-off-by: Lorenzo Bianconi <[email protected]>
---
net/core/filter.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/net/core/filter.c b/net/core/filter.c
index b446aa8be5c3..71d58ea53512 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -12546,6 +12546,36 @@ __bpf_kfunc int bpf_xdp_pull_data(struct xdp_md *x,
u32 len)
return 0;
}
+/**
+ * bpf_skb_rx_checksum() - Read skb RX checksum info.
+ * @skb_: socket buffer to read from
+ * @ip_summed: return value for skb->ip_summed
+ * @csum_meta: checksum metadata
+ *
+ * Reads the checksum-related fields from a socket buffer. For
+ * %CHECKSUM_COMPLETE, csum_meta reports the hardware checksum value.
+ * For %CHECKSUM_UNNECESSARY, csum_meta reports the checksum level.
+ * For %CHECKSUM_NONE, csum_meta is zero.
+ *
+ * Return:
+ * * %0 - success
+ */
+__bpf_kfunc int bpf_skb_rx_checksum(struct __sk_buff *skb_, u32 *ip_summed,
+ u32 *csum_meta)
+{
+ struct sk_buff *skb = (struct sk_buff *)skb_;
+
+ *ip_summed = skb->ip_summed;
+ if (skb->ip_summed == CHECKSUM_COMPLETE)
+ *csum_meta = skb->csum;
+ else if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+ *csum_meta = skb->csum_level;
+ else
+ *csum_meta = 0;
+
+ return 0;
+}
+
__bpf_kfunc_end_defs();
int bpf_dynptr_from_skb_rdonly(struct __sk_buff *skb, u64 flags,
@@ -12565,6 +12595,7 @@ int bpf_dynptr_from_skb_rdonly(struct __sk_buff *skb,
u64 flags,
BTF_KFUNCS_START(bpf_kfunc_check_set_skb)
BTF_ID_FLAGS(func, bpf_dynptr_from_skb)
+BTF_ID_FLAGS(func, bpf_skb_rx_checksum)
BTF_KFUNCS_END(bpf_kfunc_check_set_skb)
BTF_KFUNCS_START(bpf_kfunc_check_set_skb_meta)
--
2.55.0