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:
Simon Sundberg
2023-10-24 16:18:35 +02:00
parent 0707ac084d
commit 35012a2804
3 changed files with 107 additions and 2 deletions
+61
View File
@@ -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,
+13
View File
@@ -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
View File
@@ -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);
}
}
/*