As struct flow has grown larger, initializing one takes more resources. classifier_lookup_miniflow() takes struct miniflow as the search key, allowing simple search keys to be initialized touching only one cacheline, and without memsetting anything.
First users are introduced in userspace tunneling code. Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com> --- lib/classifier.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++ lib/classifier.h | 3 +++ tests/test-classifier.c | 8 +++++++- 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/lib/classifier.c b/lib/classifier.c index fe43bd1..40ac15e 100644 --- a/lib/classifier.c +++ b/lib/classifier.c @@ -880,6 +880,58 @@ classifier_lookup(const struct classifier *cls, const struct flow *flow, return best ? best->cls_rule : NULL; } +/* Returns true if 'target' satisifies 'match', that is, if each bit for which + * 'match' specifies a particular value has the correct value in 'target'. + * + * 'flow' and 'mask' have the same mask! */ +static bool +miniflow_and_mask_matches_miniflow(const struct miniflow *flow, + const struct minimask *mask, + const struct miniflow *target) +{ + const uint32_t *flowp = miniflow_get_u32_values(flow); + const uint32_t *maskp = miniflow_get_u32_values(&mask->masks); + uint32_t target_u32; + + MINIFLOW_FOR_EACH_IN_MAP(target_u32, target, mask->masks.map) { + if (OVS_UNLIKELY((*flowp++ ^ target_u32) & *maskp++)) { + return false; + } + } + + return true; +} + +/* Performs a classifier lookup with miniflow 'flow'. + * + * This function does not take a flow wildcards argument and hence + * skips most of the classifier wildcarding optimizations. */ +const struct cls_rule * +classifier_lookup_miniflow(const struct classifier *cls, + const struct miniflow *flow) +{ + struct cls_subtable *subtable; + int best_priority = INT_MIN; + const struct cls_match *best = NULL; + + PVECTOR_FOR_EACH_PRIORITY (subtable, best_priority, 2, + sizeof(struct cls_subtable), &cls->subtables) { + uint32_t hash = miniflow_hash_in_minimask(flow, &subtable->mask, 0); + struct cls_match *rule; + + CMAP_FOR_EACH_WITH_HASH (rule, cmap_node, hash, &subtable->rules) { + if (OVS_LIKELY(rule->priority > best_priority + && miniflow_and_mask_matches_miniflow( + &rule->flow, &subtable->mask, flow))) { + best_priority = rule->priority; + best = rule; + } + } + } + + return best ? best->cls_rule : NULL; +} + /* 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. */ diff --git a/lib/classifier.h b/lib/classifier.h index 2bd6fd3..c411da5 100644 --- a/lib/classifier.h +++ b/lib/classifier.h @@ -297,6 +297,9 @@ static inline void classifier_publish(struct classifier *); const struct cls_rule *classifier_lookup(const struct classifier *, const struct flow *, struct flow_wildcards *); +const struct cls_rule *classifier_lookup_miniflow(const struct classifier *, + const struct miniflow *); + bool classifier_rule_overlaps(const struct classifier *, const struct cls_rule *); const struct cls_rule *classifier_find_rule_exactly(const struct classifier *, diff --git a/tests/test-classifier.c b/tests/test-classifier.c index fde050b..3631fd9 100644 --- a/tests/test-classifier.c +++ b/tests/test-classifier.c @@ -405,9 +405,10 @@ compare_classifiers(struct classifier *cls, struct tcls *tcls) assert(classifier_count(cls) == tcls->n_rules); for (i = 0; i < confidence; i++) { - const struct cls_rule *cr0, *cr1, *cr2; + const struct cls_rule *cr0, *cr1, *cr2, *cr3; struct flow flow; struct flow_wildcards wc; + struct miniflow mf; unsigned int x; flow_wildcards_init_catchall(&wc); @@ -445,6 +446,11 @@ compare_classifiers(struct classifier *cls, struct tcls *tcls) } cr2 = classifier_lookup(cls, &flow, NULL); assert(cr2 == cr0); + + miniflow_init(&mf, &flow); + cr3 = classifier_lookup_miniflow(cls, &mf); + assert(cr3 == cr0); + miniflow_destroy(&mf); } } -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev