The new function mimics the semantics of 'hmap''s hmap_at_position(). It can be used to iterate through the classifier's rules when locking can't be used
Signed-off-by: Daniele Di Proietto <ddiproie...@vmware.com> --- lib/classifier.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/classifier.h | 6 ++++ 2 files changed, 101 insertions(+) diff --git a/lib/classifier.c b/lib/classifier.c index 00d47ac..c3b6877 100644 --- a/lib/classifier.c +++ b/lib/classifier.c @@ -1125,6 +1125,101 @@ classifier_lookup(const struct classifier *cls_, const struct flow *flow, return best ? best->cls_rule : NULL; } +static struct cls_match * +prio_list_at_position(struct cls_match * match, uint32_t *pri_offsetp) +{ + uint32_t pri_offset = *pri_offsetp, + i; + + for (i = 0; match; i++, match = next_rule_in_list(match)) { + if (i == pri_offset) { + if (next_rule_in_list(match)) { + *pri_offsetp = pri_offset + 1; + } else { + *pri_offsetp = 0; + } + + return match; + } + } + + *pri_offsetp = 0; + return NULL; +} + +/* Returns the next rule in 'cls_' in hash and list order, or NULL if no rules + * remain in 'cls_'. Uses '*bucketp's and '*offsetp's to determine where to + * begin iteration, and stores new values to pass on the next iteration + * into them before returning. + * + * It's better to use 'cls_cursor' and related functions, since they are + * faster. + * + * Before beginning iteration, store 0 into '*bucketp's and '*offsetp's. + */ +struct cls_rule * +classifier_at_position(const struct classifier *cls_, + uint32_t *subtbl_bucketp, uint32_t *subtbl_offsetp, + uint32_t *match_bucketp, uint32_t *match_offsetp, + uint32_t *pri_offsetp) +{ + struct cls_classifier *cls = cls_->cls; + + for (;;) { + struct hmap_node *subtbl_node, + *match_first_node; + struct cls_subtable *subtbl; + struct cls_match *first_match, + *match; + uint32_t match_bucket = *match_bucketp, + match_offset = *match_offsetp, + subtbl_bucket = *subtbl_bucketp, + subtbl_offset = *subtbl_offsetp; + + subtbl_node = hmap_at_position(&cls->subtables_map, &subtbl_bucket, + &subtbl_offset); + + if (!subtbl_node) { + return NULL; + } + + subtbl = CONTAINER_OF(subtbl_node, struct cls_subtable, hmap_node); + + match_first_node = hmap_at_position(&subtbl->rules, &match_bucket, + &match_offset); + + if (!match_first_node) { + *subtbl_bucketp = subtbl_bucket; + *subtbl_offsetp = subtbl_offset; + *match_bucketp = 0; + *match_offsetp = 0; + *pri_offsetp = 0; + continue; + } + + first_match = CONTAINER_OF(match_first_node, struct cls_match, hmap_node); + + match = prio_list_at_position(first_match, pri_offsetp); + + if (match_bucket == 0 && match_offset == 0) { + *subtbl_bucketp = subtbl_bucket; + *subtbl_offsetp = subtbl_offset; + } + + if (*pri_offsetp == 0) { + *match_bucketp = match_bucket; + *match_offsetp = match_offset; + } + + if (!match) { + continue; + } + + + return match->cls_rule; + } +} + /* Returns true if 'target' satisifies 'match', that is, if each bit for which * 'match' specifies a particular value has the correct value in 'target'. * diff --git a/lib/classifier.h b/lib/classifier.h index a89c562..5d98d36 100644 --- a/lib/classifier.h +++ b/lib/classifier.h @@ -339,6 +339,12 @@ struct cls_rule *cls_cursor_next(struct cls_cursor *, const struct cls_rule *); : 0); \ (RULE) = (NEXT)) +struct cls_rule * +classifier_at_position(const struct classifier *cls_, + uint32_t *subtbl_bucketp, uint32_t *subtbl_offsetp, + uint32_t *match_bucketp, uint32_t *match_offsetp, + uint32_t *pri_offset); + #ifdef __cplusplus } #endif -- 2.0.0.rc0 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev