Add a function to read current ofproto packet stats. It iterates over the ofproto rules and read their own counters. Removed rules will sum their own counters within ofproto upon being marked for removal.
These statistics show the overall processing work done by this ofproto datapath. As this work is counted separately between offload and software path, these counters reflect the dichotomy. Signed-off-by: Gaetan Rivet <[email protected]> --- ofproto/ofproto-provider.h | 33 +++++++++++++++----- ofproto/ofproto.c | 63 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 86 insertions(+), 10 deletions(-) diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index 7df3f52469..3ca87748bf 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -57,6 +57,7 @@ #include "simap.h" #include "timeval.h" #include "tun-metadata.h" +#include "util.h" #include "versions.h" #include "vl-mff-map.h" @@ -72,6 +73,24 @@ struct smap; extern struct ovs_mutex ofproto_mutex; +struct pkt_stats { + uint64_t n_packets; + uint64_t n_bytes; + uint64_t n_offload_packets; /* n_offload_packets are a subset n_packets */ + uint64_t n_offload_bytes; /* n_offload_bytes are a subset of n_bytes */ +}; + +static inline void +pkt_stats_add(struct pkt_stats *dst, struct pkt_stats src) +{ + dst->n_packets = ovs_u64_safeadd(dst->n_packets, src.n_packets); + dst->n_bytes = ovs_u64_safeadd(dst->n_bytes, src.n_bytes); + dst->n_offload_packets = ovs_u64_safeadd(dst->n_offload_packets, + src.n_offload_packets); + dst->n_offload_bytes = ovs_u64_safeadd(dst->n_offload_bytes, + src.n_offload_bytes); +} + /* An OpenFlow switch. * * With few exceptions, ofproto implementations may look at these fields but @@ -119,6 +138,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); /* Meter table. */ struct ofputil_meter_features meter_features; @@ -151,6 +171,12 @@ struct ofproto { void ofproto_init_tables(struct ofproto *, int n_tables); 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 *) + OVS_EXCLUDED(ofproto_mutex); + struct ofproto *ofproto_lookup(const char *name); struct ofport *ofproto_get_port(const struct ofproto *, ofp_port_t ofp_port); @@ -608,13 +634,6 @@ struct ofgroup { struct rule_collection rules OVS_GUARDED; /* Referring rules. */ }; -struct pkt_stats { - uint64_t n_packets; - uint64_t n_bytes; - uint64_t n_offload_packets; /* n_offload_packets are a subset n_packets */ - uint64_t n_offload_bytes; /* n_offload_bytes are a subset of n_bytes */ -}; - struct ofgroup *ofproto_group_lookup(const struct ofproto *ofproto, uint32_t group_id, ovs_version_t version, bool take_ref); diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index ec6d60a44f..7b2f9a3fc0 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -4589,12 +4589,20 @@ rule_criteria_destroy(struct rule_criteria *criteria) /* Adds rules to the 'to_remove' collection, so they can be destroyed * later all together. Destroys 'rules'. */ static void -rules_mark_for_removal(struct ofproto *ofproto, struct rule_collection *rules) +rules_mark_for_removal(struct ofproto *ofproto, struct rule_collection *rules, + bool keep_counts) OVS_REQUIRES(ofproto_mutex) { struct rule *rule; RULE_COLLECTION_FOR_EACH (rule, rules) { + if (keep_counts) { + struct pkt_stats stats; + long long int used; + + ofproto->ofproto_class->rule_get_stats(rule, &stats, &used); + pkt_stats_add(&ofproto->removed_stats, stats); + } rule_collection_add(ofproto->to_remove, rule); } rule_collection_destroy(rules); @@ -6048,7 +6056,9 @@ modify_flows_finish(struct ofproto *ofproto, struct ofproto_flow_mod *ofm, } } learned_cookies_flush(ofproto, &dead_cookies); - rules_mark_for_removal(ofproto, old_rules); + /* If modify_keep_counts is false, the provider will not port + * the counters to the new rule: they must be kept in ofproto. */ + rules_mark_for_removal(ofproto, old_rules, !ofm->modify_keep_counts); } return error; @@ -6156,7 +6166,7 @@ delete_flows_finish__(struct ofproto *ofproto, learned_cookies_dec(ofproto, rule_get_actions(rule), &dead_cookies); } - rules_mark_for_removal(ofproto, rules); + rules_mark_for_removal(ofproto, rules, true); learned_cookies_flush(ofproto, &dead_cookies); } @@ -6367,6 +6377,53 @@ ofproto_rule_reduce_timeouts(struct rule *rule, reduce_timeout(hard_timeout, &rule->hard_timeout); ovs_mutex_unlock(&rule->mutex); } + +enum ofperr +ofproto_get_pkt_stats(struct ofproto *ofproto, struct pkt_stats *stats) + OVS_EXCLUDED(ofproto_mutex) +{ + struct pkt_stats removed_stats; + struct rule_criteria criteria; + struct rule_collection rules; + struct minimatch match; + struct rule *rule; + enum ofperr error; + + /* Match *any* rule. */ + minimatch_init_catchall(&match); + rule_criteria_init(&criteria, OFPTT_ALL, &match, 0, + OVS_VERSION_MAX, 0, 0, + OFPP_ANY, OFPG_ANY); + minimatch_destroy(&match); + + ovs_mutex_lock(&ofproto_mutex); + error = collect_rules_loose(ofproto, &criteria, &rules); + rule_criteria_destroy(&criteria); + if (!error) { + rule_collection_ref(&rules); + } + removed_stats = ofproto->removed_stats; + ovs_mutex_unlock(&ofproto_mutex); + + if (error) { + return error; + } + + *stats = removed_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); + } + + rule_collection_unref(&rules); + rule_collection_destroy(&rules); + + return error; +} static enum ofperr handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh) -- 2.34.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
