summaryrefslogtreecommitdiff
path: root/lib/classifier.c
diff options
context:
space:
mode:
authorJarno Rajahalme <jrajahalme@nicira.com>2014-06-13 10:38:05 -0700
committerJarno Rajahalme <jrajahalme@nicira.com>2014-06-26 08:38:09 -0700
commite9319757f1b67c890665033073cfe738bb5bcb5b (patch)
tree265a3b4602db737b954351dede1212d80931f307 /lib/classifier.c
parenta64759f02d8324caf6c37af0ac4e3e1d26e02a43 (diff)
downloadopenvswitch-e9319757f1b67c890665033073cfe738bb5bcb5b.tar.gz
lib/classifier: Add miniflow_and_mask_matches_flow_wc.
miniflow_and_mask_matches_flow_wc() fills in the masks in flow wildcards, so a separate step to that effect is no longer needed. Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'lib/classifier.c')
-rw-r--r--lib/classifier.c57
1 files changed, 43 insertions, 14 deletions
diff --git a/lib/classifier.c b/lib/classifier.c
index 7aa389f79..9b4a270f1 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -1367,8 +1367,7 @@ check_tries(struct trie_ctx trie_ctx[CLS_MAX_TRIES], unsigned int n_tries,
static inline bool
miniflow_and_mask_matches_flow(const struct miniflow *flow,
const struct minimask *mask,
- const struct flow *target,
- struct flow_wildcards *wc)
+ const struct flow *target)
{
const uint32_t *flowp = miniflow_get_u32_values(flow);
const uint32_t *maskp = miniflow_get_u32_values(&mask->masks);
@@ -1378,12 +1377,6 @@ miniflow_and_mask_matches_flow(const struct miniflow *flow,
uint32_t diff = (*flowp++ ^ flow_u32_value(target, idx)) & *maskp++;
if (diff) {
- /* Only unwildcard if none of the differing bits is already
- * exact-matched. */
- if (wc && !(flow_u32_value(&wc->masks, idx) & diff)) {
- /* Keep one bit of the difference. */
- *flow_u32_lvalue(&wc->masks, idx) |= rightmost_1bit(diff);
- }
return false;
}
}
@@ -1399,7 +1392,7 @@ find_match(const struct cls_subtable *subtable, const struct flow *flow,
HMAP_FOR_EACH_WITH_HASH (rule, hmap_node, hash, &subtable->rules) {
if (miniflow_and_mask_matches_flow(&rule->flow, &subtable->mask,
- flow, NULL)) {
+ flow)) {
return rule;
}
}
@@ -1407,6 +1400,42 @@ find_match(const struct cls_subtable *subtable, const struct flow *flow,
return NULL;
}
+/* Returns true if 'target' satisifies 'flow'/'mask', that is, if each bit
+ * for which 'flow', for which 'mask' has a bit set, specifies a particular
+ * value has the correct value in 'target'.
+ *
+ * This function is equivalent to miniflow_and_mask_matches_flow() but this
+ * version fills in the mask bits in 'wc'. */
+static inline bool
+miniflow_and_mask_matches_flow_wc(const struct miniflow *flow,
+ const struct minimask *mask,
+ const struct flow *target,
+ struct flow_wildcards *wc)
+{
+ const uint32_t *flowp = miniflow_get_u32_values(flow);
+ const uint32_t *maskp = miniflow_get_u32_values(&mask->masks);
+ uint32_t idx;
+
+ MAP_FOR_EACH_INDEX(idx, mask->masks.map) {
+ uint32_t mask = *maskp++;
+ uint32_t diff = (*flowp++ ^ flow_u32_value(target, idx)) & mask;
+
+ if (diff) {
+ /* Only unwildcard if none of the differing bits is already
+ * exact-matched. */
+ if (!(flow_u32_value(&wc->masks, idx) & diff)) {
+ /* Keep one bit of the difference. */
+ *flow_u32_lvalue(&wc->masks, idx) |= rightmost_1bit(diff);
+ }
+ return false;
+ }
+ /* Fill in the bits that were looked at. */
+ *flow_u32_lvalue(&wc->masks, idx) |= mask;
+ }
+
+ return true;
+}
+
static struct cls_match *
find_match_wc(const struct cls_subtable *subtable, const struct flow *flow,
struct trie_ctx trie_ctx[CLS_MAX_TRIES], unsigned int n_tries,
@@ -1449,11 +1478,11 @@ find_match_wc(const struct cls_subtable *subtable, const struct flow *flow,
* optimization. */
if (!inode->s) {
ASSIGN_CONTAINER(rule, inode - i, index_nodes);
- if (miniflow_and_mask_matches_flow(&rule->flow, &subtable->mask,
- flow, wc)) {
- goto out;
+ if (miniflow_and_mask_matches_flow_wc(&rule->flow, &subtable->mask,
+ flow, wc)) {
+ return rule;
}
- goto range_out;
+ return NULL;
}
}
ofs.end = FLOW_U32S;
@@ -1481,7 +1510,7 @@ find_match_wc(const struct cls_subtable *subtable, const struct flow *flow,
ofs.start = TP_PORTS_OFS32;
goto range_out;
}
-out:
+
/* Must unwildcard all the fields, as they were looked at. */
flow_wildcards_fold_minimask(wc, &subtable->mask);
return rule;