LCOV - code coverage report
Current view: top level - disco/gui - fd_gui_gossip_bw.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 41 0.0 %
Date: 2026-10-22 18:10:43 Functions: 0 76 0.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_disco_gui_fd_gui_gossip_bw_h
       2             : #define HEADER_fd_src_disco_gui_fd_gui_gossip_bw_h
       3             : 
       4             : /* fd_gui_gossip_bw aggregates the per-peer gossip byte counts the gui
       5             :    shows.  The gossip tile (egress, keyed by destination socket) and
       6             :    each gossvf tile (ingress, keyed by source socket) add every packet
       7             :    they already handle, keyed by (ip4, port, message tag), and publish
       8             :    the aggregates to the gui at most every FD_GUI_GOSSIP_BW_FLUSH_NS
       9             :    instead of the gui reading every raw packet.  The gui attributes
      10             :    each record to a peer by socket when it applies it, the same lookup
      11             :    it did per packet.  Records are only ever summed, so the byte
      12             :    counts match the per packet path exactly; they reach the gui's
      13             :    150 ms rate windows at most one flush interval later. */
      14             : 
      15             : #include "../../util/bits/fd_bits.h"
      16             : #include "../metrics/generated/fd_metrics_enums.h"
      17             : 
      18             : struct fd_gui_gossip_bw_rec {
      19             :   uint   ip4;  /* net order */
      20             :   ushort port; /* net order */
      21             :   ushort tag;  /* in [0,FD_METRICS_ENUM_GOSSIP_MESSAGE_TYPE_CNT) */
      22             :   ulong  sz;   /* sum of gossip payload bytes */
      23             : };
      24             : 
      25             : typedef struct fd_gui_gossip_bw_rec fd_gui_gossip_bw_rec_t;
      26             : 
      27           0 : #define FD_GUI_GOSSIP_BW_REC_MAX     (256UL)
      28           0 : #define FD_GUI_GOSSIP_BW_MTU         (FD_GUI_GOSSIP_BW_REC_MAX*sizeof(fd_gui_gossip_bw_rec_t))
      29           0 : #define FD_GUI_GOSSIP_BW_LG_SLOT_CNT (9)
      30           0 : #define FD_GUI_GOSSIP_BW_FLUSH_NS    (10L*1000L*1000L)
      31             : 
      32           0 : #define FD_GUI_GOSSIP_BW_ALIGN (128UL)
      33           0 : #define FD_GUI_GOSSIP_BW_MAGIC (0xf17eda2c37b0b500UL) /* firedancer gui bw ver 0 */
      34             : 
      35             : /* Pending byte counts, keyed by ip4 | port<<32 | tag<<48 (tag is
      36             :    below FD_METRICS_ENUM_GOSSIP_MESSAGE_TYPE_CNT, so no key is ULONG_MAX). */
      37             : 
      38             : struct fd_gui_gossip_bw_ele {
      39             :   ulong key;
      40             :   ulong sz;
      41             : };
      42             : 
      43             : typedef struct fd_gui_gossip_bw_ele fd_gui_gossip_bw_ele_t;
      44             : 
      45             : #define MAP_NAME         fd_gui_gossip_bw_map
      46           0 : #define MAP_T            fd_gui_gossip_bw_ele_t
      47           0 : #define MAP_KEY_NULL     ULONG_MAX
      48           0 : #define MAP_KEY_INVAL(k) ((k)==ULONG_MAX)
      49             : #define MAP_MEMOIZE      0
      50             : #include "../../util/tmpl/fd_map_dynamic.c"
      51             : 
      52             : struct __attribute__((aligned(FD_GUI_GOSSIP_BW_ALIGN))) fd_gui_gossip_bw_private {
      53             :   ulong                    magic;    /* ==FD_GUI_GOSSIP_BW_MAGIC */
      54             :   long                     flush_ticks;
      55             :   long                     deadline; /* tickcount the pending records are due, LONG_MAX if none */
      56             :   fd_gui_gossip_bw_ele_t * map;
      57             : };
      58             : 
      59             : typedef struct fd_gui_gossip_bw_private fd_gui_gossip_bw_t;
      60             : 
      61             : FD_PROTOTYPES_BEGIN
      62             : 
      63             : /* fd_gui_gossip_bw_{align,footprint} return the required alignment and
      64             :    footprint of a memory region suitable for use as a gui_gossip_bw. */
      65             : 
      66             : FD_FN_CONST ulong
      67             : fd_gui_gossip_bw_align( void );
      68             : 
      69             : FD_FN_CONST ulong
      70             : fd_gui_gossip_bw_footprint( void );
      71             : 
      72             : /* fd_gui_gossip_bw_new formats an unused memory region for use as a
      73             :    gui_gossip_bw with no pending records.  seed seeds the key hash.
      74             :    Returns shmem on success and NULL on failure (logs details). */
      75             : 
      76             : void *
      77             : fd_gui_gossip_bw_new( void * shmem,
      78             :                       ulong  seed );
      79             : 
      80             : fd_gui_gossip_bw_t *
      81             : fd_gui_gossip_bw_join( void * shbw );
      82             : 
      83             : void *
      84             : fd_gui_gossip_bw_leave( fd_gui_gossip_bw_t const * bw );
      85             : 
      86             : void *
      87             : fd_gui_gossip_bw_delete( void * shbw );
      88             : 
      89             : /* fd_gui_gossip_bw_add counts a gossip payload sent to or received
      90             :    from ip4:port (net order) at tickcount now.  Payloads the gui does
      91             :    not attribute (too short for a tag, unknown tag) are ignored.
      92             :    Returns 1 if the table is full and must be flushed before the next
      93             :    add. */
      94             : 
      95             : static inline int
      96             : fd_gui_gossip_bw_add( fd_gui_gossip_bw_t * bw,
      97             :                       uint                 ip4,
      98             :                       ushort               port,
      99             :                       uchar const *        payload,
     100             :                       ulong                payload_sz,
     101           0 :                       long                 now ) {
     102           0 :   if( FD_UNLIKELY( payload_sz<sizeof(uint) ) ) return 0;
     103           0 :   uint tag = FD_LOAD( uint, payload );
     104           0 :   if( FD_UNLIKELY( tag>=FD_METRICS_ENUM_GOSSIP_MESSAGE_TYPE_CNT ) ) return 0;
     105             : 
     106           0 :   ulong key = (ulong)ip4 | ((ulong)port<<32) | ((ulong)tag<<48);
     107           0 :   fd_gui_gossip_bw_ele_t * ele = fd_gui_gossip_bw_map_query( bw->map, key, NULL );
     108           0 :   if( FD_LIKELY( ele ) ) {
     109           0 :     ele->sz += payload_sz;
     110           0 :     return 0;
     111           0 :   }
     112             : 
     113           0 :   if( FD_UNLIKELY( !fd_gui_gossip_bw_map_key_cnt( bw->map ) ) ) bw->deadline = now + bw->flush_ticks;
     114           0 :   fd_gui_gossip_bw_map_insert( bw->map, key )->sz = payload_sz;
     115           0 :   return fd_gui_gossip_bw_map_key_cnt( bw->map )==FD_GUI_GOSSIP_BW_REC_MAX;
     116           0 : }
     117             : 
     118             : /* fd_gui_gossip_bw_due returns 1 if there are records and they are due
     119             :    at tickcount now. */
     120             : 
     121             : static inline int
     122             : fd_gui_gossip_bw_due( fd_gui_gossip_bw_t const * bw,
     123           0 :                       long                       now ) {
     124           0 :   return fd_gui_gossip_bw_map_key_cnt( bw->map ) && now>=bw->deadline;
     125           0 : }
     126             : 
     127             : /* fd_gui_gossip_bw_next_deadline returns the tickcount the pending
     128             :    records are due, LONG_MAX if there are none. */
     129             : 
     130             : static inline long
     131           0 : fd_gui_gossip_bw_next_deadline( fd_gui_gossip_bw_t const * bw ) {
     132           0 :   return fd_gui_gossip_bw_map_key_cnt( bw->map ) ? bw->deadline : LONG_MAX;
     133           0 : }
     134             : 
     135             : /* fd_gui_gossip_bw_flush copies the pending records to out (room for
     136             :    FD_GUI_GOSSIP_BW_REC_MAX) and empties the table.  Returns the number
     137             :    of records copied. */
     138             : 
     139             : static inline ulong
     140             : fd_gui_gossip_bw_flush( fd_gui_gossip_bw_t *     bw,
     141           0 :                         fd_gui_gossip_bw_rec_t * out ) {
     142           0 :   ulong cnt      = 0UL;
     143           0 :   ulong slot_cnt = fd_gui_gossip_bw_map_slot_cnt( bw->map );
     144           0 :   for( ulong i=0UL; i<slot_cnt; i++ ) {
     145           0 :     fd_gui_gossip_bw_ele_t const * ele = bw->map + i;
     146           0 :     if( fd_gui_gossip_bw_map_key_inval( ele->key ) ) continue;
     147           0 :     out[ cnt++ ] = (fd_gui_gossip_bw_rec_t){ .ip4 = (uint)ele->key, .port = (ushort)(ele->key>>32), .tag = (ushort)(ele->key>>48), .sz = ele->sz };
     148           0 :   }
     149           0 :   fd_gui_gossip_bw_map_clear( bw->map );
     150           0 :   bw->deadline = LONG_MAX;
     151           0 :   return cnt;
     152           0 : }
     153             : 
     154             : FD_PROTOTYPES_END
     155             : 
     156             : #endif /* HEADER_fd_src_disco_gui_fd_gui_gossip_bw_h */

Generated by: LCOV version 1.14