-const struct cls_field cls_fields[CLS_N_FIELDS + 1] = {
-#define CLS_FIELD(WILDCARDS, MEMBER, NAME) \
- { offsetof(flow_t, MEMBER), \
- sizeof ((flow_t *)0)->MEMBER, \
- WILDCARDS, \
- #NAME },
- CLS_FIELDS
-#undef CLS_FIELD
- { sizeof(flow_t), 0, 0, "exact" },
-};
-
-static uint32_t hash_fields(const flow_t *, int table_idx);
-static bool equal_fields(const flow_t *, const flow_t *, int table_idx);
-
-static int table_idx_from_wildcards(uint32_t wildcards);
-static struct cls_rule *table_insert(struct hmap *, struct cls_rule *);
-static struct cls_rule *insert_exact_rule(struct classifier *,
- struct cls_rule *);
-static struct cls_bucket *find_bucket(struct hmap *, size_t hash,
- const struct cls_rule *);
-static struct cls_rule *search_table(const struct hmap *table, int field_idx,
- const struct cls_rule *);
-static struct cls_rule *search_exact_table(const struct classifier *,
- size_t hash, const flow_t *);
-static bool rules_match_1wild(const struct cls_rule *fixed,
- const struct cls_rule *wild, int field_idx);
+static struct cls_table *find_table(const struct classifier *,
+ const struct flow_wildcards *);
+static struct cls_table *insert_table(struct classifier *,
+ const struct flow_wildcards *);
+
+static struct cls_table *classifier_first_table(const struct classifier *);
+static struct cls_table *classifier_next_table(const struct classifier *,
+ const struct cls_table *);
+static void destroy_table(struct classifier *, struct cls_table *);
+
+static bool should_include(const struct cls_table *, int include);
+
+static struct cls_rule *find_match(const struct cls_table *,
+ const struct flow *);
+static struct cls_rule *find_equal(struct cls_table *, const struct flow *,
+ uint32_t hash);
+static struct cls_rule *insert_rule(struct cls_table *, struct cls_rule *);
+
+static bool flow_equal_except(const struct flow *, const struct flow *,
+ const struct flow_wildcards *);
+static void zero_wildcards(struct flow *, const struct flow_wildcards *);
+
+/* Iterates RULE over HEAD and all of the cls_rules on HEAD->list. */
+#define FOR_EACH_RULE_IN_LIST(RULE, HEAD) \
+ for ((RULE) = (HEAD); (RULE) != NULL; (RULE) = next_rule_in_list(RULE))
+#define FOR_EACH_RULE_IN_LIST_SAFE(RULE, NEXT, HEAD) \
+ for ((RULE) = (HEAD); \
+ (RULE) != NULL && ((NEXT) = next_rule_in_list(RULE), true); \
+ (RULE) = (NEXT))
+
+static struct cls_rule *next_rule_in_list(struct cls_rule *);
+
+static struct cls_table *
+cls_table_from_hmap_node(const struct hmap_node *node)
+{
+ return node ? CONTAINER_OF(node, struct cls_table, hmap_node) : NULL;
+}
+
+static struct cls_rule *
+cls_rule_from_hmap_node(const struct hmap_node *node)
+{
+ return node ? CONTAINER_OF(node, struct cls_rule, hmap_node) : NULL;
+}
+
+/* Returns the cls_table within 'cls' that has no wildcards, or NULL if there
+ * is none. */
+struct cls_table *
+classifier_exact_table(const struct classifier *cls)
+{
+ struct flow_wildcards exact_wc;
+ flow_wildcards_init_exact(&exact_wc);
+ return find_table(cls, &exact_wc);
+}
+
+/* Returns the first rule in 'table', or a null pointer if 'table' is NULL. */
+struct cls_rule *
+cls_table_first_rule(const struct cls_table *table)
+{
+ return table ? cls_rule_from_hmap_node(hmap_first(&table->rules)) : NULL;
+}
+
+/* Returns the next rule in 'table' following 'rule', or a null pointer if
+ * 'rule' is the last rule in 'table'. */
+struct cls_rule *
+cls_table_next_rule(const struct cls_table *table, const struct cls_rule *rule)
+{
+ struct cls_rule *next
+ = CONTAINER_OF(rule->list.next, struct cls_rule, hmap_node);
+
+ return (next->priority < rule->priority
+ ? next
+ : cls_rule_from_hmap_node(hmap_next(&table->rules,
+ &next->hmap_node)));
+}
+
+static void
+cls_rule_init__(struct cls_rule *rule,
+ const struct flow *flow, uint32_t wildcards)
+{
+ rule->flow = *flow;
+ flow_wildcards_init(&rule->wc, wildcards);
+ cls_rule_zero_wildcards(rule);
+}