github.com/cilium/cilium@v1.16.2/bpf/lib/csum.h (about) 1 /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 2 /* Copyright Authors of Cilium */ 3 4 #pragma once 5 6 #include <linux/tcp.h> 7 #include <linux/udp.h> 8 #include <linux/icmpv6.h> 9 10 #define TCP_CSUM_OFF (offsetof(struct tcphdr, check)) 11 #define UDP_CSUM_OFF (offsetof(struct udphdr, check)) 12 13 struct csum_offset { 14 __u16 offset; 15 __u16 flags; 16 }; 17 18 /** 19 * Determins the L4 checksum field offset and required flags 20 * @arg nexthdr L3 nextheader field 21 * @arg off Pointer to uninitialied struct csum_offset struct 22 * 23 * Sets off.offset to offset from start of L4 header to L4 checksum field 24 * and off.flags to the required flags, namely BPF_F_MARK_MANGLED_0 for UDP. 25 * For unknown L4 protocols or L4 protocols which do not have a checksum 26 * field, off is initialied to 0. 27 */ 28 static __always_inline void csum_l4_offset_and_flags(__u8 nexthdr, 29 struct csum_offset *off) 30 { 31 switch (nexthdr) { 32 case IPPROTO_TCP: 33 off->offset = TCP_CSUM_OFF; 34 break; 35 36 case IPPROTO_UDP: 37 off->offset = UDP_CSUM_OFF; 38 off->flags = BPF_F_MARK_MANGLED_0; 39 break; 40 #ifdef ENABLE_SCTP 41 case IPPROTO_SCTP: 42 /* Disable readjusting checksums of SCTP packets. 43 * SCTP packets use a crc32c checksum over the SCTP 44 * header and the data and do not checksum the any 45 * part of the packet prior to the SCTP header. 46 * This means as long as we do not modify the ports 47 * the SCTP checksum will not change. We do this 48 * because there is not a good way to calculate a 49 * crc32c checksum in eBPF and will likely require 50 * additional kernel support. 51 */ 52 off->offset = 0; 53 break; 54 #endif /* ENABLE_SCTP */ 55 case IPPROTO_ICMPV6: 56 off->offset = offsetof(struct icmp6hdr, icmp6_cksum); 57 break; 58 59 case IPPROTO_ICMP: 60 break; 61 } 62 } 63 64 /** 65 * Helper to change L4 checksum 66 * @arg ctx Packet 67 * @arg l4_off Offset to L4 header 68 * @arg csum Pointer to csum_offset as extracted by csum_l4_offset_and_flags() 69 * @arg from From value or 0 if to contains csum diff 70 * @arg to To value or a csum diff 71 * @arg flags Additional flags to be passed to l4_csum_replace() 72 */ 73 static __always_inline int csum_l4_replace(struct __ctx_buff *ctx, __u64 l4_off, 74 const struct csum_offset *csum, 75 __be32 from, __be32 to, int flags) 76 { 77 return l4_csum_replace(ctx, l4_off + csum->offset, from, to, flags | csum->flags); 78 }