LCOV - code coverage report
Current view: top level - util/net - fd_udp.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 6 33 18.2 %
Date: 2025-03-20 12:08:36 Functions: 3 404 0.7 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_util_net_fd_udp_h
       2             : #define HEADER_fd_src_util_net_fd_udp_h
       3             : 
       4             : #include "fd_ip4.h" /* UDP is tightly tied to IP regardless of standard intent due to pseudo header layer violating BS */
       5             : 
       6             : /* FIXME: UDP CRASH COURSE HERE */
       7             : 
       8             : union fd_udp_hdr {
       9             :   struct {
      10             :     ushort net_sport; /* src port, net order */
      11             :     ushort net_dport; /* dst port, net order */
      12             :     ushort net_len;   /* datagram length, from first byte of this header to last byte of the udp payload */
      13             :     ushort check;     /* UDP checksum ("invariant" order), from first byte of pseudo header prepended before this header to last
      14             :                          byte of udp payload with zero padding to even length inclusive.  In IP4, 0 indicates no checksum. */
      15             :   };
      16             :   uchar uc[8];
      17             : };
      18             : 
      19             : typedef union fd_udp_hdr fd_udp_hdr_t;
      20             : 
      21             : /* FIXME: CONSIDER A PRETTY PRINTER FOR A FD_UDP_HDR? */
      22             : 
      23             : FD_PROTOTYPES_BEGIN
      24             : 
      25             : /* fd_ip4_udp_check is used for udp check field computation and
      26             :    validation.  If the dgram has no checksum (check==0), this returns
      27             :    the value to use for check.  If the dgram has a checksum (check!=0),
      28             :    this returns 0 if the message has a valid checksum or non-zero if
      29             :    not.  ip4_saddr and ip4_daddr are the ip4 source and destination
      30             :    addresses to use for the udp pseudo header.  udp is a non-NULL
      31             :    pointer to the first byte of a memory region containing the udp
      32             :    header and dgram is a non-NULL pointer to the first byte of a memory
      33             :    region containing a datagram of size:
      34             : 
      35             :      dgram_sz = fd_ushort_bswap(udp->net_len) - sizeof(fd_udp_hdr_t)
      36             : 
      37             :    bytes.  This assumes it is safe to read up to 3 bytes past the end of
      38             :    dgram (technically it will read the fd_align_up(dgram_sz,4UL) bytes
      39             :    dgram).  The contents of the tail read region are irrelevant.
      40             : 
      41             :    This is neither a particularly fast calculation (reasonably fast
      42             :    O(dgram_sz)) nor a particularly robust and it can inhibit cut-through
      43             :    usage.  So in general it is best to avoid UDP checksums, usually by
      44             :    exploiting their optionality in IP4 (note that the Ethernet CRC is
      45             :    reasonably strong and still provides protection).
      46             : 
      47             :    As such, this is mostly here for the rare application that needs to
      48             :    manually compute / validate UDP checksums (e.g. overhead doesn't
      49             :    matter or when the hardware sending/receiving the packet doesn't do
      50             :    various checksum offload computations and UDP checksums are
      51             :    required). */
      52             : 
      53             : FD_FN_PURE static inline ushort
      54             : fd_ip4_udp_check( uint                 ip4_saddr,
      55             :                   uint                 ip4_daddr,
      56             :                   fd_udp_hdr_t const * udp,
      57           0 :                   void const *         dgram ) { /* Assumed safe to tail read up to 3 bytes past end of msg */
      58           0 :   ushort net_len = udp->net_len; /* In net order */
      59           0 :   uint   rem     = (uint)fd_ushort_bswap( net_len ) - (uint)sizeof(fd_udp_hdr_t);
      60           0 : 
      61           0 :   /* Sum the pseudo header and UDP header words */
      62           0 :   ulong ul = ((((ulong)FD_IP4_HDR_PROTOCOL_UDP)<<8) | (((ulong)net_len)<<16))
      63           0 :            + ((ulong)ip4_saddr)
      64           0 :            + ((ulong)ip4_daddr)
      65           0 :            + ((ulong)FD_LOAD( uint, udp->uc   ))
      66           0 :            + ((ulong)FD_LOAD( uint, udp->uc+4 ));
      67           0 : 
      68           0 :   /* Sum the dgram words (reads up to 4 past end of msg) */
      69           0 :   uchar const * u = dgram;
      70           0 :   for( ; rem>3U; rem-=4U, u+=4 ) ul += (ulong)FD_LOAD( uint, u );
      71           0 :   ul += (ulong)( FD_LOAD( uint, u ) & ((1U<<(8U*rem))-1U) );
      72           0 : 
      73           0 :   /* Reduce the sum to a 16-bit one's complement sum */
      74           0 :   ul  = ( ul>>32            ) +
      75           0 :         ((ul>>16) & 0xffffUL) +
      76           0 :         ( ul      & 0xffffUL);
      77           0 :   ul  = ( ul>>16            ) +
      78           0 :         ( ul      & 0xffffUL);
      79           0 :   ul += ( ul>>16            );
      80           0 : 
      81           0 :   /* And complement it */
      82           0 :   return (ushort)~ul;
      83           0 : }
      84             : 
      85             : /* fd_udp_hdr_bswap reverses the endianness of all fields in the UDP
      86             :    header. */
      87             : 
      88             : static inline void
      89    27717935 : fd_udp_hdr_bswap( fd_udp_hdr_t * hdr ) {
      90    27717935 :   hdr->net_sport = (ushort)fd_ushort_bswap( hdr->net_sport    );
      91    27717935 :   hdr->net_dport = (ushort)fd_ushort_bswap( hdr->net_dport    );
      92    27717935 :   hdr->net_len   = (ushort)fd_ushort_bswap( hdr->net_len      );
      93    27717935 :   hdr->check     = (ushort)fd_ushort_bswap( hdr->check        );
      94    27717935 : }
      95             : 
      96             : FD_PROTOTYPES_END
      97             : 
      98             : #endif /* HEADER_fd_src_util_net_fd_udp_h */

Generated by: LCOV version 1.14