Used in a future patch. Signed-off-by: Ethan Jackson <et...@nicira.com> --- lib/classifier.c | 47 ++++++++++++++++++++++++++++++----------------- lib/classifier.h | 5 +++-- lib/dpif-netdev.c | 2 +- 3 files changed, 34 insertions(+), 20 deletions(-)
diff --git a/lib/classifier.c b/lib/classifier.c index 330cd67..3479367 100644 --- a/lib/classifier.c +++ b/lib/classifier.c @@ -942,32 +942,45 @@ find_match_miniflow(const struct cls_subtable *subtable, return NULL; } -/* Finds and returns the highest-priority rule in 'cls' that matches - * 'miniflow'. Returns a null pointer if no rules in 'cls' match 'flow'. - * If multiple rules of equal priority match 'flow', returns one arbitrarily. +/* For each flow miniflow in 'flows' performs a classifier lookup writing the + * result into the corresponding slot in 'rules'. If a particular entry in + * 'flows' is NULL it is skipped. * - * This function is optimized for the userspace datapath, which only ever has - * one priority value for it's flows! - */ -struct cls_rule *classifier_lookup_miniflow_first(const struct classifier *cls_, - const struct miniflow *flow) + * This function is optimized for use in the userspace datapath and therefore + * does not implement a lot of features available in the standard + * classifier_lookup() function. Specifically, it does not implement + * priorities, instead returning any rule which matches the flow. */ +void +classifier_lookup_miniflow_batch(const struct classifier *cls_, + const struct miniflow **flows, + struct cls_rule **rules, size_t len) { struct cls_classifier *cls = cls_->cls; struct cls_subtable *subtable; + size_t i, begin = 0; + memset(rules, 0, len * sizeof *rules); PVECTOR_FOR_EACH (subtable, &cls->subtables) { - struct cls_match *rule; + for (i = begin; i < len; i++) { + struct cls_match *match; + uint32_t hash; - rule = find_match_miniflow(subtable, flow, - miniflow_hash_in_minimask(flow, - &subtable->mask, - 0)); - if (rule) { - return rule->cls_rule; + if (OVS_UNLIKELY(rules[i] || !flows[i])) { + continue; + } + + hash = miniflow_hash_in_minimask(flows[i], &subtable->mask, 0); + match = find_match_miniflow(subtable, flows[i], hash); + if (OVS_UNLIKELY(match)) { + rules[i] = match->cls_rule; + } } - } - return NULL; + for (; begin < len && (rules[begin] || !flows[begin]); begin++); + if (begin == len) { + break; + } + } } /* Finds and returns a rule in 'cls' with exactly the same priority and diff --git a/lib/classifier.h b/lib/classifier.h index 326ca08..602d504 100644 --- a/lib/classifier.h +++ b/lib/classifier.h @@ -286,8 +286,9 @@ struct cls_rule *classifier_lookup(const struct classifier *cls, const struct flow *, struct flow_wildcards *) OVS_REQ_RDLOCK(cls->rwlock); -struct cls_rule *classifier_lookup_miniflow_first(const struct classifier *cls, - const struct miniflow *) +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 *) diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 4deb763..3a2b68f 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -1078,7 +1078,7 @@ dp_netdev_lookup_flow(const struct dp_netdev *dp, const struct miniflow *key) struct dp_netdev_flow *netdev_flow; struct cls_rule *rule; - rule = classifier_lookup_miniflow_first(&dp->cls, key); + classifier_lookup_miniflow_batch(&dp->cls, &key, &rule, 1); netdev_flow = dp_netdev_flow_cast(rule); return netdev_flow; -- 1.8.1.2 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev