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