On Tue, Nov 19, 2013 at 11:20:37AM -0800, Jarno Rajahalme wrote: > Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
miniflow_get_map_in_range() is longer than I would ordinarily write as inline in a header file. Do you have a special reason to do that? I spent some time studying find_match_wc(). I think that the time for 'rl != rule' is equivalent to 'rule == NULL', because once we've narrowed the possibilities down to a single rule, that rule can't change as we look further (if it did, that would indicate a bug, I believe). Once I figured that out, it seemed that the logic could be simplified slightly, at least from my point of view. It also seemed like the relationship between find_match_wc() and find_match() could be simplified a bit. So here's what I suggest folding in, I'm curious to see what you think. Thanks, Ben. diff --git a/lib/classifier.c b/lib/classifier.c index 7f7aa84..f94cb96 100644 --- a/lib/classifier.c +++ b/lib/classifier.c @@ -41,8 +41,6 @@ static void update_subtables_after_removal(struct classifier *, struct cls_subtable *, unsigned int del_priority); -static struct cls_rule *find_match(const struct cls_subtable *, - const struct flow *); static struct cls_rule *find_match_wc(const struct cls_subtable *, const struct flow *, struct flow_wildcards *); @@ -397,8 +395,7 @@ classifier_lookup(const struct classifier *cls, const struct flow *flow, continue; } - rule = (wc) ? find_match_wc(subtable, flow, wc) - : find_match(subtable, flow); + rule = find_match_wc(subtable, flow, wc); if (rule) { best = rule; LIST_FOR_EACH_CONTINUE (subtable, list_node, @@ -412,8 +409,7 @@ classifier_lookup(const struct classifier *cls, const struct flow *flow, continue; } - rule = (wc) ? find_match_wc(subtable, flow, wc) - : find_match(subtable, flow); + rule = find_match_wc(subtable, flow, wc); if (rule && rule->priority > best->priority) { best = rule; } @@ -825,9 +821,9 @@ update_subtables_after_removal(struct classifier *cls, } static struct cls_rule * -find_match(const struct cls_subtable *subtable, const struct flow *flow) +find_match(const struct cls_subtable *subtable, const struct flow *flow, + uint32_t hash) { - uint32_t hash = flow_hash_in_minimask(flow, &subtable->mask, 0); struct cls_rule *rule; HMAP_FOR_EACH_WITH_HASH (rule, hmap_node, hash, &subtable->rules) { @@ -848,6 +844,11 @@ find_match_wc(const struct cls_subtable *subtable, const struct flow *flow, uint8_t prev_u32ofs = 0; int i; + if (!wc) { + return find_match(subtable, flow, + flow_hash_in_minimask(flow, &subtable->mask, 0)); + } + /* Try to finish early by checking fields in segments. */ for (i = 0; i < subtable->n_indices; i++) { struct hindex_node *inode; @@ -863,35 +864,37 @@ find_match_wc(const struct cls_subtable *subtable, const struct flow *flow, prev_u32ofs); return NULL; } - /* Check if we have narrowed down to a single rule already. This - * check shows a measurable benefit with non-trivial flow tables. - * (Rare) hash collisions may cause us to miss the opportunity for - * this optimization. */ - if (!inode->s) { - struct cls_rule *rl; - /* Found single candidate. */ - ASSIGN_CONTAINER(rl, inode - i, index_nodes); - /* Do not check same rule again. */ - if (rl != rule) { - rule = rl; /* Update last rule we looked at. */ - if (minimatch_matches_flow(&rule->match, flow)) { - /* Found match, no need to look further. */ - goto out; - } + + /* If we have narrowed down to a single rule already, check whether + * that rule matches. If it does match, then we're done. If it does + * not match, then we know that we will never get a match, but we do + * not yet know how many wildcards we need to fold into 'wc' so we + * continue iterating through indices to find that out. (We won't + * waste time calling minimatch_matches_flow() again because we've set + * 'rule' nonnull.) + * + * This check shows a measurable benefit with non-trivial flow tables. + * + * (Rare) hash collisions may cause us to miss the opportunity for this + * optimization. */ + if (!inode->s && !rule) { + ASSIGN_CONTAINER(rule, inode - i, index_nodes); + if (minimatch_matches_flow(&rule->match, flow)) { + goto out; } } } - /* Have 'rule' already only if there is a single non-matching rule. */ + if (!rule) { + /* Multiple potential matches exist, look for one. */ hash = flow_hash_in_minimask_range(flow, &subtable->mask, prev_u32ofs, FLOW_U32S, &basis); - HMAP_FOR_EACH_WITH_HASH (rule, hmap_node, hash, &subtable->rules) { - if (minimatch_matches_flow(&rule->match, flow)) { - goto out; - } - } + rule = find_match(subtable, flow, hash); + } else { + /* We already narrowed the matching candidates down to just 'rule', + * but it didn't match. */ + rule = NULL; } - rule = NULL; out: flow_wildcards_fold_minimask(wc, &subtable->mask); return rule; _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev