Skip to content

Commit 2647429

Browse files
committed
pping: Add warnings for failing to create map entry
Send a warning notifying the user that PPing failed to create a flow/timestamp entry due to the corresponding map being full. To avoid sending a warning for every packet, only emit warnings every WARN_MAP_FULL_INTERVAL (which is currently hard-coded to 1s). Signed-off-by: Simon Sundberg <[email protected]>
1 parent 54886c9 commit 2647429

File tree

3 files changed

+68
-5
lines changed

3 files changed

+68
-5
lines changed

pping/pping.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,15 @@ static void print_event_json(const union pping_event *e)
821821
jsonw_end_object(json_ctx);
822822
}
823823

824+
static void warn_map_full(const struct map_full_event *e)
825+
{
826+
print_ns_datetime(stderr, e->timestamp);
827+
fprintf(stderr, " Warning: Unable to create %s entry for flow ",
828+
e->map == PPING_MAP_FLOWSTATE ? "flow" : "timestamp");
829+
print_flow_ppvizformat(stderr, &e->flow);
830+
fprintf(stderr, "\n");
831+
}
832+
824833
static void handle_event(void *ctx, int cpu, void *data, __u32 data_size)
825834
{
826835
const union pping_event *e = data;
@@ -829,6 +838,9 @@ static void handle_event(void *ctx, int cpu, void *data, __u32 data_size)
829838
return;
830839

831840
switch (e->event_type) {
841+
case EVENT_TYPE_MAP_FULL:
842+
warn_map_full(&e->map_event);
843+
break;
832844
case EVENT_TYPE_RTT:
833845
case EVENT_TYPE_FLOW:
834846
print_event_func(e);

pping/pping.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ typedef __u64 fixpoint64;
1414
/* For the event_type members of rtt_event and flow_event */
1515
#define EVENT_TYPE_FLOW 1
1616
#define EVENT_TYPE_RTT 2
17+
#define EVENT_TYPE_MAP_FULL 3
1718

1819
enum __attribute__((__packed__)) flow_event_type {
1920
FLOW_EVENT_NONE,
@@ -37,6 +38,11 @@ enum __attribute__((__packed__)) flow_event_source {
3738
EVENT_SOURCE_USERSPACE
3839
};
3940

41+
enum __attribute__((__packed__)) pping_map {
42+
PPING_MAP_FLOWSTATE = 0,
43+
PPING_MAP_PACKETTS
44+
};
45+
4046
struct bpf_config {
4147
__u64 rate_limit;
4248
fixpoint64 rtt_rate;
@@ -133,10 +139,23 @@ struct flow_event {
133139
__u8 reserved;
134140
};
135141

142+
/*
143+
* An event indicating that a new entry could not be created the map due to the
144+
* map being full.
145+
*/
146+
struct map_full_event {
147+
__u64 event_type;
148+
__u64 timestamp;
149+
struct network_tuple flow;
150+
enum pping_map map;
151+
__u8 reserved[3];
152+
};
153+
136154
union pping_event {
137155
__u64 event_type;
138156
struct rtt_event rtt_event;
139157
struct flow_event flow_event;
158+
struct map_full_event map_event;
140159
};
141160

142161
/*

pping/pping_kern.c

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
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 {
7881
char _license[] SEC("license") = "GPL";
7982
// Global config struct - set from userspace
8083
static volatile const struct bpf_config config = {};
84+
static volatile __u64 last_warn_time[2] = { 0 };
85+
8186

8287
// Map definitions
8388
struct {
@@ -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

Comments
 (0)