diff options
-rw-r--r-- | include/openvswitch/match.h | 4 | ||||
-rw-r--r-- | lib/classifier.c | 19 | ||||
-rw-r--r-- | lib/classifier.h | 4 | ||||
-rw-r--r-- | lib/flow.h | 27 | ||||
-rw-r--r-- | lib/match.c | 44 |
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)); +} |