[ovs-dev] [LimitFlows 3/4] ofproto: Track various kinds of special types of flows.

Ben Pfaff blp at nicira.com
Mon Apr 19 21:08:50 UTC 2010


Until now, counting the number of subrules or other kinds of hidden rules
has required iterating through the flow table.  This commit makes ofproto
keep track of the number of flows in each important category as it inserts
and removes them, to avoid such iterations.  This immediately speeds up
table stats requests, although the value of doing that is doubtful.  More
importantly, it makes limiting table sizes more practical, which will be
implemented in an upcoming commit.
---
 ofproto/ofproto.c |   75 +++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 59 insertions(+), 16 deletions(-)

diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 3414b21..6498f7c 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -221,6 +221,9 @@ struct ofproto {
     long long int next_expiration;
     struct tag_set revalidate_set;
     bool tun_id_from_cookie;
+    int n_subrules;            /* # of rules in 'cls' with nonnull 'super'. */
+    int hidden_exact_rules;    /* # of hidden, exact, non-subrules in 'cls'. */
+    int hidden_wild_rules;     /* # of hidden wildcarded rules in 'cls'. */
 
     /* OpenFlow connections. */
     struct list all_conns;
@@ -1570,6 +1573,39 @@ rule_execute(struct ofproto *ofproto, struct rule *rule,
     }
 }
 
+/* Adds 'adjustment' to the counter in 'p' used for counting 'rule'.  (This is
+ * a no-op if 'rule' is not in a category that is specially tracked.) */
+static void
+rule_adjust_counter(struct ofproto *p, const struct rule *rule,
+                    int adjustment)
+{
+    if (rule_is_hidden(rule)) {
+        int *counter = (rule->super ? &p->n_subrules
+                        : rule->cr.wc.wildcards ? &p->hidden_wild_rules
+                        : &p->hidden_exact_rules);
+        *counter += adjustment;
+        assert(*counter >= 0);
+    }
+}
+
+/* Counts 'rule' in the various counters in 'p'.  This should be done just
+ * after inserting a rule into 'p''s flow table, to ensure that the counters
+ * are kept up-to-date. */
+static void
+rule_count(struct ofproto *p, const struct rule *rule)
+{
+    rule_adjust_counter(p, rule, 1);
+}
+
+/* Un-counts 'rule' in the various counters in 'p'.  This should be done just
+ * before removing a rule from 'p''s flow table, to ensure that the counters
+ * are kept up-to-date. */
+static void
+rule_uncount(struct ofproto *p, const struct rule *rule)
+{
+    rule_adjust_counter(p, rule, -1);
+}
+
 static void
 rule_insert(struct ofproto *p, struct rule *rule, struct ofpbuf *packet,
             uint16_t in_port)
