From 35012a280484d339de111b7b389ea09da57d4f80 Mon Sep 17 00:00:00 2001 From: Simon Sundberg Date: Tue, 24 Oct 2023 16:18:35 +0200 Subject: [PATCH] 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 --- pping/pping.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ pping/pping.h | 13 ++++++++++ pping/pping_kern.c | 35 ++++++++++++++++++++++++-- 3 files changed, 107 insertions(+), 2 deletions(-) diff --git a/pping/pping.c b/pping/pping.c index 34a786d..6aea915 100644 --- a/pping/pping.c +++ b/pping/pping.c @@ -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, diff --git a/pping/pping.h b/pping/pping.h index ce995eb..0d53db9 100644 --- a/pping/pping.h +++ b/pping/pping.h @@ -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; diff --git a/pping/pping_kern.c b/pping/pping_kern.c index a6f6351..5898435 100644 --- a/pping/pping_kern.c +++ b/pping/pping_kern.c @@ -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); + } } /*