Add counters to track emitted packets to each ofproto. Mark rules that have output actions that would result in packets being emitted outside OVS, and add new counters specific for those rules.
Signed-off-by: Gaetan Rivet <[email protected]> --- ofproto/ofproto-provider.h | 22 +++++++++++++++++-- ofproto/ofproto.c | 45 +++++++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index 3ca87748bf..c4feb1b01b 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -91,6 +91,16 @@ pkt_stats_add(struct pkt_stats *dst, struct pkt_stats src) src.n_offload_bytes); } +static inline void +pkt_stats_addmul(struct pkt_stats *dst, struct pkt_stats src, uint64_t n) +{ + src.n_packets = ovs_u64_safemul(src.n_packets, n); + src.n_bytes = ovs_u64_safemul(src.n_bytes, n); + src.n_offload_packets = ovs_u64_safemul(src.n_offload_packets, n); + src.n_offload_bytes = ovs_u64_safemul(src.n_offload_bytes, n); + pkt_stats_add(dst, src); +} + /* An OpenFlow switch. * * With few exceptions, ofproto implementations may look at these fields but @@ -139,6 +149,7 @@ struct ofproto { /* List of flows to remove from flow tables. */ struct rule_collection *to_remove OVS_GUARDED_BY(ofproto_mutex); struct pkt_stats removed_stats OVS_GUARDED_BY(ofproto_mutex); + struct pkt_stats removed_output_stats OVS_GUARDED_BY(ofproto_mutex); /* Meter table. */ struct ofputil_meter_features meter_features; @@ -174,7 +185,8 @@ void ofproto_init_max_ports(struct ofproto *, uint16_t max_ports); /* Read the current packet stats of this ofproto. * It sums each currently existing rule packet stats as well * as past, removed rules. */ -enum ofperr ofproto_get_pkt_stats(struct ofproto *, struct pkt_stats *) +enum ofperr ofproto_get_pkt_stats(struct ofproto *, struct pkt_stats *, + struct pkt_stats *) OVS_EXCLUDED(ofproto_mutex); struct ofproto *ofproto_lookup(const char *name); @@ -500,10 +512,16 @@ struct rule_actions { * 'has_meter' is true if 'ofpacts' contains an OFPACT_METER action. * * 'has_learn_with_delete' is true if 'ofpacts' contains an OFPACT_LEARN - * action whose flags include NX_LEARN_F_DELETE_LEARNED. */ + * action whose flags include NX_LEARN_F_DELETE_LEARNED. + * + * 'n_output' is set at least to 1 if any action output packets. + * Then for each additional OFPACT_OUTPUT actions it is + * incremented. + */ bool has_meter; bool has_learn_with_delete; bool has_groups; + uint8_t n_output; /* Actions. */ uint32_t ofpacts_len; /* Size of 'ofpacts', in bytes. */ diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 7b2f9a3fc0..f9a6b13d94 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -3262,6 +3262,8 @@ const struct rule_actions * rule_actions_create(const struct ofpact *ofpacts, size_t ofpacts_len) { struct rule_actions *actions; + bool has_output = false; + const struct ofpact *a; actions = xmalloc(sizeof *actions + ofpacts_len); actions->ofpacts_len = ofpacts_len; @@ -3274,6 +3276,31 @@ rule_actions_create(const struct ofpact *ofpacts, size_t ofpacts_len) actions->has_learn_with_delete = (next_learn_with_delete(actions, NULL) != NULL); + actions->n_output = 0; + OFPACT_FOR_EACH_FLATTENED (a, ofpacts, ofpacts_len) { + if (a->type == OFPACT_OUTPUT + || a->type == OFPACT_OUTPUT_TRUNC + || a->type == OFPACT_OUTPUT_REG) { + actions->n_output += 1; + } + if (a->type == OFPACT_OUTPUT + || a->type == OFPACT_OUTPUT_TRUNC + || a->type == OFPACT_OUTPUT_REG + || a->type == OFPACT_ENQUEUE + || a->type == OFPACT_CONTROLLER) { + has_output = true; + } + } + if (has_output && actions->n_output == 0) { + actions->n_output = 1; + } + /* Rules within a group are a rule set, not a rule list. + * It means if there are more than one 'output' action, only + * one of them will be executed. */ + if (actions->has_groups && actions->n_output > 1) { + actions->n_output = 1; + } + return actions; } @@ -4602,6 +4629,10 @@ rules_mark_for_removal(struct ofproto *ofproto, struct rule_collection *rules, ofproto->ofproto_class->rule_get_stats(rule, &stats, &used); pkt_stats_add(&ofproto->removed_stats, stats); + if (rule->actions->n_output) { + pkt_stats_addmul(&ofproto->removed_output_stats, stats, + rule->actions->n_output); + } } rule_collection_add(ofproto->to_remove, rule); } @@ -6379,9 +6410,12 @@ ofproto_rule_reduce_timeouts(struct rule *rule, } enum ofperr -ofproto_get_pkt_stats(struct ofproto *ofproto, struct pkt_stats *stats) +ofproto_get_pkt_stats(struct ofproto *ofproto, + struct pkt_stats *stats, + struct pkt_stats *output_stats) OVS_EXCLUDED(ofproto_mutex) { + struct pkt_stats removed_output_stats; struct pkt_stats removed_stats; struct rule_criteria criteria; struct rule_collection rules; @@ -6403,6 +6437,7 @@ ofproto_get_pkt_stats(struct ofproto *ofproto, struct pkt_stats *stats) rule_collection_ref(&rules); } removed_stats = ofproto->removed_stats; + removed_output_stats = ofproto->removed_output_stats; ovs_mutex_unlock(&ofproto_mutex); if (error) { @@ -6411,12 +6446,20 @@ ofproto_get_pkt_stats(struct ofproto *ofproto, struct pkt_stats *stats) *stats = removed_stats; + if (output_stats != NULL) { + *output_stats = removed_output_stats; + } + RULE_COLLECTION_FOR_EACH (rule, &rules) { struct pkt_stats rule_stats; long long int used; ofproto->ofproto_class->rule_get_stats(rule, &rule_stats, &used); pkt_stats_add(stats, rule_stats); + if (output_stats != NULL && rule->actions->n_output) { + pkt_stats_addmul(output_stats, rule_stats, + rule->actions->n_output); + } } rule_collection_unref(&rules); -- 2.34.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
