[ovs-dev] [PATCH v2 04/19] classifier: Add support for invisible flows.

Jarno Rajahalme jrajahalme at nicira.com
Mon May 18 23:10:13 UTC 2015


This makes it possible to tentatively add flows to the classifier
without the datapath seeing them.

Signed-off-by: Jarno Rajahalme <jrajahalme at nicira.com>
---
 lib/classifier-private.h |    3 +-
 lib/classifier.c         |   68 +++++++++++++++++++++++++++++++++++++---------
 lib/classifier.h         |    1 +
 ofproto/ofproto.c        |    1 +
 utilities/ovs-ofctl.c    |    1 +
 5 files changed, 60 insertions(+), 14 deletions(-)

diff --git a/lib/classifier-private.h b/lib/classifier-private.h
index 4eed9e4..a7edbe9 100644
--- a/lib/classifier-private.h
+++ b/lib/classifier-private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Nicira, Inc.
+ * Copyright (c) 2014, 2015 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -79,6 +79,7 @@ struct cls_match {
                                                     * 'indices'. */
     /* Accessed by all readers. */
     struct cmap_node cmap_node; /* Within struct cls_subtable 'rules'. */
+    bool visible;
     const struct cls_rule *cls_rule;
     OVSRCU_TYPE(struct cls_conjunction_set *) conj_set;
     const struct miniflow flow; /* Matching rule. Mask is in the subtable. */
diff --git a/lib/classifier.c b/lib/classifier.c
index 68a3443..0cf42f6 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -99,6 +99,7 @@ cls_match_alloc(const struct cls_rule *rule,
     rculist_init(&cls_match->list);
     *CONST_CAST(const struct cls_rule **, &cls_match->cls_rule) = rule;
     *CONST_CAST(int *, &cls_match->priority) = rule->priority;
+    cls_match->visible = false;
     miniflow_clone_inline(CONST_CAST(struct miniflow *, &cls_match->flow),
                           &rule->match.flow, count);
     ovsrcu_set_hidden(&cls_match->conj_set,
@@ -136,6 +137,19 @@ next_rule_in_list(const struct cls_match *rule)
     return next->priority < rule->priority ? next : NULL;
 }
 
+/* Return the next lower-priority rule in the list that is visible.  */
+static inline const struct cls_match *
+next_visible_rule_in_list(const struct cls_match *rule)
+{
+    const struct cls_match *next = rule;
+
+    do {
+        next = next_rule_in_list(next);
+    } while (next && !next->visible);
+
+    return next;
+}
+
 static inline struct cls_match *
 next_rule_in_list_protected__(struct cls_match *rule)
 {
@@ -301,6 +315,17 @@ cls_rule_is_catchall(const struct cls_rule *rule)
 {
     return minimask_is_catchall(&rule->match.mask);
 }
+
+/* Rules inserted during classifier_defer() need to be made visible before
+ * calling classifier_publish().
+ */
+void cls_rule_make_visible(const struct cls_rule *rule)
+{
+    ovs_assert(rule->cls_match);   /* Must be in a classifier. */
+
+    rule->cls_match->visible = true;
+}
+
 
 /* Initializes 'cls' as a classifier that initially contains no classification
  * rules. */
@@ -623,8 +648,6 @@ classifier_replace(struct classifier *cls, const struct cls_rule *rule,
             new->partition = create_partition(cls, subtable, metadata);
         }
 
-        /* Make rule visible to lookups. */
-
         /* Add new node to segment indices.
          *
          * Readers may find the rule in the indices before the rule is visible
@@ -680,7 +703,10 @@ classifier_replace(struct classifier *cls, const struct cls_rule *rule,
 
                 /* No change in subtable's max priority or max count. */
 
-                /* Make rule visible to iterators. */
+                /* Make rule visible to lookups? */
+                new->visible = cls->publish;
+
+                /* Make rule visible to iterators (immediately). */
                 rculist_replace(CONST_CAST(struct rculist *, &rule->node),
                                 &old->node);
 
@@ -693,7 +719,10 @@ classifier_replace(struct classifier *cls, const struct cls_rule *rule,
         }
     }
 
-    /* Make rule visible to iterators. */
+    /* Make rule visible to lookups? */
+    new->visible = cls->publish;
+
+    /* Make rule visible to iterators (immediately). */
     rculist_push_back(&subtable->rules_list,
                       CONST_CAST(struct rculist *, &rule->node));
 
@@ -1200,7 +1229,7 @@ classifier_lookup__(const struct classifier *cls, struct flow *flow,
             }
 
             /* Find next-lower-priority flow with identical flow match. */
-            match = next_rule_in_list(soft[i]->match);
+            match = next_visible_rule_in_list(soft[i]->match);
             if (match) {
                 soft[i] = ovsrcu_get(struct cls_conjunction_set *,
                                      &match->conj_set);
@@ -1664,12 +1693,18 @@ static inline const struct cls_match *
 find_match(const struct cls_subtable *subtable, const struct flow *flow,
            uint32_t hash)
 {
-    const struct cls_match *rule;
+    const struct cls_match *head, *rule;
 
-    CMAP_FOR_EACH_WITH_HASH (rule, cmap_node, hash, &subtable->rules) {
-        if (miniflow_and_mask_matches_flow(&rule->flow, &subtable->mask,
-                                           flow)) {
-            return rule;
+    CMAP_FOR_EACH_WITH_HASH (head, cmap_node, hash, &subtable->rules) {
+        if (OVS_LIKELY(miniflow_and_mask_matches_flow(&head->flow,
+                                                      &subtable->mask,
+                                                      flow))) {
+            /* Return highest priority rule that is visible. */
+            FOR_EACH_RULE_IN_LIST(rule, head) {
+                if (OVS_LIKELY(rule->visible)) {
+                    return rule;
+                }
+            }
         }
     }
 
@@ -1768,10 +1803,17 @@ find_match_wc(const struct cls_subtable *subtable, const struct flow *flow,
          * (Rare) hash collisions may cause us to miss the opportunity for this
          * optimization. */
         if (!cmap_node_next(inode)) {
-            ASSIGN_CONTAINER(rule, inode - i, index_nodes);
-            if (miniflow_and_mask_matches_flow_wc(&rule->flow, &subtable->mask,
+            const struct cls_match *head;
+
+            ASSIGN_CONTAINER(head, inode - i, index_nodes);
+            if (miniflow_and_mask_matches_flow_wc(&head->flow, &subtable->mask,
                                                   flow, wc)) {
-                return rule;
+                /* Return highest priority rule that is visible. */
+                FOR_EACH_RULE_IN_LIST(rule, head) {
+                    if (OVS_LIKELY(rule->visible)) {
+                        return rule;
+                    }
+                }
             }
             return NULL;
         }
diff --git a/lib/classifier.h b/lib/classifier.h
index f9af33e..77c4458 100644
--- a/lib/classifier.h
+++ b/lib/classifier.h
@@ -285,6 +285,7 @@ void cls_rule_format(const struct cls_rule *, struct ds *);
 bool cls_rule_is_catchall(const struct cls_rule *);
 bool cls_rule_is_loose_match(const struct cls_rule *rule,
                              const struct minimatch *criteria);
+void cls_rule_make_visible(const struct cls_rule *rule);
 
 /* Constructor/destructor.  Must run single-threaded. */
 void classifier_init(struct classifier *, const uint8_t *flow_segments);
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 5c3b497..9c4e97d 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -4431,6 +4431,7 @@ add_flow(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
         ofproto_rule_unref(rule);
         return error;
     }
+    cls_rule_make_visible(&rule->cr);
     classifier_publish(&table->cls);
 
     learned_cookies_inc(ofproto, actions);
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 3d61c4b..54a5bb8 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -2403,6 +2403,7 @@ fte_insert(struct classifier *cls, const struct match *match,
 
         ovsrcu_postpone(fte_free, old);
     }
+    cls_rule_make_visible(&fte->rule);
 }
 
 /* Reads the flows in 'filename' as flow table entries in 'cls' for the version
-- 
1.7.10.4




More information about the dev mailing list