LCOV - code coverage report
Current view: top level - waltz/ip - fd_ip.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 2 3 66.7 %
Date: 2024-11-13 11:58:15 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef HEADER_fd_src_waltz_ip_fd_ip_h
       2             : #define HEADER_fd_src_waltz_ip_fd_ip_h
       3             : 
       4             : #include "fd_ip_enum.h"
       5             : #include "fd_netlink.h"
       6             : #include "../../util/fd_util.h"
       7             : 
       8             : /* implements a number of IP protocol functions required by XDP, since we're bypassing
       9             :    parts of the kernel */
      10             : 
      11             : 
      12             : /* ARP
      13             : 
      14             :    We use netlink to retrieve the ARP table
      15             : 
      16             :    Whenever an IP we're trying to resolve is not in the ARP table, we'll simply send an
      17             :    ARP request. The Kernel should see the responses and update its ARP table
      18             : 
      19             :    */
      20             : 
      21             : /* Routing
      22             : 
      23             :    We use netlink to obtain the routing table
      24             : 
      25             :    In particular we need to choose which next hop IP is required
      26             : 
      27             :    */
      28             : 
      29             : /* magic */
      30           6 : #define FD_IP_MAGIC (0x37ad94a6ec098fc1UL)
      31             : 
      32             : /* size of an ARP probe packet, including eth header */
      33           0 : #define FD_IP_ARP_SZ (sizeof(fd_ip_arp_t))
      34             : 
      35             : /* alias fd_ip_route_entry_t to fd_nl_route_entry_t
      36             :    and   fd_ip_arp_entry_t   to fd_nl_arp_entry_t */
      37             : typedef fd_nl_route_entry_t fd_ip_route_entry_t;
      38             : typedef fd_nl_arp_entry_t   fd_ip_arp_entry_t;
      39             : 
      40             : struct fd_ip {
      41             :   ulong magic;
      42             : 
      43             :   /* capacity */
      44             :   ulong num_arp_entries;
      45             :   ulong num_route_entries;
      46             : 
      47             :   /* current state */
      48             :   ulong cur_num_arp_entries;
      49             :   ulong cur_num_route_entries;
      50             : 
      51             :   /* table index */
      52             :   /* there are two arp tables and two route tables */
      53             :   /* these indicate whether the current table is the first or second */
      54             :   uint  arp_table_idx;
      55             :   uint  route_table_idx;
      56             : 
      57             :   ulong ofs_netlink;
      58             :   ulong ofs_arp_table;
      59             :   ulong ofs_route_table;
      60             : };
      61             : typedef struct fd_ip fd_ip_t;
      62             : 
      63             : 
      64             : struct fd_ip_arp {
      65             :   /* Ethernet header */
      66             :   uchar  dst_mac_addr[6];        /* broadcast address */
      67             :   uchar  src_mac_addr[6];        /* source mac address */
      68             :   ushort ethtype;                /* Ethertype - ARP is 0x0806 */
      69             : 
      70             :   /* ARP */
      71             :   ushort hw_type;                /* Ethernet is 1 */
      72             :   ushort proto_type;             /* IP is 0x0800 */
      73             :   uchar  hw_addr_len;            /* hardware address length - ethernet is 6 */
      74             :   uchar  proto_addr_len;         /* protocol address length - IPv4 is 4 */
      75             :   ushort op;                     /* operation - request is 1 */
      76             :   uchar  sender_hw_addr[6];      /* sender hardware address */
      77             :   uchar  sender_proto_addr[4];   /* sender protocol (IPv4) address */
      78             :   uchar  target_hw_addr[6];      /* target hardware address - ignored for request */
      79             :   uchar  target_proto_addr[4];   /* target protocol (IPv4) address - ignored for request */
      80             : 
      81             : };
      82             : typedef struct fd_ip_arp fd_ip_arp_t;
      83             : 
      84             : 
      85             : FD_PROTOTYPES_BEGIN
      86             : 
      87             : /* footprint and align
      88             : 
      89             :    obtain the required footprint and alignment */
      90             : 
      91          12 : #define FD_IP_ALIGN (64UL)
      92             : 
      93             : FD_FN_CONST ulong fd_ip_footprint( ulong arp_entries, ulong routing_entries );
      94             : FD_FN_CONST ulong fd_ip_align( void );
      95             : 
      96             : 
      97             : /* new IP
      98             : 
      99             :    create IP stack in the workspace
     100             : 
     101             :    arp_entries        the maximum number of arp entries allowed
     102             :    routing_entries    the maximum number ot routing entries allowed
     103             : 
     104             :    returns
     105             :      a void pointer to the value required by fd_ip_join */
     106             : 
     107             : void *
     108             : fd_ip_new( void * shmem, ulong arp_entries, ulong routing_entries  );
     109             : 
     110             : 
     111             : /* join existing IP stack
     112             : 
     113             :    joins the IP stack that already exists in the workspace
     114             : 
     115             :    returns pointer to the fd_ip_t instance or NULL in a failure
     116             : 
     117             :    only one join to each fd_ip_t per process is allowed
     118             :    each join creates a netlink file descriptor
     119             : 
     120             :    args
     121             :      mem           the return value from fd_ip_new
     122             : 
     123             :    returns
     124             :      pointer to the fd_ip_t joined for use, or NULL if an error occurred */
     125             : 
     126             : 
     127             : fd_ip_t *
     128             : fd_ip_join( void * mem );
     129             : 
     130             : 
     131             : /* leave the fd_ip
     132             : 
     133             :    cleans up local resources
     134             :    the supplied ip pointer should not be used after
     135             : 
     136             :    args
     137             :      ip            the fd_ip to leave */
     138             : void *
     139             : fd_ip_leave( fd_ip_t * ip );
     140             : 
     141             : 
     142             : /* get pointer to netlink
     143             :    this is used internally */
     144             : fd_nl_t *
     145             : fd_ip_netlink_get( fd_ip_t * ip );
     146             : 
     147             : 
     148             : /* get pointer to start of current routing table
     149             :    this is used internally
     150             :    probably best not to modify the data */
     151             : fd_ip_route_entry_t *
     152             : fd_ip_route_table_get( fd_ip_t * ip );
     153             : 
     154             : 
     155             : /* get pointer to start of alternate routing table
     156             :    this is used internally
     157             :    probably best not to modify the data */
     158             : fd_ip_route_entry_t *
     159             : fd_ip_route_table_get_alt( fd_ip_t * ip );
     160             : 
     161             : 
     162             : /* get pointer to start of current arp table
     163             :    this is used internally
     164             :    probably best not to modify the data */
     165             : fd_ip_arp_entry_t *
     166             : fd_ip_arp_table_get( fd_ip_t * ip );
     167             : 
     168             : 
     169             : /* get pointer to start of alternate arp table
     170             :    this is used internally
     171             :    probably best not to modify the data */
     172             : fd_ip_arp_entry_t *
     173             : fd_ip_arp_table_get_alt( fd_ip_t * ip );
     174             : 
     175             : 
     176             : /* fetch the ARP table from the kernel
     177             : 
     178             :    The table is written into the workspace
     179             : 
     180             :    use fd_ip_arp_query to access the data */
     181             : 
     182             : void
     183             : fd_ip_arp_fetch( fd_ip_t * ip );
     184             : 
     185             : 
     186             : /* query an arp entry
     187             : 
     188             :    searches for an IP address in the table
     189             : 
     190             :    if found, *arp is set to point to the entry and the function
     191             :        returns FD_IP_SUCCESS
     192             : 
     193             :    otherwise, the function returns FD_IP_ERROR */
     194             : 
     195             : int
     196             : fd_ip_arp_query( fd_ip_t * ip, fd_ip_arp_entry_t ** arp, uint ip_addr );
     197             : 
     198             : 
     199             : /* generate a raw ARP probe (request) packet
     200             : 
     201             :    used for caller to generate an ARP packet to send in the event
     202             :      we don't have an existing ARP entry
     203             : 
     204             :    writes ARP packet into buf
     205             : 
     206             :    if successful, returns FD_IP_SUCCESS
     207             : 
     208             :    if unable to generate ARP, if the dest capacity (dest_cap) is not enough space
     209             :      then the function returns FD_IP_ERROR
     210             : 
     211             :    args
     212             :      buf          the buffer used to accept the raw ethernet packet
     213             :      buf_cap      the capacity in bytes of buf
     214             :      arp_len      *arp_len is set to the length in bytes of the generated ARP packet
     215             :      ip_addr      the IPv4 address of the target to be probed
     216             :      src_mac_addr the MAC address of the source (caller)
     217             : 
     218             :    returns
     219             :      FD_IP_SUCCESS on success
     220             :      FD_IP_ERROR   on failure (buf_cap not large enough) */
     221             : 
     222             : int
     223             : fd_ip_arp_gen_arp_probe( uchar *       buf,
     224             :                          ulong         buf_cap,
     225             :                          ulong *       arp_len,
     226             :                          uint          dst_ip_addr,
     227             :                          uint          src_ip_addr,
     228             :                          uchar const * src_mac_addr );
     229             : 
     230             : 
     231             : /* fetch the routing table from the kernel
     232             : 
     233             :    the routing table will be written into the workspace, completely replacing
     234             :    any existing routing entries */
     235             : 
     236             : void
     237             : fd_ip_route_fetch( fd_ip_t * ip );
     238             : 
     239             : 
     240             : /* query the routing table
     241             : 
     242             :    the provided IP address is looked up in the routing table
     243             : 
     244             :    if an appropriate entry is found, *route is set to point to it
     245             :      and FD_IP_SUCCESS is returned
     246             : 
     247             :    otherwise, FD_IP_ERROR is returned */
     248             : 
     249             : int
     250             : fd_ip_route_query( fd_ip_t *              ip,
     251             :                    fd_ip_route_entry_t ** route,
     252             :                    uint                   ip_addr );
     253             : 
     254             : 
     255             : /* Do routing for an ip_addr
     256             : 
     257             :    Handles unicast, broadcast and multicast
     258             :        broadcast:
     259             :          ff.ff.ff.ff -> mac: ff:ff:ff:ff:ff:ff
     260             :        subnet broadcast:
     261             :          a.ff.ff.ff/8
     262             :          a.b.ff.ff/16
     263             :          a.b.c.ff/24 -> if local, ff:ff:ff:ff:ff:ff
     264             :                         else normal routing
     265             :        multicast:
     266             :          224+a,b,c,d -> 01:00:5e:B:c:d (B = b & 0x7f)
     267             : 
     268             :    Queries the routing table
     269             :      If no match return -1 error
     270             :      If match,
     271             :        Determines which ip_addr to use
     272             :          If local, uses dst_ip_addr
     273             :          Else, uses the gateway/next hop ip addr
     274             :     Queries the arp table
     275             :       If no match returns 1 - send probe
     276             :       If match, sets mac and ifindex and returns 0
     277             : 
     278             :     returns
     279             :       FD_IP_NO_ROUTE    No route to destination
     280             :       FD_IP_SUCCESS     Route (and arp if necessary) found. out_* have been set
     281             :       FD_IP_PROBE_RQD   Route, but we need to send an ARP probe to resolve the MAC address
     282             :                           Resolve the supplied out_next_ip_addr by sending a probe packet
     283             :                         Delay between probes
     284             :       FD_IP_MULTICAST   Multicast
     285             :       FD_IP_BROADCAST   Local broadcast */
     286             : int
     287             : fd_ip_route_ip_addr( uchar *   out_dst_mac,
     288             :                      uint *    out_next_ip_addr,
     289             :                      uint *    out_ifindex,
     290             :                      fd_ip_t * ip,
     291             :                      uint      ip_addr );
     292             : 
     293             : 
     294             : /* Prepares the ARP cache for receiving a new ARP entry
     295             : 
     296             :    Should be called prior to sending an ARP request
     297             : 
     298             :    The kernel ignores unsolicited ARP responses, so this function
     299             :    allows our ARP requests to update the kernel ARP table
     300             : 
     301             :    It creates or updates an entry depending on the current state
     302             :    If there is no entry, it creates one in state NONE
     303             :    Otherwise, it moves NONE to INCOMPLETE and moves DELAY to PROBE
     304             :    This should give the kernel what it needs to handle the rest of
     305             :    the transitions correctly
     306             : 
     307             :    return values:
     308             :      FD_IP_SUCCESS   Call successful, nothing to do
     309             :      FD_IP_PROBE     Call successful, caller should send an ARP probe
     310             :      FD_IP_RETRY     Call successful, caller should try this call again soon
     311             :                        or immediately
     312             :      FD_IP_ERROR     Call unsuccessful */
     313             : int
     314             : fd_ip_update_arp_table( fd_ip_t * ip,
     315             :                         uint      ip_addr,
     316             :                         uint      ifindex );
     317             : 
     318             : FD_PROTOTYPES_END
     319             : 
     320             : #endif

Generated by: LCOV version 1.14