X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fclassifier.c;h=8d711a150a40017ad1a3205f50b010880fc54f73;hb=f1588b1f;hp=cdad9c9e1bc8caf44d32c48ec4680caabe2ff027;hpb=02dd3123a0e312f1d33403e744af52dd6096f12d;p=openvswitch diff --git a/lib/classifier.c b/lib/classifier.c index cdad9c9e..8d711a15 100644 --- a/lib/classifier.c +++ b/lib/classifier.c @@ -55,8 +55,8 @@ static bool rules_match_2wild(const struct cls_rule *wild1, /* Converts the flow in 'flow' into a cls_rule in 'rule', with the given * 'wildcards' and 'priority'.*/ void -cls_rule_from_flow(struct cls_rule *rule, const flow_t *flow, - uint32_t wildcards, unsigned int priority) +cls_rule_from_flow(const flow_t *flow, uint32_t wildcards, + unsigned int priority, struct cls_rule *rule) { assert(!flow->reserved[0] && !flow->reserved[1] && !flow->reserved[2]); rule->flow = *flow; @@ -66,13 +66,15 @@ cls_rule_from_flow(struct cls_rule *rule, const flow_t *flow, } /* Converts the ofp_match in 'match' into a cls_rule in 'rule', with the given - * 'priority'. */ + * 'priority'. If 'tun_id_from_cookie' is set then the upper 32 bits of + * 'cookie' are stored in the rule as the tunnel ID. */ void -cls_rule_from_match(struct cls_rule *rule, const struct ofp_match *match, - unsigned int priority) +cls_rule_from_match(const struct ofp_match *match, unsigned int priority, + bool tun_id_from_cookie, uint64_t cookie, + struct cls_rule *rule) { uint32_t wildcards; - flow_from_match(&rule->flow, &wildcards, match); + flow_from_match(match, tun_id_from_cookie, cookie, &rule->flow, &wildcards); flow_wildcards_init(&rule->wc, wildcards); rule->priority = rule->wc.wildcards ? priority : UINT16_MAX; rule->table_idx = table_idx_from_wildcards(rule->wc.wildcards); @@ -175,8 +177,7 @@ classifier_destroy(struct classifier *cls) struct hmap *tbl; for (tbl = &cls->tables[0]; tbl < &cls->tables[CLS_N_FIELDS]; tbl++) { - HMAP_FOR_EACH_SAFE (bucket, next_bucket, - struct cls_bucket, hmap_node, tbl) { + HMAP_FOR_EACH_SAFE (bucket, next_bucket, hmap_node, tbl) { free(bucket); } hmap_destroy(tbl); @@ -305,7 +306,7 @@ classifier_lookup_wild(const struct classifier *cls, const flow_t *flow) struct cls_rule target; int i; - cls_rule_from_flow(&target, flow, 0, 0); + cls_rule_from_flow(flow, 0, 0, &target); for (i = 0; i < CLS_N_FIELDS; i++) { struct cls_rule *rule = search_table(&cls->tables[i], i, &target); if (rule && (!best || rule->priority > best->priority)) { @@ -330,14 +331,14 @@ classifier_find_rule_exactly(const struct classifier *cls, return search_exact_table(cls, flow_hash(target, 0), target); } - assert(wildcards == (wildcards & OFPFW_ALL)); + assert(wildcards == (wildcards & OVSFW_ALL)); table_idx = table_idx_from_wildcards(wildcards); hash = hash_fields(target, table_idx); - HMAP_FOR_EACH_WITH_HASH (bucket, struct cls_bucket, hmap_node, hash, + HMAP_FOR_EACH_WITH_HASH (bucket, hmap_node, hash, &cls->tables[table_idx]) { if (equal_fields(&bucket->fixed, target, table_idx)) { struct cls_rule *pos; - LIST_FOR_EACH (pos, struct cls_rule, node.list, &bucket->rules) { + LIST_FOR_EACH (pos, node.list, &bucket->rules) { if (pos->priority < priority) { return NULL; } else if (pos->priority == priority && @@ -351,8 +352,8 @@ classifier_find_rule_exactly(const struct classifier *cls, return NULL; } -/* Checks if the flow defined by 'target' with 'wildcards' at 'priority' - * overlaps with any other rule at the same priority in the classifier. +/* Checks if the flow defined by 'target' with 'wildcards' at 'priority' + * overlaps with any other rule at the same priority in the classifier. * Two rules are considered overlapping if a packet could match both. */ bool classifier_rule_overlaps(const struct classifier *cls, @@ -367,18 +368,17 @@ classifier_rule_overlaps(const struct classifier *cls, true : false; } - cls_rule_from_flow(&target_rule, target, wildcards, priority); + cls_rule_from_flow(target, wildcards, priority, &target_rule); for (tbl = &cls->tables[0]; tbl < &cls->tables[CLS_N_FIELDS]; tbl++) { struct cls_bucket *bucket; - HMAP_FOR_EACH (bucket, struct cls_bucket, hmap_node, tbl) { + HMAP_FOR_EACH (bucket, hmap_node, tbl) { struct cls_rule *rule; - LIST_FOR_EACH (rule, struct cls_rule, node.list, - &bucket->rules) { - if (rule->priority == priority - && rules_match_2wild(rule, &target_rule, 0)) { + LIST_FOR_EACH (rule, node.list, &bucket->rules) { + if (rule->priority == priority + && rules_match_2wild(rule, &target_rule, 0)) { return true; } } @@ -407,8 +407,7 @@ classifier_for_each_match(const struct classifier *cls, table++) { struct cls_bucket *bucket, *next_bucket; - HMAP_FOR_EACH_SAFE (bucket, next_bucket, - struct cls_bucket, hmap_node, table) { + 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 @@ -420,8 +419,7 @@ classifier_for_each_match(const struct classifier *cls, * 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, struct cls_rule, node.list, - &bucket->rules) { + LIST_FOR_EACH (rule, node.list, &bucket->rules) { if (rules_match_1wild(rule, target, 0)) { if (prev_rule) { callback(prev_rule, aux); @@ -440,7 +438,7 @@ classifier_for_each_match(const struct classifier *cls, if (target->wc.wildcards) { struct cls_rule *rule, *next_rule; - HMAP_FOR_EACH_SAFE (rule, next_rule, struct cls_rule, node.hmap, + HMAP_FOR_EACH_SAFE (rule, next_rule, node.hmap, &cls->exact_table) { if (rules_match_1wild(rule, target, 0)) { callback(rule, aux); @@ -463,7 +461,10 @@ classifier_for_each_match(const struct classifier *cls, * 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. */ + * wildcards and an exact-match rule will never be in the same table. + * + * If 'include' is CLS_INC_EXACT then CLASSIFIER_FOR_EACH_EXACT_RULE(_SAFE) is + * probably easier to use. */ void classifier_for_each(const struct classifier *cls, int include, void (*callback)(struct cls_rule *, void *aux), @@ -475,8 +476,7 @@ classifier_for_each(const struct classifier *cls, int include, for (tbl = &cls->tables[0]; tbl < &cls->tables[CLS_N_FIELDS]; tbl++) { struct cls_bucket *bucket, *next_bucket; - HMAP_FOR_EACH_SAFE (bucket, next_bucket, - struct cls_bucket, hmap_node, tbl) { + HMAP_FOR_EACH_SAFE (bucket, next_bucket, hmap_node, tbl) { struct cls_rule *prev_rule, *rule; /* We can't just use LIST_FOR_EACH_SAFE here because, if the @@ -484,8 +484,7 @@ classifier_for_each(const struct classifier *cls, int include, * 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, struct cls_rule, node.list, - &bucket->rules) { + LIST_FOR_EACH (rule, node.list, &bucket->rules) { if (prev_rule) { callback(prev_rule, aux); } @@ -501,8 +500,7 @@ classifier_for_each(const struct classifier *cls, int include, if (include & CLS_INC_EXACT) { struct cls_rule *rule, *next_rule; - HMAP_FOR_EACH_SAFE (rule, next_rule, - struct cls_rule, node.hmap, &cls->exact_table) { + HMAP_FOR_EACH_SAFE (rule, next_rule, node.hmap, &cls->exact_table) { callback(rule, aux); } } @@ -639,15 +637,15 @@ static struct cls_rule * bucket_insert(struct cls_bucket *bucket, struct cls_rule *rule) { struct cls_rule *pos; - LIST_FOR_EACH (pos, struct cls_rule, node.list, &bucket->rules) { - if (pos->priority <= rule->priority) { - if (pos->priority == rule->priority - && pos->wc.wildcards == rule->wc.wildcards + LIST_FOR_EACH (pos, node.list, &bucket->rules) { + if (pos->priority == rule->priority) { + if (pos->wc.wildcards == rule->wc.wildcards && rules_match_1wild(pos, rule, rule->table_idx)) { list_replace(&rule->node.list, &pos->node.list); return pos; } + } else if (pos->priority < rule->priority) { break; } } @@ -677,8 +675,7 @@ static struct cls_bucket * find_bucket(struct hmap *table, size_t hash, const struct cls_rule *rule) { struct cls_bucket *bucket; - HMAP_FOR_EACH_WITH_HASH (bucket, struct cls_bucket, hmap_node, hash, - table) { + HMAP_FOR_EACH_WITH_HASH (bucket, hmap_node, hash, table) { if (equal_fields(&bucket->fixed, &rule->flow, rule->table_idx)) { return bucket; } @@ -826,10 +823,10 @@ static bool rules_match_2wild(const struct cls_rule *wild1, const struct cls_rule *wild2, int field_idx) { - return rules_match(wild1, wild2, - wild1->wc.wildcards | wild2->wc.wildcards, + return rules_match(wild1, wild2, + wild1->wc.wildcards | wild2->wc.wildcards, wild1->wc.nw_src_mask & wild2->wc.nw_src_mask, - wild1->wc.nw_dst_mask & wild2->wc.nw_dst_mask, + wild1->wc.nw_dst_mask & wild2->wc.nw_dst_mask, field_idx); } @@ -848,7 +845,7 @@ search_bucket(struct cls_bucket *bucket, int field_idx, return NULL; } - LIST_FOR_EACH (pos, struct cls_rule, node.list, &bucket->rules) { + LIST_FOR_EACH (pos, node.list, &bucket->rules) { if (rules_match_1wild(target, pos, field_idx)) { return pos; } @@ -876,7 +873,7 @@ search_table(const struct hmap *table, int field_idx, return search_bucket(bucket, field_idx, target); } - HMAP_FOR_EACH_WITH_HASH (bucket, struct cls_bucket, hmap_node, + HMAP_FOR_EACH_WITH_HASH (bucket, hmap_node, hash_fields(&target->flow, field_idx), table) { struct cls_rule *rule = search_bucket(bucket, field_idx, target); if (rule) { @@ -892,8 +889,7 @@ search_exact_table(const struct classifier *cls, size_t hash, { struct cls_rule *rule; - HMAP_FOR_EACH_WITH_HASH (rule, struct cls_rule, node.hmap, - hash, &cls->exact_table) { + HMAP_FOR_EACH_WITH_HASH (rule, node.hmap, hash, &cls->exact_table) { if (flow_equal(&rule->flow, target)) { return rule; }