summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/openvswitch/match.h4
-rw-r--r--lib/classifier.c19
-rw-r--r--lib/classifier.h4
-rw-r--r--lib/flow.h27
-rw-r--r--lib/match.c44
5 files changed, 98 insertions, 0 deletions
diff --git a/include/openvswitch/match.h b/include/openvswitch/match.h
index e5cf1a0d7..49333ae8f 100644
--- a/include/openvswitch/match.h
+++ b/include/openvswitch/match.h
@@ -246,6 +246,7 @@ struct minimatch {
};
void minimatch_init(struct minimatch *, const struct match *);
+void minimatch_init_catchall(struct minimatch *);
void minimatch_clone(struct minimatch *, const struct minimatch *);
void minimatch_move(struct minimatch *dst, struct minimatch *src);
void minimatch_destroy(struct minimatch *);
@@ -253,6 +254,7 @@ void minimatch_destroy(struct minimatch *);
void minimatch_expand(const struct minimatch *, struct match *);
bool minimatch_equal(const struct minimatch *a, const struct minimatch *b);
+uint32_t minimatch_hash(const struct minimatch *, uint32_t basis);
bool minimatch_matches_flow(const struct minimatch *, const struct flow *);
@@ -262,6 +264,8 @@ void minimatch_format(const struct minimatch *, const struct tun_table *,
char *minimatch_to_string(const struct minimatch *,
const struct ofputil_port_map *, int priority);
+bool minimatch_has_default_hidden_fields(const struct minimatch *);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/classifier.c b/lib/classifier.c
index cea9053b6..edb40c89c 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -1223,6 +1223,25 @@ classifier_find_match_exactly(const struct classifier *cls,
return retval;
}
+/* Finds and returns a rule in 'cls' with priority 'priority' and exactly the
+ * same matching criteria as 'target', and that is visible in 'version'.
+ * Returns a null pointer if 'cls' doesn't contain an exact match visible in
+ * 'version'. */
+const struct cls_rule *
+classifier_find_minimatch_exactly(const struct classifier *cls,
+ const struct minimatch *target, int priority,
+ ovs_version_t version)
+{
+ const struct cls_rule *retval;
+ struct cls_rule cr;
+
+ cls_rule_init_from_minimatch(&cr, target, priority);
+ retval = classifier_find_rule_exactly(cls, &cr, version);
+ cls_rule_destroy(&cr);
+
+ return retval;
+}
+
/* Checks if 'target' would overlap any other rule in 'cls' in 'version'. Two
* rules are considered to overlap if both rules have the same priority and a
* packet could match both, and if both rules are visible in the same version.
diff --git a/lib/classifier.h b/lib/classifier.h
index 1263afdfd..d1bd4aa12 100644
--- a/lib/classifier.h
+++ b/lib/classifier.h
@@ -406,6 +406,10 @@ const struct cls_rule *classifier_find_match_exactly(const struct classifier *,
const struct match *,
int priority,
ovs_version_t);
+const struct cls_rule *classifier_find_minimatch_exactly(
+ const struct classifier *, const struct minimatch *,
+ int priority, ovs_version_t);
+
bool classifier_is_empty(const struct classifier *);
int classifier_count(const struct classifier *);
diff --git a/lib/flow.h b/lib/flow.h
index 3331e2068..5e41567b2 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -728,6 +728,11 @@ static inline ovs_be32 miniflow_get_be32(const struct miniflow *,
static inline uint16_t miniflow_get_vid(const struct miniflow *, size_t);
static inline uint16_t miniflow_get_tcp_flags(const struct miniflow *);
static inline ovs_be64 miniflow_get_metadata(const struct miniflow *);
+static inline uint64_t miniflow_get_tun_metadata_present_map(
+ const struct miniflow *);
+static inline uint32_t miniflow_get_recirc_id(const struct miniflow *);
+static inline uint32_t miniflow_get_dp_hash(const struct miniflow *);
+static inline ovs_be32 miniflow_get_ports(const struct miniflow *);
bool miniflow_equal(const struct miniflow *a, const struct miniflow *b);
bool miniflow_equal_in_minimask(const struct miniflow *a,
@@ -857,6 +862,27 @@ miniflow_get_metadata(const struct miniflow *flow)
return MINIFLOW_GET_BE64(flow, metadata);
}
+/* Returns the bitmap that indicates which tunnel metadata fields are present
+ * in 'flow'. */
+static inline uint64_t
+miniflow_get_tun_metadata_present_map(const struct miniflow *flow)
+{
+ return MINIFLOW_GET_U64(flow, tunnel.metadata.present.map);
+}
+
+/* Returns the recirc_id in 'flow.' */
+static inline uint32_t
+miniflow_get_recirc_id(const struct miniflow *flow)
+{
+ return MINIFLOW_GET_U32(flow, recirc_id);
+}
+
+/* Returns the dp_hash in 'flow.' */
+static inline uint32_t
+miniflow_get_dp_hash(const struct miniflow *flow)
+{
+ return MINIFLOW_GET_U32(flow, dp_hash);
+}
/* Returns the 'tp_src' and 'tp_dst' fields together as one piece of data. */
static inline ovs_be32
@@ -864,6 +890,7 @@ miniflow_get_ports(const struct miniflow *flow)
{
return MINIFLOW_GET_TYPE__(flow, ovs_be32, tp_src);
}
+
/* Returns the mask for the OpenFlow 1.1+ "metadata" field in 'mask'.
*
* The return value is all-1-bits if 'mask' matches on the whole value of the
diff --git a/lib/match.c b/lib/match.c
index 3eab0fd5d..2e9a80329 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -1667,6 +1667,15 @@ minimatch_init(struct minimatch *dst, const struct match *src)
dst->tun_md = tun_metadata_allocation_clone(&src->tun_md);
}
+/* Initializes 'match' as a "catch-all" match that matches every packet. */
+void
+minimatch_init_catchall(struct minimatch *match)
+{
+ match->flows[0] = xcalloc(2, sizeof *match->flow);
+ match->flows[1] = match->flows[0] + 1;
+ match->tun_md = NULL;
+}
+
/* Initializes 'dst' as a copy of 'src'. The caller must eventually free 'dst'
* with minimatch_destroy(). */
void
@@ -1718,6 +1727,16 @@ minimatch_equal(const struct minimatch *a, const struct minimatch *b)
&& miniflow_equal(a->flow, b->flow);
}
+/* Returns a hash value for the flow and wildcards in 'match', starting from
+ * 'basis'. */
+uint32_t
+minimatch_hash(const struct minimatch *match, uint32_t basis)
+{
+ size_t n_values = miniflow_n_values(match->flow);
+ size_t flow_size = sizeof *match->flow + MINIFLOW_VALUES_SIZE(n_values);
+ return hash_bytes(match->flow, 2 * flow_size, basis);
+}
+
/* Returns true if 'target' satisifies 'match', that is, if each bit for which
* 'match' specifies a particular value has the correct value in 'target'.
*
@@ -1771,3 +1790,28 @@ minimatch_to_string(const struct minimatch *match,
minimatch_expand(match, &megamatch);
return match_to_string(&megamatch, port_map, priority);
}
+
+static bool
+minimatch_has_default_recirc_id(const struct minimatch *m)
+{
+ uint32_t flow_recirc_id = miniflow_get_recirc_id(m->flow);
+ uint32_t mask_recirc_id = miniflow_get_recirc_id(&m->mask->masks);
+ return flow_recirc_id == 0 && (mask_recirc_id == UINT32_MAX ||
+ mask_recirc_id == 0);
+}
+
+static bool
+minimatch_has_default_dp_hash(const struct minimatch *m)
+{
+ return (!miniflow_get_dp_hash(m->flow)
+ && !miniflow_get_dp_hash(&m->mask->masks));
+}
+
+/* Return true if the hidden fields of the match are set to the default values.
+ * The default values equals to those set up by match_init_hidden_fields(). */
+bool
+minimatch_has_default_hidden_fields(const struct minimatch *m)
+{
+ return (minimatch_has_default_recirc_id(m)
+ && minimatch_has_default_dp_hash(m));
+}