mirror of
https://github.com/xdp-project/bpf-examples.git
synced 2024-05-06 15:54:53 +00:00
pping: Add errors to global counters
Add counters for runtime errors in the BPF programs to the global
counters. Specifically, add counters for failing to create entries in
the packet-timestamp, flow-state and aggregation-subnet maps. The
counters can easily be extended to include other errors in the
future. Output any non-zero counters at in an errors section at the
end of the global-counters report.
Example standard entry (linebreaks not part of actual output):
13:53:40.450555237: TCP=(pkts=110983, bytes=899455326), ICMP=(pkts=16,
bytes=1568), ECN=(Not-ECT=110999), errors=(store-packet-ts=210,
create-flow-state=8, create-agg-subnet-state=110999)
Example JSON entry:
{
"timestamp": 1698235250698609700,
"protocol_counters": {
"TCP": {
"packets": 111736,
"bytes": 898999024
},
"ICMP": {
"packets": 20,
"bytes": 1960
}
},
"ecn_counters": {
"no_ECT": 111756
},
"errors": {
"store_packet_ts": 165,
"create_flow_state": 10,
"create_agg_subnet_state": 111756
}
}
Signed-off-by: Simon Sundberg <simon.sundberg@kau.se>
This commit is contained in:
@@ -1149,6 +1149,12 @@ static bool ecncounters_empty(const struct ecn_counters *counters)
|
||||
return memcmp(counters, &empty, sizeof(empty)) == 0;
|
||||
}
|
||||
|
||||
static bool pping_errors_empty(const struct pping_error_counters *errors)
|
||||
{
|
||||
static const struct pping_error_counters empty = { 0 };
|
||||
|
||||
return memcmp(errors, &empty, sizeof(empty)) == 0;
|
||||
}
|
||||
|
||||
static void print_counter_standard(FILE *stream, const char *name, __u64 val,
|
||||
bool *first)
|
||||
@@ -1197,6 +1203,22 @@ static void print_ecncounters_standard(FILE *stream,
|
||||
fprintf(stream, ")");
|
||||
}
|
||||
|
||||
static void
|
||||
print_ppingerrors_standard(FILE *stream,
|
||||
const struct pping_error_counters *errors)
|
||||
{
|
||||
bool first = true;
|
||||
|
||||
fprintf(stream, "errors=(");
|
||||
print_counter_standard(stream, "store-packet-ts", errors->pktts_store,
|
||||
&first);
|
||||
print_counter_standard(stream, "create-flow-state", errors->flow_create,
|
||||
&first);
|
||||
print_counter_standard(stream, "create-agg-subnet-state",
|
||||
errors->agg_subnet_create, &first);
|
||||
fprintf(stream, ")");
|
||||
}
|
||||
|
||||
static void
|
||||
print_globalcounters_standard(FILE *stream, __u64 t_monotonic,
|
||||
const struct global_counters *counters)
|
||||
@@ -1236,6 +1258,11 @@ print_globalcounters_standard(FILE *stream, __u64 t_monotonic,
|
||||
print_ecncounters_standard(stream, &counters->ecn);
|
||||
}
|
||||
|
||||
if (!pping_errors_empty(&counters->err)) {
|
||||
fprintf(stream, ", ");
|
||||
print_ppingerrors_standard(stream, &counters->err);
|
||||
}
|
||||
|
||||
fprintf(stream, "\n");
|
||||
}
|
||||
|
||||
@@ -1271,6 +1298,17 @@ static void print_ecncounters_json(json_writer_t *jctx,
|
||||
jsonw_end_object(jctx);
|
||||
}
|
||||
|
||||
static void print_ppingerrors_json(json_writer_t *jctx,
|
||||
const struct pping_error_counters *errors)
|
||||
{
|
||||
jsonw_start_object(jctx);
|
||||
print_counter_json(jctx, "store_packet_ts", errors->pktts_store);
|
||||
print_counter_json(jctx, "create_flow_state", errors->flow_create);
|
||||
print_counter_json(jctx, "create_agg_subnet_state",
|
||||
errors->agg_subnet_create);
|
||||
jsonw_end_object(jctx);
|
||||
}
|
||||
|
||||
static void print_globalcounters_json(json_writer_t *jctx, __u64 t_monotonic,
|
||||
const struct global_counters *counters)
|
||||
{
|
||||
@@ -1309,6 +1347,9 @@ static void print_globalcounters_json(json_writer_t *jctx, __u64 t_monotonic,
|
||||
jsonw_name(jctx, "ecn_counters");
|
||||
print_ecncounters_json(jctx, &counters->ecn);
|
||||
|
||||
jsonw_name(jctx, "errors");
|
||||
print_ppingerrors_json(jctx, &counters->err);
|
||||
|
||||
jsonw_end_object(jctx);
|
||||
}
|
||||
|
||||
@@ -1332,6 +1373,14 @@ static void update_ecncounters(struct ecn_counters *to,
|
||||
to->ce += from->ce;
|
||||
}
|
||||
|
||||
static void update_pping_errors(struct pping_error_counters *to,
|
||||
const struct pping_error_counters *from)
|
||||
{
|
||||
to->pktts_store += from->pktts_store;
|
||||
to->flow_create += from->flow_create;
|
||||
to->agg_subnet_create += from->agg_subnet_create;
|
||||
}
|
||||
|
||||
static void update_globalcounters(struct global_counters *to,
|
||||
const struct global_counters *from)
|
||||
{
|
||||
@@ -1353,6 +1402,7 @@ static void update_globalcounters(struct global_counters *to,
|
||||
}
|
||||
|
||||
update_ecncounters(&to->ecn, &from->ecn);
|
||||
update_pping_errors(&to->err, &from->err);
|
||||
}
|
||||
|
||||
static void merge_percpu_globalcounters(struct global_counters *merged,
|
||||
@@ -1378,6 +1428,16 @@ static void diff_ecncounters(struct ecn_counters *diff,
|
||||
diff->ce = next->ce - prev->ce;
|
||||
}
|
||||
|
||||
static void diff_pping_errors(struct pping_error_counters *diff,
|
||||
const struct pping_error_counters *prev,
|
||||
const struct pping_error_counters *next)
|
||||
{
|
||||
diff->pktts_store = next->pktts_store - prev->pktts_store;
|
||||
diff->flow_create = next->flow_create - prev->flow_create;
|
||||
diff->agg_subnet_create =
|
||||
next->agg_subnet_create - prev->agg_subnet_create;
|
||||
}
|
||||
|
||||
static void diff_globalcounters(struct global_counters *diff,
|
||||
const struct global_counters *prev,
|
||||
const struct global_counters *next)
|
||||
@@ -1401,6 +1461,7 @@ static void diff_globalcounters(struct global_counters *diff,
|
||||
}
|
||||
|
||||
diff_ecncounters(&diff->ecn, &prev->ecn, &next->ecn);
|
||||
diff_pping_errors(&diff->err, &prev->err, &next->err);
|
||||
}
|
||||
|
||||
static int report_globalcounters(struct output_context *out_ctx,
|
||||
|
||||
@@ -83,6 +83,12 @@ enum __attribute__((__packed__)) connection_state {
|
||||
CONNECTION_STATE_CLOSED
|
||||
};
|
||||
|
||||
enum pping_error {
|
||||
PPING_ERR_PKTTS_STORE,
|
||||
PPING_ERR_FLOW_CREATE,
|
||||
PPING_ERR_AGGSUBNET_CREATE
|
||||
};
|
||||
|
||||
struct bpf_config {
|
||||
__u64 rate_limit;
|
||||
fixpoint64 rtt_rate;
|
||||
@@ -272,8 +278,15 @@ struct ecn_counters {
|
||||
__u64 ce;
|
||||
};
|
||||
|
||||
struct pping_error_counters {
|
||||
__u64 pktts_store;
|
||||
__u64 flow_create;
|
||||
__u64 agg_subnet_create;
|
||||
};
|
||||
|
||||
struct global_counters {
|
||||
struct ecn_counters ecn;
|
||||
struct pping_error_counters err;
|
||||
__u64 nonip_pkts;
|
||||
__u64 nonip_bytes;
|
||||
__u64 tcp_pkts;
|
||||
|
||||
+33
-2
@@ -321,6 +321,31 @@ get_dualflow_key_from_packet(struct packet_info *p_info)
|
||||
&p_info->reply_pid.flow;
|
||||
}
|
||||
|
||||
static void update_pping_error(enum pping_error err)
|
||||
{
|
||||
if (!config.agg_rtts)
|
||||
return;
|
||||
|
||||
struct global_counters *counters;
|
||||
__u32 key = 0;
|
||||
|
||||
counters = bpf_map_lookup_elem(&map_global_counters, &key);
|
||||
if (!counters)
|
||||
return;
|
||||
|
||||
switch (err) {
|
||||
case PPING_ERR_PKTTS_STORE:
|
||||
counters->err.pktts_store++;
|
||||
break;
|
||||
case PPING_ERR_FLOW_CREATE:
|
||||
counters->err.flow_create++;
|
||||
break;
|
||||
case PPING_ERR_AGGSUBNET_CREATE:
|
||||
counters->err.agg_subnet_create++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void update_ecn_counters(struct ecn_counters *counters, __u8 ecn)
|
||||
{
|
||||
switch (ecn) {
|
||||
@@ -929,6 +954,7 @@ create_dualflow_state(void *ctx, struct packet_info *p_info)
|
||||
|
||||
if (bpf_map_update_elem(&flow_state, key, &new_state, BPF_NOEXIST) !=
|
||||
0) {
|
||||
update_pping_error(PPING_ERR_FLOW_CREATE);
|
||||
send_map_full_event(ctx, p_info, PPING_MAP_FLOWSTATE);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1123,6 +1149,9 @@ lookup_or_create_aggregation_stats(struct in6_addr *ip, __u8 ipv, bool create)
|
||||
BPF_NOEXIST);
|
||||
// Cannot create new entry, switch to backup entry
|
||||
if (!create || (err && err != -EEXIST)) {
|
||||
if (create)
|
||||
update_pping_error(PPING_ERR_AGGSUBNET_CREATE);
|
||||
|
||||
if (ipv == AF_INET)
|
||||
key.v4 = IPV4_BACKUP_KEY;
|
||||
else
|
||||
@@ -1184,10 +1213,12 @@ static void pping_timestamp_packet(struct flow_state *f_state, void *ctx,
|
||||
f_state->last_timestamp = p_info->time;
|
||||
|
||||
if (bpf_map_update_elem(&packet_ts, &p_info->pid, &p_info->time,
|
||||
BPF_NOEXIST) == 0)
|
||||
BPF_NOEXIST) == 0) {
|
||||
__sync_fetch_and_add(&f_state->outstanding_timestamps, 1);
|
||||
else
|
||||
} else {
|
||||
update_pping_error(PPING_ERR_PKTTS_STORE);
|
||||
send_map_full_event(ctx, p_info, PPING_MAP_PACKETTS);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user