2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 06:15:47 +00:00

lib/classifier: Lockless lookups.

Now that all the relevant classifier structures use RCU and internal
mutual exclusion for modifications, we can remove the fat-rwlock and
thus make the classifier lookups lockless.

As the readers are operating concurrently with the writers, a
concurrent reader may or may not see a new rule being added by a
writer, depending on how the concurrent events overlap with each
other.  Overall, this is no different from the former locked behavior,
but there the visibility of the new rule only depended on the timing
of the locking functions.

A new rule is first added to the segment indices, so the readers may
find the rule in the indices before the rule is visible in the
subtables 'rules' map.  This may result in us losing the opportunity
to quit lookups earlier, resulting in sub-optimal wildcarding.  This
will be fixed by forthcoming revalidation always scheduled after flow
table changes.

Similar behavior may happen due to us removing the overlapping rule
(if any) from the indices only after the corresponding new rule has
been added.

The subtable's max priority is updated only after a rule is inserted
to the maps, so the concurrent readers may not see the rule, as the
updated priority ordered subtable list will only be visible after the
subtable's max priority is updated.

Similarly, the classifier's partitions are updated by the caller after
the rule is inserted to the maps, so the readers may keep skipping the
subtable until they see the updated partitions.

Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: YAMAMOTO Takashi <yamamoto@valinux.co.jp>
This commit is contained in:
Jarno Rajahalme
2014-07-11 02:29:08 -07:00
parent f358a2cb2e
commit afae68b16f
9 changed files with 80 additions and 149 deletions

View File

@@ -214,7 +214,6 @@
* by a single writer. */
#include "cmap.h"
#include "fat-rwlock.h"
#include "match.h"
#include "meta-flow.h"
@@ -222,13 +221,9 @@
extern "C" {
#endif
/* Needed only for the lock annotation in struct classifier. */
extern struct ovs_mutex ofproto_mutex;
/* Classifier internal data structures. */
struct cls_classifier;
struct cls_subtable;
struct cls_partition;
struct cls_match;
enum {
@@ -237,7 +232,6 @@ enum {
/* A flow classifier. */
struct classifier {
struct fat_rwlock rwlock OVS_ACQ_AFTER(ofproto_mutex);
struct cls_classifier *cls;
};
@@ -266,38 +260,31 @@ 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 classifier_init(struct classifier *cls, const uint8_t *flow_segments);
void classifier_init(struct classifier *, const uint8_t *flow_segments);
void classifier_destroy(struct classifier *);
bool classifier_set_prefix_fields(struct classifier *cls,
bool classifier_set_prefix_fields(struct classifier *,
const enum mf_field_id *trie_fields,
unsigned int n_trie_fields)
OVS_REQ_WRLOCK(cls->rwlock);
unsigned int n_trie_fields);
bool classifier_is_empty(const struct classifier *cls);
int classifier_count(const struct classifier *cls)
OVS_REQ_RDLOCK(cls->rwlock);
void classifier_insert(struct classifier *cls, struct cls_rule *)
OVS_REQ_WRLOCK(cls->rwlock);
struct cls_rule *classifier_replace(struct classifier *cls, struct cls_rule *)
OVS_REQ_WRLOCK(cls->rwlock);
void classifier_remove(struct classifier *cls, struct cls_rule *)
OVS_REQ_WRLOCK(cls->rwlock);
struct cls_rule *classifier_lookup(const struct classifier *cls,
bool classifier_is_empty(const struct classifier *);
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_lookup(const struct classifier *,
const struct flow *,
struct flow_wildcards *)
OVS_REQ_RDLOCK(cls->rwlock);
struct flow_wildcards *);
void classifier_lookup_miniflow_batch(const struct classifier *cls,
const struct miniflow **flows,
struct cls_rule **rules, size_t len)
OVS_REQ_RDLOCK(cls->rwlock);
bool classifier_rule_overlaps(const struct classifier *cls,
const struct cls_rule *)
OVS_REQ_RDLOCK(cls->rwlock);
struct cls_rule **rules, size_t len);
bool classifier_rule_overlaps(const struct classifier *,
const struct cls_rule *);
struct cls_rule *classifier_find_rule_exactly(const struct classifier *cls,
struct cls_rule *classifier_find_rule_exactly(const struct classifier *,
const struct cls_rule *);
struct cls_rule *classifier_find_match_exactly(const struct classifier *cls,
struct cls_rule *classifier_find_match_exactly(const struct classifier *,
const struct match *,
unsigned int priority);