@@ -1581,6 +1617,7 @@ rule_insert(struct ofproto *p, struct rule *rule, struct ofpbuf *packet,
     if (!rule->cr.wc.wildcards) {
         rule_make_actions(p, rule, packet);
     }
+    rule_count(p, rule);
 
     /* Send the packet and credit it to the rule. */
     if (packet) {
@@ -1600,6 +1637,7 @@ rule_insert(struct ofproto *p, struct rule *rule, struct ofpbuf *packet,
 
     /* Free the rule that was displaced, if any. */
     if (displaced_rule) {
+        rule_uncount(p, displaced_rule);
         rule_destroy(p, displaced_rule);
     }
 }
@@ -1615,6 +1653,7 @@ rule_create_subrule(struct ofproto *ofproto, struct rule *rule,
     cls_rule_from_flow(flow, 0, (rule->cr.priority <= UINT16_MAX ? UINT16_MAX
                         : rule->cr.priority), &subrule->cr);
     classifier_insert_exact(&ofproto->cls, &subrule->cr);
+    rule_count(ofproto, rule);
 
     return subrule;
 }
@@ -1622,6 +1661,7 @@ rule_create_subrule(struct ofproto *ofproto, struct rule *rule,
 static void
 rule_remove(struct ofproto *ofproto, struct rule *rule)
 {
+    rule_uncount(ofproto, rule);
     if (rule->cr.wc.wildcards) {
         COVERAGE_INC(ofproto_del_wc_flow);
         ofproto->need_revalidate = true;
@@ -2459,15 +2499,25 @@ handle_desc_stats_request(struct ofproto *p, struct ofconn *ofconn,
     return 0;
 }
 
-static void
-count_subrules(struct cls_rule *cls_rule, void *n_subrules_)
+/* Returns the number of exact-match flows in 'p''s flow table that are visible
+ * to OpenFlow.  (This excludes subrules and any exact-match rules set up
+ * internally.  Currently OVS doesn't ever set up any exact-match hidden rules,
+ * but it seems like a good idea to get this right in case OVS ever needs
+ * to.)  */
+static int
+ofproto_count_visible_exact(const struct ofproto *p)
 {
-    struct rule *rule = rule_from_cls_rule(cls_rule);
-    int *n_subrules = n_subrules_;
+    return (classifier_count_exact(&p->cls)
+            - p->n_subrules - p->hidden_exact_rules);
+}
 
-    if (rule->super) {
-        (*n_subrules)++;
-    }
+/* Returns the number of wildcarded flows in 'p''s flow table that are visible
+ * to OpenFlow.  (This excludes rules set up internally by OVS, e.g. by in-band
+ * control.)  */
+static int
+ofproto_count_visible_wild(const struct ofproto *p)
+{
+    return classifier_count_wild(&p->cls) - p->hidden_wild_rules;
 }
 
 static int
@@ -2477,16 +2527,9 @@ handle_table_stats_request(struct ofproto *p, struct ofconn *ofconn,
     struct ofp_table_stats *ots;
     struct ofpbuf *msg;
     struct odp_stats dpstats;
-    int n_exact, n_subrules, n_wild;
 
     msg = start_stats_reply(request, sizeof *ots * 2);
 
-    /* Count rules of various kinds. */
-    n_subrules = 0;
-    classifier_for_each(&p->cls, CLS_INC_EXACT, count_subrules, &n_subrules);
-    n_exact = classifier_count_exact(&p->cls) - n_subrules;
-    n_wild = classifier_count(&p->cls) - classifier_count_exact(&p->cls);
-
     /* Hash table. */
     dpif_get_dp_stats(p->dpif, &dpstats);
     ots = append_stats_reply(sizeof *ots, ofconn, &msg);
@@ -2494,8 +2537,8 @@ handle_table_stats_request(struct ofproto *p, struct ofconn *ofconn,
     ots->table_id = TABLEID_EXACT;
     strcpy(ots->name, "exact");
     ots->wildcards = htonl(0);
+    ots->active_count = htonl(ofproto_count_visible_exact(p));
     ots->max_entries = htonl(dpstats.max_capacity);
-    ots->active_count = htonl(n_exact);
     ots->lookup_count = htonll(dpstats.n_frags + dpstats.n_hit +
                                dpstats.n_missed);
     ots->matched_count = htonll(dpstats.n_hit); /* XXX */
@@ -2507,8 +2550,8 @@ handle_table_stats_request(struct ofproto *p, struct ofconn *ofconn,
     strcpy(ots->name, "wildcard");
     ots->wildcards = p->tun_id_from_cookie ? htonl(OVSFW_ALL)
                                            : htonl(OFPFW_ALL);
+    ots->active_count = htonl(ofproto_count_visible_wild(p));
     ots->max_entries = htonl(65536);
-    ots->active_count = htonl(n_wild);
     ots->lookup_count = htonll(0);              /* XXX */
     ots->matched_count = htonll(0);             /* XXX */
 
-- 
1.6.6.1





More information about the dev mailing list