Having a masked version allows generating better wildcarding. Signed-off-by: Jarno Rajahalme <ja...@ovn.org> --- include/openvswitch/meta-flow.h | 4 +++- include/openvswitch/ofp-parse.h | 4 ++-- lib/dpctl.c | 4 ++-- lib/meta-flow.c | 37 +++++++++++++++++++++++++++---------- lib/ofp-parse.c | 31 ++++++++++++++++--------------- ofproto/ofproto-dpif-xlate.c | 2 +- tests/test-odp.c | 2 +- 7 files changed, 52 insertions(+), 32 deletions(-)
diff --git a/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h index 533a4e6..900cd6a 100644 --- a/include/openvswitch/meta-flow.h +++ b/include/openvswitch/meta-flow.h @@ -2090,7 +2090,9 @@ void mf_set_flow_value_masked(const struct mf_field *, struct flow *); bool mf_is_tun_metadata(const struct mf_field *); bool mf_is_set(const struct mf_field *, const struct flow *); -void mf_mask_field(const struct mf_field *, struct flow *); +void mf_mask_field(const struct mf_field *, struct flow_wildcards *); +void mf_mask_field_masked(const struct mf_field *, const union mf_value *mask, + struct flow_wildcards *); int mf_field_len(const struct mf_field *, const union mf_value *value, const union mf_value *mask, bool *is_masked); diff --git a/include/openvswitch/ofp-parse.h b/include/openvswitch/ofp-parse.h index 1ab5095..a460d8a 100644 --- a/include/openvswitch/ofp-parse.h +++ b/include/openvswitch/ofp-parse.h @@ -61,8 +61,8 @@ char *parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *, enum ofputil_protocol *usable_protocols) OVS_WARN_UNUSED_RESULT; -char *parse_ofp_exact_flow(struct flow *flow, struct flow *mask, const char *s, - const struct simap *portno_names); +char *parse_ofp_exact_flow(struct flow *flow, struct flow_wildcards *wc, + const char *s, const struct simap *portno_names); char *parse_ofp_meter_mod_str(struct ofputil_meter_mod *, const char *string, int command, diff --git a/lib/dpctl.c b/lib/dpctl.c index 76b701c..b470ab0 100644 --- a/lib/dpctl.c +++ b/lib/dpctl.c @@ -802,8 +802,8 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p) } if (filter) { - char *err = parse_ofp_exact_flow(&flow_filter, &wc_filter.masks, - filter, &names_portno); + char *err = parse_ofp_exact_flow(&flow_filter, &wc_filter, filter, + &names_portno); if (err) { dpctl_error(dpctl_p, 0, "Failed to parse filter (%s)", err); error = EINVAL; diff --git a/lib/meta-flow.c b/lib/meta-flow.c index 503da0c..28079d7 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -1122,20 +1122,37 @@ mf_set_value(const struct mf_field *mf, } } -/* Unwildcard 'mask' member field described by 'mf'. The caller is - * responsible for ensuring that 'mask' meets 'mf''s prerequisites. */ +/* Unwildcard the bits in 'mask' of the 'wc' member field described by 'mf'. + * The caller is responsible for ensuring that 'wc' meets 'mf''s + * prerequisites. */ void -mf_mask_field(const struct mf_field *mf, struct flow *mask) +mf_mask_field_masked(const struct mf_field *mf, const union mf_value *mask, + struct flow_wildcards *wc) { - /* For MFF_DL_VLAN, we cannot send a all 1's to flow_set_dl_vlan() - * as that will be considered as OFP10_VLAN_NONE. So consider it as a - * special case. For the rest, calling mf_set_flow_value() is good - * enough. */ + union mf_value temp_mask; + /* For MFF_DL_VLAN, we cannot send a all 1's to flow_set_dl_vlan() as that + * will be considered as OFP10_VLAN_NONE. So make sure the mask only has + * valid bits in this case. */ if (mf->id == MFF_DL_VLAN) { - flow_set_dl_vlan(mask, htons(VLAN_VID_MASK)); - } else { - mf_set_flow_value(mf, &exact_match_mask, mask); + temp_mask.be16 = htons(VLAN_VID_MASK) & mask->be16; + mask = &temp_mask; + } + + union mf_value mask_value; + + mf_get_value(mf, &wc->masks, &mask_value); + for (size_t i = 0; i < mf->n_bytes; i++) { + mask_value.b[i] |= mask->b[i]; } + mf_set_flow_value(mf, &mask_value, &wc->masks); +} + +/* Unwildcard 'wc' member field described by 'mf'. The caller is + * responsible for ensuring that 'mask' meets 'mf''s prerequisites. */ +void +mf_mask_field(const struct mf_field *mf, struct flow_wildcards *wc) +{ + mf_mask_field_masked(mf, &exact_match_mask, wc); } static int diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index 370e3e5..73072d6 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -1115,23 +1115,23 @@ parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *fsr, /* Parses a specification of a flow from 's' into 'flow'. 's' must take the * form FIELD=VALUE[,FIELD=VALUE]... where each FIELD is the name of a * mf_field. Fields must be specified in a natural order for satisfying - * prerequisites. If 'mask' is specified, fills the mask field for each of the + * prerequisites. If 'wc' is specified, masks the field in 'wc' for each of the * field specified in flow. If the map, 'names_portno' is specfied, converts * the in_port name into port no while setting the 'flow'. * * Returns NULL on success, otherwise a malloc()'d string that explains the * problem. */ char * -parse_ofp_exact_flow(struct flow *flow, struct flow *mask, const char *s, - const struct simap *portno_names) +parse_ofp_exact_flow(struct flow *flow, struct flow_wildcards *wc, + const char *s, const struct simap *portno_names) { char *pos, *key, *value_s; char *error = NULL; char *copy; memset(flow, 0, sizeof *flow); - if (mask) { - memset(mask, 0, sizeof *mask); + if (wc) { + memset(wc, 0, sizeof *wc); } pos = copy = xstrdup(s); @@ -1143,8 +1143,8 @@ parse_ofp_exact_flow(struct flow *flow, struct flow *mask, const char *s, goto exit; } flow->dl_type = htons(p->dl_type); - if (mask) { - mask->dl_type = OVS_BE16_MAX; + if (wc) { + wc->masks.dl_type = OVS_BE16_MAX; } if (p->nw_proto) { @@ -1154,8 +1154,8 @@ parse_ofp_exact_flow(struct flow *flow, struct flow *mask, const char *s, goto exit; } flow->nw_proto = p->nw_proto; - if (mask) { - mask->nw_proto = UINT8_MAX; + if (wc) { + wc->masks.nw_proto = UINT8_MAX; } } } else { @@ -1185,8 +1185,9 @@ parse_ofp_exact_flow(struct flow *flow, struct flow *mask, const char *s, && simap_contains(portno_names, value_s)) { flow->in_port.ofp_port = u16_to_ofp( simap_get(portno_names, value_s)); - if (mask) { - mask->in_port.ofp_port = u16_to_ofp(ntohs(OVS_BE16_MAX)); + if (wc) { + wc->masks.in_port.ofp_port + = u16_to_ofp(ntohs(OVS_BE16_MAX)); } } else { field_error = mf_parse_value(mf, value_s, &value); @@ -1198,8 +1199,8 @@ parse_ofp_exact_flow(struct flow *flow, struct flow *mask, const char *s, } mf_set_flow_value(mf, &value, flow); - if (mask) { - mf_mask_field(mf, mask); + if (wc) { + mf_mask_field(mf, wc); } } } @@ -1214,8 +1215,8 @@ exit: if (error) { memset(flow, 0, sizeof *flow); - if (mask) { - memset(mask, 0, sizeof *mask); + if (wc) { + memset(wc, 0, sizeof *wc); } } return error; diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index a847557..c32d9bc 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -3545,7 +3545,7 @@ xlate_hash_fields_select_group(struct xlate_ctx *ctx, struct group_dpif *group) basis = hash_boolean(mf_is_set(mf, &ctx->xin->flow), basis); } - mf_mask_field(mf, &ctx->wc->masks); + mf_mask_field(mf, ctx->wc); } } diff --git a/tests/test-odp.c b/tests/test-odp.c index 8e4db09..dabfb85 100644 --- a/tests/test-odp.c +++ b/tests/test-odp.c @@ -163,7 +163,7 @@ parse_filter(char *filter_parse) memset(&flow_filter, 0, sizeof(flow_filter)); memset(&wc_filter, 0, sizeof(wc_filter)); - error = parse_ofp_exact_flow(&flow_filter, &wc_filter.masks, filter, + error = parse_ofp_exact_flow(&flow_filter, &wc_filter, filter, NULL); if (error) { ovs_fatal(0, "Failed to parse filter (%s)", error); -- 2.1.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev