28
28
// Mask for IPv6 flowlabel + traffic class - used in fib lookup
29
29
#define IPV6_FLOWINFO_MASK __cpu_to_be32(0x0FFFFFFF)
30
30
31
+ // Emit a warning max once per second when failing to add entry to map
32
+ #define WARN_MAP_FULL_INTERVAL 1000000000UL
33
+
31
34
/*
32
35
* This struct keeps track of the data and data_end pointers from the xdp_md or
33
36
* __skb_buff contexts, as well as a currently parsed to position kept in nh.
@@ -78,6 +81,8 @@ struct packet_info {
78
81
char _license [] SEC ("license" ) = "GPL" ;
79
82
// Global config struct - set from userspace
80
83
static volatile const struct bpf_config config = {};
84
+ static volatile __u64 last_warn_time [2 ] = { 0 };
85
+
81
86
82
87
// Map definitions
83
88
struct {
@@ -441,11 +446,35 @@ static void send_flow_event(void *ctx, struct packet_info *p_info,
441
446
bpf_perf_event_output (ctx , & events , BPF_F_CURRENT_CPU , & fe , sizeof (fe ));
442
447
}
443
448
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
+
444
473
/*
445
474
* Attempt to create a new flow-state.
446
475
* Returns a pointer to the flow_state if successful, NULL otherwise
447
476
*/
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 )
449
478
{
450
479
struct flow_state new_state = { 0 };
451
480
@@ -455,8 +484,10 @@ static struct flow_state *create_flow(struct packet_info *p_info)
455
484
EVENT_REASON_FIRST_OBS_PCKT ;
456
485
457
486
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 );
459
489
return NULL ;
490
+ }
460
491
461
492
return bpf_map_lookup_elem (& flow_state , & p_info -> pid .flow );
462
493
}
@@ -474,7 +505,7 @@ static struct flow_state *update_flow(void *ctx, struct packet_info *p_info,
474
505
!(p_info -> event_type == FLOW_EVENT_CLOSING ||
475
506
p_info -> event_type == FLOW_EVENT_CLOSING_BOTH )) {
476
507
* new_flow = true;
477
- f_state = create_flow (p_info );
508
+ f_state = create_flow (ctx , p_info );
478
509
}
479
510
480
511
if (!f_state )
@@ -610,8 +641,9 @@ static void pping_timestamp_packet(struct flow_state *f_state, void *ctx,
610
641
*/
611
642
f_state -> last_timestamp = p_info -> time ;
612
643
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 );
615
647
}
616
648
617
649
/*
0 commit comments