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  }