> Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com> Reviewed-by: YAMAMOTO Takashi <yamam...@valinux.co.jp>
> --- > ofproto/ofproto-dpif-xlate.c | 8 +++++- > ofproto/ofproto-dpif-xlate.h | 3 ++- > ofproto/ofproto-dpif.c | 58 > +++++++++++++++++++++++++++++++++++++++++- > 3 files changed, 66 insertions(+), 3 deletions(-) > > diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c > index 91ce7b7..b8c7aed 100644 > --- a/ofproto/ofproto-dpif-xlate.c > +++ b/ofproto/ofproto-dpif-xlate.c > @@ -102,6 +102,10 @@ struct xbridge { > /* Number of MPLS label stack entries that the datapath supports > * in matches. */ > size_t max_mpls_depth; > + > + /* True if the datapath supports masked data in OVS_ACTION_ATTR_SET > + * actions. */ > + bool masked_set_action; > }; > > struct xbundle { > @@ -264,7 +268,8 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const > char *name, > bool forward_bpdu, bool has_in_band, > bool enable_recirc, > bool variable_length_userdata, > - size_t max_mpls_depth) > + size_t max_mpls_depth, > + bool masked_set_action) > { > struct xbridge *xbridge = xbridge_lookup(ofproto); > > @@ -319,6 +324,7 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const > char *name, > xbridge->enable_recirc = enable_recirc; > xbridge->variable_length_userdata = variable_length_userdata; > xbridge->max_mpls_depth = max_mpls_depth; > + xbridge->masked_set_action = masked_set_action; > } > > void > diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h > index 8b53e10..31dec11 100644 > --- a/ofproto/ofproto-dpif-xlate.h > +++ b/ofproto/ofproto-dpif-xlate.h > @@ -140,7 +140,8 @@ void xlate_ofproto_set(struct ofproto_dpif *, const char > *name, > enum ofp_config_flags, bool forward_bpdu, > bool has_in_band, bool enable_recirc, > bool variable_length_userdata, > - size_t mpls_label_stack_length) > + size_t mpls_label_stack_length, > + bool masked_set_action) > OVS_REQ_WRLOCK(xlate_rwlock); > void xlate_remove_ofproto(struct ofproto_dpif *) > OVS_REQ_WRLOCK(xlate_rwlock); > > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > index a92fe81..c77465b 100644 > --- a/ofproto/ofproto-dpif.c > +++ b/ofproto/ofproto-dpif.c > @@ -262,6 +262,10 @@ struct dpif_backer { > * False if the datapath supports only 8-byte (or shorter) userdata. */ > bool variable_length_userdata; > > + /* True if the datapath supports masked data in OVS_ACTION_ATTR_SET > + * actions. */ > + bool masked_set_action; > + > /* Maximum number of MPLS label stack entries that the datapath supports > * in a match */ > size_t max_mpls_depth; > @@ -593,7 +597,8 @@ type_run(const char *type) > connmgr_has_in_band(ofproto->up.connmgr), > ofproto->backer->enable_recirc, > ofproto->backer->variable_length_userdata, > - ofproto->backer->max_mpls_depth); > + ofproto->backer->max_mpls_depth, > + ofproto->backer->masked_set_action); > > HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) { > xlate_bundle_set(ofproto, bundle, bundle->name, > @@ -818,6 +823,7 @@ struct odp_garbage { > static bool check_variable_length_userdata(struct dpif_backer *backer); > static size_t check_max_mpls_depth(struct dpif_backer *backer); > static bool check_recirc(struct dpif_backer *backer); > +static bool check_masked_set_action(struct dpif_backer *backer); > > static int > open_dpif_backer(const char *type, struct dpif_backer **backerp) > @@ -921,6 +927,7 @@ open_dpif_backer(const char *type, struct dpif_backer > **backerp) > backer->enable_recirc = check_recirc(backer); > backer->variable_length_userdata = > check_variable_length_userdata(backer); > backer->max_mpls_depth = check_max_mpls_depth(backer); > + backer->masked_set_action = check_masked_set_action(backer); > backer->rid_pool = recirc_id_pool_create(); > > if (backer->recv_set_enable) { > @@ -1108,6 +1115,55 @@ check_max_mpls_depth(struct dpif_backer *backer) > return n; > } > > +/* Tests whether 'backer''s datapath supports masked data in > + * OVS_ACTION_ATTR_SET actions. We need to disable some features on older > + * datapaths that don't support this feature. */ > +static bool > +check_masked_set_action(struct dpif_backer *backer) > +{ > + struct eth_header *eth; > + struct ofpbuf actions; > + struct dpif_execute execute; > + struct ofpbuf packet; > + int error; > + struct ovs_key_ethernet key, mask; > + > + /* Compose a set action that will cause an EINVAL error on older > + * datapaths that don't support masked set actions. > + * Avoid using a full mask, as it could be translated to a non-masked > + * set action instead. */ > + ofpbuf_init(&actions, 64); > + memset(&key, 0x53, sizeof key); > + memset(&mask, 0x7f, sizeof mask); > + commit_masked_set_action(&actions, OVS_KEY_ATTR_ETHERNET, &key, &mask, > + sizeof key); > + > + /* Compose a dummy ethernet packet. */ > + ofpbuf_init(&packet, ETH_HEADER_LEN); > + eth = ofpbuf_put_zeros(&packet, ETH_HEADER_LEN); > + eth->eth_type = htons(0x1234); > + > + /* Execute the actions. On older datapaths this fails with EINVAL, on > + * newer datapaths it succeeds. */ > + execute.actions = ofpbuf_data(&actions); > + execute.actions_len = ofpbuf_size(&actions); > + execute.packet = &packet; > + execute.md = PKT_METADATA_INITIALIZER(0); > + execute.needs_help = false; > + > + error = dpif_execute(backer->dpif, &execute); > + > + ofpbuf_uninit(&packet); > + ofpbuf_uninit(&actions); > + > + if (error) { > + /* Masked set action is not supported. */ > + VLOG_INFO("%s: datapath does not support masked set action feature.", > + dpif_name(backer->dpif)); > + } > + return !error; > +} > + > static int > construct(struct ofproto *ofproto_) > { > -- > 1.7.10.4 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev