Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com> Reviewed-by: YAMAMOTO Takashi <yamam...@valinux.co.jp> Acked-by: Ben Pfaff <b...@nicira.com> --- v5: rebase, no other changes.
ofproto/ofproto-dpif-xlate.c | 18 +++++++++---- ofproto/ofproto-dpif-xlate.h | 3 ++- ofproto/ofproto-dpif.c | 58 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 72 insertions(+), 7 deletions(-) diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 6e33a27..02b9538 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -106,6 +106,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 { @@ -367,7 +371,8 @@ static void xlate_xbridge_set(struct xbridge *xbridge, 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); static void xlate_xbundle_set(struct xbundle *xbundle, enum port_vlan_mode vlan_mode, int vlan, unsigned long *trunks, bool use_priority_tags, @@ -431,7 +436,8 @@ xlate_xbridge_set(struct xbridge *xbridge, 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) { if (xbridge->ml != ml) { mac_learning_unref(xbridge->ml); @@ -477,6 +483,7 @@ xlate_xbridge_set(struct xbridge *xbridge, 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; } static void @@ -552,7 +559,7 @@ xlate_xbridge_copy(struct xbridge *xbridge) xbridge->ipfix, xbridge->netflow, xbridge->frag, xbridge->forward_bpdu, xbridge->has_in_band, xbridge->enable_recirc, xbridge->variable_length_userdata, - xbridge->max_mpls_depth); + xbridge->max_mpls_depth, xbridge->masked_set_action); LIST_FOR_EACH (xbundle, list_node, &xbridge->xbundles) { xlate_xbundle_copy(new_xbridge, xbundle); } @@ -706,7 +713,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; @@ -726,7 +734,7 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name, xlate_xbridge_set(xbridge, dpif, miss_rule, no_packet_in_rule, ml, stp, ms, mbridge, sflow, ipfix, netflow, frag, forward_bpdu, has_in_band, enable_recirc, variable_length_userdata, - max_mpls_depth); + max_mpls_depth, masked_set_action); } static void diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h index b0dfc18..b9f95bc 100644 --- a/ofproto/ofproto-dpif-xlate.h +++ b/ofproto/ofproto-dpif-xlate.h @@ -153,7 +153,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); void xlate_remove_ofproto(struct ofproto_dpif *); void xlate_bundle_set(struct ofproto_dpif *, struct ofbundle *, diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index a635ca6..e2b746d 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -263,6 +263,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; @@ -602,7 +606,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, @@ -827,6 +832,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) @@ -923,6 +929,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(); error = dpif_recv_set(backer->dpif, backer->recv_set_enable); @@ -1113,6 +1120,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