2828// Mask for IPv6 flowlabel + traffic class - used in fib lookup
2929#define IPV6_FLOWINFO_MASK __cpu_to_be32(0x0FFFFFFF)
3030
31+ // Emit a warning max once per second when failing to add entry to map
32+ #define WARN_MAP_FULL_INTERVAL 1000000000UL
33+
3134/*
3235 * This struct keeps track of the data and data_end pointers from the xdp_md or
3336 * __skb_buff contexts, as well as a currently parsed to position kept in nh.
@@ -78,6 +81,8 @@ struct packet_info {
7881char _license [] SEC ("license" ) = "GPL" ;
7982// Global config struct - set from userspace
8083static volatile const struct bpf_config config = {};
84+ static volatile __u64 last_warn_time [2 ] = { 0 };
85+
8186
8287// Map definitions
8388struct {
@@ -441,11 +446,35 @@ static void send_flow_event(void *ctx, struct packet_info *p_info,
441446 bpf_perf_event_output (ctx , & events , BPF_F_CURRENT_CPU , & fe , sizeof (fe ));
442447}
443448
449+ /*
450+ * Send a map-full event for the map.
451+ * Will only trigger once every WARN_MAP_FULL_INTERVAL
452+ */
453+ static void send_map_full_event (void * ctx , struct packet_info * p_info ,
454+ enum pping_map map )
455+ {
456+ struct map_full_event me ;
457+
458+ if (p_info -> time < last_warn_time [map ] ||
459+ p_info -> time - last_warn_time [map ] < WARN_MAP_FULL_INTERVAL )
460+ return ;
461+
462+ last_warn_time [map ] = p_info -> time ;
463+
464+ __builtin_memset (& me , 0 , sizeof (me ));
465+ me .event_type = EVENT_TYPE_MAP_FULL ;
466+ me .timestamp = p_info -> time ;
467+ me .flow = p_info -> pid .flow ;
468+ me .map = map ;
469+
470+ bpf_perf_event_output (ctx , & events , BPF_F_CURRENT_CPU , & me , sizeof (me ));
471+ }
472+
444473/*
445474 * Attempt to create a new flow-state.
446475 * Returns a pointer to the flow_state if successful, NULL otherwise
447476 */
448- static struct flow_state * create_flow (struct packet_info * p_info )
477+ static struct flow_state * create_flow (void * ctx , struct packet_info * p_info )
449478{
450479 struct flow_state new_state = { 0 };
451480
@@ -455,8 +484,10 @@ static struct flow_state *create_flow(struct packet_info *p_info)
455484 EVENT_REASON_FIRST_OBS_PCKT ;
456485
457486 if (bpf_map_update_elem (& flow_state , & p_info -> pid .flow , & new_state ,
458- BPF_NOEXIST ) != 0 )
487+ BPF_NOEXIST ) != 0 ) {
488+ send_map_full_event (ctx , p_info , PPING_MAP_FLOWSTATE );
459489 return NULL ;
490+ }
460491
461492 return bpf_map_lookup_elem (& flow_state , & p_info -> pid .flow );
462493}
@@ -474,7 +505,7 @@ static struct flow_state *update_flow(void *ctx, struct packet_info *p_info,
474505 !(p_info -> event_type == FLOW_EVENT_CLOSING ||
475506 p_info -> event_type == FLOW_EVENT_CLOSING_BOTH )) {
476507 * new_flow = true;
477- f_state = create_flow (p_info );
508+ f_state = create_flow (ctx , p_info );
478509 }
479510
480511 if (!f_state )
@@ -610,8 +641,9 @@ static void pping_timestamp_packet(struct flow_state *f_state, void *ctx,
610641 */
611642 f_state -> last_timestamp = p_info -> time ;
612643
613- bpf_map_update_elem (& packet_ts , & p_info -> pid , & p_info -> time ,
614- BPF_NOEXIST );
644+ if (bpf_map_update_elem (& packet_ts , & p_info -> pid , & p_info -> time ,
645+ BPF_NOEXIST ) != 0 )
646+ send_map_full_event (ctx , p_info , PPING_MAP_PACKETTS );
615647}
616648
617649/*
0 commit comments