X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fclassifier.c;h=31a0e8b368382224705513d0f681aa8339f76b09;hb=003ce655b7116d18c86a74c50391e54990346931;hp=55ca5eabec1b586455ff83ea780645258140f82e;hpb=965607c850bb14e24905c46845d050f14105d923;p=sliver-openvswitch.git diff --git a/lib/classifier.c b/lib/classifier.c index 55ca5eabe..31a0e8b36 100644 --- a/lib/classifier.c +++ b/lib/classifier.c @@ -566,6 +566,68 @@ classifier_lookup(const struct classifier *cls, const struct flow *flow, return best; } +/* Returns true if 'target' satisifies 'match', that is, if each bit for which + * 'match' specifies a particular value has the correct value in 'target'. */ +static bool +minimatch_matches_miniflow(const struct minimatch *match, + const struct miniflow *target) +{ + const uint32_t *flowp = (const uint32_t *)match->flow.values; + const uint32_t *maskp = (const uint32_t *)match->mask.masks.values; + uint32_t target_u32; + + MINIFLOW_FOR_EACH_IN_MAP(target_u32, target, match->mask.masks.map) { + if ((*flowp++ ^ target_u32) & *maskp++) { + return false; + } + } + + return true; +} + +static inline struct cls_rule * +find_match_miniflow(const struct cls_subtable *subtable, + const struct miniflow *flow, + uint32_t hash) +{ + struct cls_rule *rule; + + HMAP_FOR_EACH_WITH_HASH (rule, hmap_node, hash, &subtable->rules) { + if (minimatch_matches_miniflow(&rule->match, flow)) { + return rule; + } + } + + return NULL; +} + +/* Finds and returns the highest-priority rule in 'cls' that matches + * 'miniflow'. Returns a null pointer if no rules in 'cls' match 'flow'. + * If multiple rules of equal priority match 'flow', returns one arbitrarily. + * + * This function is optimized for the userspace datapath, which only ever has + * one priority value for it's flows! + */ +struct cls_rule *classifier_lookup_miniflow_first(const struct classifier *cls, + const struct miniflow *flow) +{ + struct cls_subtable *subtable; + + LIST_FOR_EACH (subtable, list_node, &cls->subtables_priority) { + struct cls_rule *rule; + + rule = find_match_miniflow(subtable, flow, + miniflow_hash_in_minimask(flow, + &subtable->mask, + 0)); + if (rule) { + return rule; + } + } + + return NULL; +} + /* Finds and returns a rule in 'cls' with exactly the same priority and * matching criteria as 'target'. Returns a null pointer if 'cls' doesn't * contain an exact match. */