> 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

Reply via email to