LCOV - code coverage report
Current view: top level - waltz/neigh - fd_neigh4_probe.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 51 0.0 %
Date: 2025-03-20 12:08:36 Functions: 0 3 0.0 %

          Line data    Source code
       1             : #include "fd_neigh4_probe.h"
       2             : #include "../../tango/tempo/fd_tempo.h" /* fd_tempo_tick_per_ns */
       3             : 
       4             : #include <errno.h>
       5             : #include <sys/socket.h> /* socket(2) */
       6             : #include <netinet/in.h> /* IPPROTO_IP */
       7             : #include <unistd.h> /* close(2) */
       8             : 
       9             : void
      10             : fd_neigh4_prober_init( fd_neigh4_prober_t * prober,
      11             :                        float                max_probes_per_second,
      12             :                        ulong                max_probe_burst,
      13           0 :                        float                probe_delay_seconds ) {
      14             : 
      15           0 :   int sock_fd = socket( AF_INET, SOCK_DGRAM, 0 );
      16           0 :   if( FD_UNLIKELY( sock_fd<0 ) ) {
      17           0 :     FD_LOG_ERR(( "socket(AF_INET,SOCK_DGRAM,0) failed (%i-%s)",
      18           0 :                  errno, fd_io_strerror( errno ) ));
      19           0 :   }
      20             : 
      21             :   /* IP_TTL=1 is the lowest permitted value:
      22             :      https://github.com/torvalds/linux/blob/v6.13/net/ipv4/ip_sockglue.c#L300 */
      23           0 :   int ip_ttl = 1;
      24           0 :   if( FD_UNLIKELY( 0!=setsockopt( sock_fd, IPPROTO_IP, IP_TTL, &ip_ttl, sizeof(int) ) ) ) {
      25           0 :     (void)close( sock_fd );
      26           0 :     FD_LOG_ERR(( "setsockopt(%i,IPPROTO_IP,IP_TTL,1) failed (%i-%s)",
      27           0 :                  sock_fd, errno, fd_io_strerror( errno ) ));
      28           0 :   }
      29             : 
      30             :   /* Only need to send probe packets to Ethernet neighbors */
      31           0 :   int dontroute = 1;
      32           0 :   if( FD_UNLIKELY( 0!=setsockopt( sock_fd, SOL_SOCKET, SO_DONTROUTE, &dontroute, sizeof(int) ) ) ) {
      33           0 :     (void)close( sock_fd );
      34           0 :     FD_LOG_ERR(( "setsockopt(%i,SOL_SOCKET,SO_DONTROUTE,1) failed (%i-%s)",
      35           0 :                  sock_fd, errno, fd_io_strerror( errno ) ));
      36           0 :   }
      37             : 
      38           0 :   float tick_per_ns = (float)fd_tempo_tick_per_ns( NULL );
      39             : 
      40           0 :   *prober = (fd_neigh4_prober_t) {
      41           0 :     .sock_fd     = sock_fd,
      42           0 :     .probe_delay = (long)( tick_per_ns * probe_delay_seconds * 1e9f ),
      43           0 :     .rate_limit  = (fd_token_bucket_t) {
      44           0 :       .ts      = fd_tickcount(),
      45           0 :       .rate    = tick_per_ns * (max_probes_per_second / 1e9f),
      46           0 :       .burst   = (float)max_probe_burst,
      47           0 :       .balance = 0.f
      48           0 :     },
      49           0 :     .local_rate_limited_cnt  = 0UL,
      50           0 :     .global_rate_limited_cnt = 0UL
      51           0 :   };
      52           0 : }
      53             : 
      54             : void
      55           0 : fd_neigh4_prober_fini( fd_neigh4_prober_t * prober ) {
      56           0 :   if( FD_UNLIKELY( 0!=close( prober->sock_fd ) ) ) {
      57           0 :     FD_LOG_ERR(( "close(%i) failed (%i-%s)",
      58           0 :                  prober->sock_fd, errno, fd_io_strerror( errno ) ));
      59           0 :   }
      60           0 :   prober->sock_fd = -1;
      61           0 : }
      62             : 
      63             : int
      64             : fd_neigh4_probe( fd_neigh4_prober_t * prober,
      65             :                  fd_neigh4_entry_t *  entry,
      66             :                  uint                 ip4_addr,
      67           0 :                  long                 now ) {
      68             : 
      69           0 :   struct sockaddr_in dst = {
      70           0 :     .sin_family = AF_INET,
      71           0 :     .sin_port   = (ushort)0xFFFF,
      72           0 :     .sin_addr   = { .s_addr = ip4_addr }
      73           0 :   };
      74           0 :   if( FD_UNLIKELY( sendto( prober->sock_fd, NULL, 0UL, MSG_DONTWAIT, fd_type_pun_const( &dst ), sizeof(struct sockaddr_in) )<0 ) ) {
      75           0 :     return errno;
      76           0 :   }
      77             : 
      78           0 :   entry->probe_suppress_until = now + prober->probe_delay;
      79             : 
      80           0 :   return 0;
      81           0 : }

Generated by: LCOV version 1.14