- * 'callback' is allowed to delete the rule that is passed as its argument, but
- * it must not delete (or move) any other rules in 'cls' that are in the same
- * table as the argument rule. Two rules are in the same table if their
- * cls_rule structs have the same table_idx; as a special case, a rule with
- * wildcards and an exact-match rule will never be in the same table. */
-void
-classifier_for_each_match(const struct classifier *cls,
- const struct cls_rule *target,
- int include, cls_cb_func *callback, void *aux)
-{
- if (include & CLS_INC_WILD) {
- const struct hmap *table;
-
- for (table = &cls->tables[0]; table < &cls->tables[CLS_N_FIELDS];
- table++) {
- struct cls_bucket *bucket, *next_bucket;
-
- HMAP_FOR_EACH_SAFE (bucket, next_bucket, hmap_node, table) {
- /* XXX there is a bit of room for optimization here based on
- * rejecting entire buckets on their fixed fields, but it will
- * only be worthwhile for big buckets (which we hope we won't
- * get anyway, but...) */
- struct cls_rule *prev_rule, *rule;
-
- /* We can't just use LIST_FOR_EACH_SAFE here because, if the
- * callback deletes the last rule in the bucket, then the
- * bucket itself will be destroyed. The bucket contains the
- * list head so that's a use-after-free error. */
- prev_rule = NULL;
- LIST_FOR_EACH (rule, node.list, &bucket->rules) {
- if (rules_match_1wild(rule, target, 0)) {
- if (prev_rule) {
- callback(prev_rule, aux);
- }
- prev_rule = rule;
- }
- }
- if (prev_rule) {
- callback(prev_rule, aux);
- }
- }
- }
- }
-
- if (include & CLS_INC_EXACT) {
- if (target->wc.wildcards) {
- struct cls_rule *rule, *next_rule;
-
- HMAP_FOR_EACH_SAFE (rule, next_rule, node.hmap,
- &cls->exact_table) {
- if (rules_match_1wild(rule, target, 0)) {
- callback(rule, aux);
- }
- }
- } else {
- /* Optimization: there can be at most one match in the exact
- * table. */
- size_t hash = flow_hash(&target->flow, 0);
- struct cls_rule *rule = search_exact_table(cls, hash,
- &target->flow);
- if (rule) {
- callback(rule, aux);
- }
- }
- }
-}
-
-/* 'callback' is allowed to delete the rule that is passed as its argument, but
- * it must not delete (or move) any other rules in 'cls' that are in the same
- * table as the argument rule. Two rules are in the same table if their
- * cls_rule structs have the same table_idx; as a special case, a rule with
- * wildcards and an exact-match rule will never be in the same table.