classifier already provides lockless lookups, and protected
modifications.  When user wants to remove a flow, we currently require
the flow to exist in the classifier.  To be thread safe, this requires
the caller to introduce their own mutex, lock it before a lookup, and
then issue classifier_remove() while the lock is still held.

This patch relaxes the "existence requirement" of the rule in
classifier_remove(), allowing it to be called on a rule that may have
already been removed from the classifier.  This allows users to do a
classifier_lookup() and classifier_remove() without additional
syncronization.

Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
---
 lib/classifier.c |   24 ++++++++++++++++++------
 lib/classifier.h |    2 +-
 2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/lib/classifier.c b/lib/classifier.c
index a5ffe85..f30ba95 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -770,22 +770,31 @@ classifier_insert(struct classifier *cls, struct cls_rule 
*rule)
 
 /* Removes 'rule' from 'cls'.  It is the caller's responsibility to destroy
  * 'rule' with cls_rule_destroy(), freeing the memory block in which 'rule'
- * resides, etc., as necessary. */
-void
+ * resides, etc., as necessary.
+ *
+ * Does nothing if 'rule' has been already removed, or was never inserted.
+ *
+ * Returns the removed rule, or NULL, if it was already removed.
+ */
+struct cls_rule *
 classifier_remove(struct classifier *cls, struct cls_rule *rule)
     OVS_EXCLUDED(cls->mutex)
 {
     struct cls_partition *partition;
-    struct cls_match *cls_match = rule->cls_match;
+    struct cls_match *cls_match;
     struct cls_match *head;
     struct cls_subtable *subtable;
     int i;
     uint32_t basis = 0, hash, ihash[CLS_MAX_INDICES];
     uint8_t prev_be32ofs = 0;
 
-    ovs_assert(cls_match);
-
     ovs_mutex_lock(&cls->mutex);
+    cls_match = rule->cls_match;
+    if (!cls_match) {
+        rule = NULL;
+        goto unlock; /* Already removed. */
+    }
+
     subtable = find_subtable(cls, &rule->match.mask);
     ovs_assert(subtable);
 
@@ -858,9 +867,12 @@ classifier_remove(struct classifier *cls, struct cls_rule 
*rule)
 
     cls->n_rules--;
 
-    rule->cls_match = NULL;
     ovsrcu_postpone(free, cls_match);
+    rule->cls_match = NULL;
+unlock:
     ovs_mutex_unlock(&cls->mutex);
+
+    return rule;
 }
 
 /* Prefix tree context.  Valid when 'lookup_done' is true.  Can skip all
diff --git a/lib/classifier.h b/lib/classifier.h
index f75d242..d1f4e86 100644
--- a/lib/classifier.h
+++ b/lib/classifier.h
@@ -291,7 +291,7 @@ int classifier_count(const struct classifier *);
 void classifier_insert(struct classifier *, struct cls_rule *);
 struct cls_rule *classifier_replace(struct classifier *, struct cls_rule *);
 
-void classifier_remove(struct classifier *, struct cls_rule *);
+struct cls_rule *classifier_remove(struct classifier *, struct cls_rule *);
 struct cls_rule *classifier_lookup(const struct classifier *,
                                    const struct flow *,
                                    struct flow_wildcards *);
-- 
1.7.10.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to