summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/classifier.c107
-rw-r--r--lib/classifier.h25
-rw-r--r--lib/ovs-router.c2
-rw-r--r--tests/test-classifier.c2
4 files changed, 73 insertions, 63 deletions
diff --git a/lib/classifier.c b/lib/classifier.c
index ca79e6ce2..a4c99fae9 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -53,8 +53,7 @@ cls_match_alloc(struct cls_rule *rule)
}
static struct cls_subtable *find_subtable(const struct classifier *cls,
- const struct minimask *)
- OVS_REQUIRES(cls->mutex);
+ const struct minimask *);
static struct cls_subtable *insert_subtable(struct classifier *cls,
const struct minimask *)
OVS_REQUIRES(cls->mutex);
@@ -64,26 +63,41 @@ static struct cls_match *insert_rule(struct classifier *cls,
struct cls_subtable *, struct cls_rule *)
OVS_REQUIRES(cls->mutex);
-static struct cls_match *find_match_wc(const struct cls_subtable *,
- const struct flow *, struct trie_ctx *,
- unsigned int n_tries,
- struct flow_wildcards *);
-static struct cls_match *find_equal(struct cls_subtable *,
+static const struct cls_match *find_match_wc(const struct cls_subtable *,
+ const struct flow *,
+ struct trie_ctx *,
+ unsigned int n_tries,
+ struct flow_wildcards *);
+static struct cls_match *find_equal(const struct cls_subtable *,
const struct miniflow *, uint32_t hash);
+static inline const struct cls_match *
+next_rule_in_list__(const struct cls_match *rule)
+{
+ const struct cls_match *next = NULL;
+ next = OBJECT_CONTAINING(rculist_next(&rule->list), next, list);
+ return next;
+}
+
+static inline const struct cls_match *
+next_rule_in_list(const struct cls_match *rule)
+{
+ const struct cls_match *next = next_rule_in_list__(rule);
+ return next->priority < rule->priority ? next : NULL;
+}
+
static inline struct cls_match *
-next_rule_in_list__(struct cls_match *rule)
- OVS_NO_THREAD_SAFETY_ANALYSIS
+next_rule_in_list_protected__(struct cls_match *rule)
{
struct cls_match *next = NULL;
- next = OBJECT_CONTAINING(rculist_next(&rule->list), next, list);
+ next = OBJECT_CONTAINING(rculist_next_protected(&rule->list), next, list);
return next;
}
static inline struct cls_match *
-next_rule_in_list(struct cls_match *rule)
+next_rule_in_list_protected(struct cls_match *rule)
{
- struct cls_match *next = next_rule_in_list__(rule);
+ struct cls_match *next = next_rule_in_list_protected__(rule);
return next->priority < rule->priority ? next : NULL;
}
@@ -92,13 +106,9 @@ next_rule_in_list(struct cls_match *rule)
* protoceted by it. */
#define FOR_EACH_RULE_IN_LIST(RULE, HEAD) \
for ((RULE) = (HEAD); (RULE) != NULL; (RULE) = next_rule_in_list(RULE))
-#define FOR_EACH_RULE_IN_LIST_SAFE(RULE, NEXT, HEAD) \
- for ((RULE) = (HEAD); \
- (RULE) != NULL && ((NEXT) = next_rule_in_list(RULE), true); \
- (RULE) = (NEXT))
-
-static struct cls_match *next_rule_in_list__(struct cls_match *);
-static struct cls_match *next_rule_in_list(struct cls_match *);
+#define FOR_EACH_RULE_IN_LIST_PROTECTED(RULE, HEAD) \
+ for ((RULE) = (HEAD); (RULE) != NULL; \
+ (RULE) = next_rule_in_list_protected(RULE))
static unsigned int minimask_get_prefix_len(const struct minimask *,
const struct mf_field *);
@@ -379,7 +389,7 @@ trie_init(struct classifier *cls, int trie_idx, const struct mf_field *field)
CMAP_FOR_EACH (head, cmap_node, &subtable->rules) {
struct cls_match *match;
- FOR_EACH_RULE_IN_LIST (match, head) {
+ FOR_EACH_RULE_IN_LIST_PROTECTED (match, head) {
trie_insert(trie, match->cls_rule, plen);
}
}
@@ -468,13 +478,13 @@ static inline ovs_be32 minimatch_get_ports(const struct minimatch *match)
* inserting the new rule. In this case, no rules are displaced by the new
* rule, even rules that cannot have any effect because the new rule matches a
* superset of their flows and has higher priority. */
-struct cls_rule *
+const struct cls_rule *
classifier_replace(struct classifier *cls, struct cls_rule *rule)
OVS_EXCLUDED(cls->mutex)
{
struct cls_match *old_rule;
struct cls_subtable *subtable;
- struct cls_rule *old_cls_rule = NULL;
+ const struct cls_rule *old_cls_rule = NULL;
ovs_mutex_lock(&cls->mutex);
subtable = find_subtable(cls, &rule->match.mask);
@@ -515,7 +525,7 @@ classifier_replace(struct classifier *cls, struct cls_rule *rule)
} else {
old_cls_rule = old_rule->cls_rule;
rule->cls_match->partition = old_rule->partition;
- old_cls_rule->cls_match = NULL;
+ CONST_CAST(struct cls_rule *, old_cls_rule)->cls_match = NULL;
/* 'old_rule' contains a cmap_node, which may not be freed
* immediately. */
@@ -534,7 +544,7 @@ classifier_replace(struct classifier *cls, struct cls_rule *rule)
void
classifier_insert(struct classifier *cls, struct cls_rule *rule)
{
- struct cls_rule *displaced_rule = classifier_replace(cls, rule);
+ const struct cls_rule *displaced_rule = classifier_replace(cls, rule);
ovs_assert(!displaced_rule);
}
@@ -546,8 +556,8 @@ classifier_insert(struct classifier *cls, struct cls_rule *rule)
*
* Returns the removed rule, or NULL, if it was already removed.
*/
-struct cls_rule *
-classifier_remove(struct classifier *cls, struct cls_rule *rule)
+const struct cls_rule *
+classifier_remove(struct classifier *cls, const struct cls_rule *rule)
OVS_EXCLUDED(cls->mutex)
{
struct cls_partition *partition;
@@ -596,7 +606,7 @@ classifier_remove(struct classifier *cls, struct cls_rule *rule)
} else if (rculist_is_empty(&cls_match->list)) {
cmap_remove(&subtable->rules, &cls_match->cmap_node, hash);
} else {
- struct cls_match *next = next_rule_in_list(cls_match);
+ struct cls_match *next = next_rule_in_list_protected(cls_match);
rculist_remove(&cls_match->list);
cmap_replace(&subtable->rules, &cls_match->cmap_node,
@@ -637,7 +647,7 @@ classifier_remove(struct classifier *cls, struct cls_rule *rule)
cls->n_rules--;
ovsrcu_postpone(free, cls_match);
- rule->cls_match = NULL;
+ CONST_CAST(struct cls_rule *, rule)->cls_match = NULL;
unlock:
ovs_mutex_unlock(&cls->mutex);
@@ -675,7 +685,7 @@ trie_ctx_init(struct trie_ctx *ctx, const struct cls_trie *trie)
* set of bits that were significant in the lookup. At some point
* earlier, 'wc' should have been initialized (e.g., by
* flow_wildcards_init_catchall()). */
-struct cls_rule *
+const struct cls_rule *
classifier_lookup(const struct classifier *cls, const struct flow *flow,
struct flow_wildcards *wc)
{
@@ -723,7 +733,7 @@ classifier_lookup(const struct classifier *cls, const struct flow *flow,
best = NULL;
PVECTOR_FOR_EACH_PRIORITY(subtable, best_priority, 2,
sizeof(struct cls_subtable), &cls->subtables) {
- struct cls_match *rule;
+ const struct cls_match *rule;
if (!tag_intersects(tags, subtable->tag)) {
continue;
@@ -742,13 +752,13 @@ classifier_lookup(const struct classifier *cls, const struct flow *flow,
/* Finds and returns a rule in 'cls' with exactly the same priority and
* matching criteria as 'target'. Returns a null pointer if 'cls' doesn't
* contain an exact match. */
-struct cls_rule *
+const struct cls_rule *
classifier_find_rule_exactly(const struct classifier *cls,
const struct cls_rule *target)
OVS_EXCLUDED(cls->mutex)
{
- struct cls_match *head, *rule;
- struct cls_subtable *subtable;
+ const struct cls_match *head, *rule;
+ const struct cls_subtable *subtable;
ovs_mutex_lock(&cls->mutex);
subtable = find_subtable(cls, &target->match.mask);
@@ -778,11 +788,11 @@ out:
/* Finds and returns a rule in 'cls' with priority 'priority' and exactly the
* same matching criteria as 'target'. Returns a null pointer if 'cls' doesn't
* contain an exact match. */
-struct cls_rule *
+const struct cls_rule *
classifier_find_match_exactly(const struct classifier *cls,
const struct match *target, int priority)
{
- struct cls_rule *retval;
+ const struct cls_rule *retval;
struct cls_rule cr;
cls_rule_init(&cr, target, priority);
@@ -814,7 +824,7 @@ classifier_rule_overlaps(const struct classifier *cls,
CMAP_FOR_EACH (head, cmap_node, &subtable->rules) {
struct cls_match *rule;
- FOR_EACH_RULE_IN_LIST (rule, head) {
+ FOR_EACH_RULE_IN_LIST_PROTECTED (rule, head) {
if (rule->priority < target->priority) {
break; /* Rules in descending priority order. */
}
@@ -885,13 +895,13 @@ rule_matches(const struct cls_match *rule, const struct cls_rule *target)
&target->match.mask));
}
-static struct cls_match *
+static const struct cls_match *
search_subtable(const struct cls_subtable *subtable,
struct cls_cursor *cursor)
{
if (!cursor->target
|| !minimask_has_extra(&subtable->mask, &cursor->target->match.mask)) {
- struct cls_match *rule;
+ const struct cls_match *rule;
CMAP_CURSOR_FOR_EACH (rule, cmap_node, &cursor->rules,
&subtable->rules) {
@@ -929,7 +939,7 @@ struct cls_cursor cls_cursor_start(const struct classifier *cls,
ovs_mutex_lock(&cursor.cls->mutex);
CMAP_CURSOR_FOR_EACH (subtable, cmap_node, &cursor.subtables,
&cursor.cls->subtables_map) {
- struct cls_match *rule = search_subtable(subtable, &cursor);
+ const struct cls_match *rule = search_subtable(subtable, &cursor);
if (rule) {
cursor.subtable = subtable;
@@ -945,13 +955,13 @@ struct cls_cursor cls_cursor_start(const struct classifier *cls,
return cursor;
}
-static struct cls_rule *
+static const struct cls_rule *
cls_cursor_next(struct cls_cursor *cursor)
OVS_NO_THREAD_SAFETY_ANALYSIS
{
- struct cls_match *rule = cursor->rule->cls_match;
+ const struct cls_match *rule = cursor->rule->cls_match;
const struct cls_subtable *subtable;
- struct cls_match *next;
+ const struct cls_match *next;
next = next_rule_in_list__(rule);
if (next->priority < rule->priority) {
@@ -997,7 +1007,6 @@ cls_cursor_advance(struct cls_cursor *cursor)
static struct cls_subtable *
find_subtable(const struct classifier *cls, const struct minimask *mask)
- OVS_REQUIRES(cls->mutex)
{
struct cls_subtable *subtable;
@@ -1187,11 +1196,11 @@ miniflow_and_mask_matches_flow(const struct miniflow *flow,
return true;
}
-static inline struct cls_match *
+static inline const struct cls_match *
find_match(const struct cls_subtable *subtable, const struct flow *flow,
uint32_t hash)
{
- struct cls_match *rule;
+ const struct cls_match *rule;
CMAP_FOR_EACH_WITH_HASH (rule, cmap_node, hash, &subtable->rules) {
if (miniflow_and_mask_matches_flow(&rule->flow, &subtable->mask,
@@ -1249,13 +1258,13 @@ fill_range_wc(const struct cls_subtable *subtable, struct flow_wildcards *wc,
}
}
-static struct cls_match *
+static const struct cls_match *
find_match_wc(const struct cls_subtable *subtable, const struct flow *flow,
struct trie_ctx trie_ctx[CLS_MAX_TRIES], unsigned int n_tries,
struct flow_wildcards *wc)
{
uint32_t basis = 0, hash;
- struct cls_match *rule = NULL;
+ const struct cls_match *rule = NULL;
int i;
struct range ofs;
@@ -1338,7 +1347,7 @@ find_match_wc(const struct cls_subtable *subtable, const struct flow *flow,
}
static struct cls_match *
-find_equal(struct cls_subtable *subtable, const struct miniflow *flow,
+find_equal(const struct cls_subtable *subtable, const struct miniflow *flow,
uint32_t hash)
{
struct cls_match *head;
@@ -1409,7 +1418,7 @@ insert_rule(struct classifier *cls, struct cls_subtable *subtable,
* order of decreasing priority. */
struct cls_match *rule;
- FOR_EACH_RULE_IN_LIST (rule, head) {
+ FOR_EACH_RULE_IN_LIST_PROTECTED (rule, head) {
if (new->priority >= rule->priority) {
if (rule == head) {
/* 'new' is the new highest-priority flow in the list. */
diff --git a/lib/classifier.h b/lib/classifier.h
index 92be5bf2f..a884e2469 100644
--- a/lib/classifier.h
+++ b/lib/classifier.h
@@ -288,21 +288,22 @@ bool classifier_set_prefix_fields(struct classifier *,
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 *);
-
-struct cls_rule *classifier_remove(struct classifier *, struct cls_rule *);
-struct cls_rule *classifier_lookup(const struct classifier *,
- const struct flow *,
- struct flow_wildcards *);
+const struct cls_rule *classifier_replace(struct classifier *,
+ struct cls_rule *);
+const struct cls_rule *classifier_remove(struct classifier *,
+ const struct cls_rule *);
+const struct cls_rule *classifier_lookup(const struct classifier *,
+ const struct flow *,
+ struct flow_wildcards *);
bool classifier_rule_overlaps(const struct classifier *,
const struct cls_rule *);
-struct cls_rule *classifier_find_rule_exactly(const struct classifier *,
- const struct cls_rule *);
+const struct cls_rule *classifier_find_rule_exactly(const struct classifier *,
+ const struct cls_rule *);
-struct cls_rule *classifier_find_match_exactly(const struct classifier *,
- const struct match *,
- int priority);
+const struct cls_rule *classifier_find_match_exactly(const struct classifier *,
+ const struct match *,
+ int priority);
/* Iteration. */
@@ -312,7 +313,7 @@ struct cls_cursor {
const struct cls_rule *target;
struct cmap_cursor subtables;
struct cmap_cursor rules;
- struct cls_rule *rule;
+ const struct cls_rule *rule;
bool safe;
};
diff --git a/lib/ovs-router.c b/lib/ovs-router.c
index 8ed75089b..f1f5d1124 100644
--- a/lib/ovs-router.c
+++ b/lib/ovs-router.c
@@ -130,7 +130,7 @@ ovs_router_insert(ovs_be32 ip_dst, uint8_t plen, const char output_bridge[],
static bool
rt_entry_delete(uint8_t priority, ovs_be32 ip_dst, uint8_t plen)
{
- struct cls_rule *cr;
+ const struct cls_rule *cr;
struct cls_rule rule;
struct match match;
diff --git a/tests/test-classifier.c b/tests/test-classifier.c
index 66da60751..2848d01bc 100644
--- a/tests/test-classifier.c
+++ b/tests/test-classifier.c
@@ -405,7 +405,7 @@ compare_classifiers(struct classifier *cls, struct tcls *tcls)
assert(classifier_count(cls) == tcls->n_rules);
for (i = 0; i < confidence; i++) {
- struct cls_rule *cr0, *cr1, *cr2;
+ const struct cls_rule *cr0, *cr1, *cr2;
struct flow flow;
struct flow_wildcards wc;
unsigned int x;