struct classifier {
int n_rules; /* Total number of rules. */
struct hmap tables; /* Contains "struct cls_table"s. */
+ struct list tables_priority; /* Tables in descending priority order */
};
/* A set of rules that all have the same fields wildcarded. */
struct cls_table {
struct hmap_node hmap_node; /* Within struct classifier 'tables' hmap. */
+ struct list list_node; /* Within classifier 'tables_priority_list' */
struct hmap rules; /* Contains "struct cls_rule"s. */
struct minimask mask; /* Wildcards for fields. */
int n_table_rules; /* Number of rules, including duplicates. */
+ unsigned int max_priority; /* Max priority of any rule in the table. */
+ unsigned int max_count; /* Count of max_priority rules. */
};
/* Returns true if 'table' is a "catch-all" table that will match every
struct cls_rule *classifier_replace(struct classifier *, struct cls_rule *);
void classifier_remove(struct classifier *, struct cls_rule *);
struct cls_rule *classifier_lookup(const struct classifier *,
- const struct flow *);
+ const struct flow *,
+ struct flow_wildcards *);
bool classifier_rule_overlaps(const struct classifier *,
const struct cls_rule *);
#define CLS_CURSOR_FOR_EACH(RULE, MEMBER, CURSOR) \
for (ASSIGN_CONTAINER(RULE, cls_cursor_first(CURSOR), MEMBER); \
- &(RULE)->MEMBER != NULL; \
+ RULE != OBJECT_CONTAINING(NULL, RULE, MEMBER); \
ASSIGN_CONTAINER(RULE, cls_cursor_next(CURSOR, &(RULE)->MEMBER), \
MEMBER))
#define CLS_CURSOR_FOR_EACH_SAFE(RULE, NEXT, MEMBER, CURSOR) \
for (ASSIGN_CONTAINER(RULE, cls_cursor_first(CURSOR), MEMBER); \
- (&(RULE)->MEMBER != NULL \
+ (RULE != OBJECT_CONTAINING(NULL, RULE, MEMBER) \
? ASSIGN_CONTAINER(NEXT, cls_cursor_next(CURSOR, &(RULE)->MEMBER), \
- MEMBER) \
+ MEMBER), 1 \
: 0); \
(RULE) = (NEXT))