On Thu, Nov 01, 2018 at 05:19:30AM -0700, Slava Ovsiienko wrote:
> This part of patchset adds support of VXLAN-related items and
> actions to the flow translation routine. Later some tunnel types,
> other than VXLAN can be addedd (GRE). No VTEP devices are created at
> this point, the flow rule is just translated, not applied yet.
> 
> Suggested-by: Adrien Mazarguil <adrien.mazarg...@6wind.com>
> Signed-off-by: Viacheslav Ovsiienko <viachesl...@mellanox.com>
> ---
>  drivers/net/mlx5/mlx5_flow_tcf.c | 535 
> ++++++++++++++++++++++++++++++++++-----
>  1 file changed, 472 insertions(+), 63 deletions(-)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow_tcf.c 
> b/drivers/net/mlx5/mlx5_flow_tcf.c
> index b5be264..c404a63 100644
> --- a/drivers/net/mlx5/mlx5_flow_tcf.c
> +++ b/drivers/net/mlx5/mlx5_flow_tcf.c
> @@ -2020,8 +2020,8 @@ struct pedit_parser {
>                       if (ret < 0)
>                               return ret;
>                       item_flags |= (item_flags & MLX5_FLOW_LAYER_TUNNEL) ?
> -                                     MLX5_FLOW_LAYER_INNER_L2 :
> -                                     MLX5_FLOW_LAYER_OUTER_L2;
> +                                             MLX5_FLOW_LAYER_INNER_L2 :
> +                                             MLX5_FLOW_LAYER_OUTER_L2;

Irrelevant. Please remove.

>                       /* TODO:
>                        * Redundant check due to different supported mask.
>                        * Same for the rest of items.
> @@ -2179,7 +2179,7 @@ struct pedit_parser {
>                               return -rte_errno;
>                       break;
>               case RTE_FLOW_ITEM_TYPE_VXLAN:
> -                     if (!(action_flags & RTE_FLOW_ACTION_TYPE_VXLAN_DECAP))
> +                     if (!(action_flags & MLX5_FLOW_ACTION_VXLAN_DECAP))

Shouldn't this be fixed in patch [6/13]?

>                               return rte_flow_error_set
>                                       (error, ENOTSUP,
>                                        RTE_FLOW_ERROR_TYPE_ITEM,
> @@ -2762,6 +2762,241 @@ struct pedit_parser {
>  }
>  
>  /**
> + * Convert VXLAN VNI to 32-bit integer.
> + *
> + * @param[in] vni
> + *   VXLAN VNI in 24-bit wire format.
> + *
> + * @return
> + *   VXLAN VNI as a 32-bit integer value in network endian.
> + */
> +static inline rte_be32_t
> +vxlan_vni_as_be32(const uint8_t vni[3])
> +{
> +     union {
> +             uint8_t vni[4];
> +             rte_be32_t dword;
> +     } ret = {
> +             .vni = { 0, vni[0], vni[1], vni[2] },
> +     };
> +     return ret.dword;
> +}
> +
> +/**
> + * Helper function to process RTE_FLOW_ITEM_TYPE_ETH entry in configuration
> + * of action RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP. Fills the MAC address fields
> + * in the encapsulation parameters structure. The item must be prevalidated,
> + * no any validation checks performed by function.
> + *
> + * @param[in] spec
> + *   RTE_FLOW_ITEM_TYPE_ETH entry specification.
> + * @param[in] mask
> + *   RTE_FLOW_ITEM_TYPE_ETH entry mask.
> + * @param[out] encap
> + *   Structure to fill the gathered MAC address data.
> + */
> +static void
> +flow_tcf_parse_vxlan_encap_eth(const struct rte_flow_item_eth *spec,
> +                            const struct rte_flow_item_eth *mask,
> +                            struct flow_tcf_vxlan_encap *encap)
> +{
> +     /* Item must be validated before. No redundant checks. */
> +     assert(spec);
> +     if (!mask || !memcmp(&mask->dst,
> +                          &rte_flow_item_eth_mask.dst,
> +                          sizeof(rte_flow_item_eth_mask.dst))) {
> +             /*
> +              * Ethernet addresses are not supported by
> +              * tc as tunnel_key parameters. Destination
> +              * address is needed to form encap packet
> +              * header and retrieved by kernel from
> +              * implicit sources (ARP table, etc),
> +              * address masks are not supported at all.
> +              */
> +             encap->eth.dst = spec->dst;
> +             encap->mask |= FLOW_TCF_ENCAP_ETH_DST;
> +     }
> +     if (!mask || !memcmp(&mask->src,
> +                          &rte_flow_item_eth_mask.src,
> +                          sizeof(rte_flow_item_eth_mask.src))) {
> +             /*
> +              * Ethernet addresses are not supported by
> +              * tc as tunnel_key parameters. Source ethernet
> +              * address is ignored anyway.
> +              */
> +             encap->eth.src = spec->src;
> +             encap->mask |= FLOW_TCF_ENCAP_ETH_SRC;
> +     }
> +}
> +
> +/**
> + * Helper function to process RTE_FLOW_ITEM_TYPE_IPV4 entry in configuration
> + * of action RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP. Fills the IPV4 address fields
> + * in the encapsulation parameters structure. The item must be prevalidated,
> + * no any validation checks performed by function.
> + *
> + * @param[in] spec
> + *   RTE_FLOW_ITEM_TYPE_IPV4 entry specification.
> + * @param[out] encap
> + *   Structure to fill the gathered IPV4 address data.
> + */
> +static void
> +flow_tcf_parse_vxlan_encap_ipv4(const struct rte_flow_item_ipv4 *spec,
> +                             struct flow_tcf_vxlan_encap *encap)
> +{
> +     /* Item must be validated before. No redundant checks. */
> +     assert(spec);
> +     encap->ipv4.dst = spec->hdr.dst_addr;
> +     encap->ipv4.src = spec->hdr.src_addr;
> +     encap->mask |= FLOW_TCF_ENCAP_IPV4_SRC |
> +                    FLOW_TCF_ENCAP_IPV4_DST;
> +}
> +
> +/**
> + * Helper function to process RTE_FLOW_ITEM_TYPE_IPV6 entry in configuration
> + * of action RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP. Fills the IPV6 address fields
> + * in the encapsulation parameters structure. The item must be prevalidated,
> + * no any validation checks performed by function.
> + *
> + * @param[in] spec
> + *   RTE_FLOW_ITEM_TYPE_IPV6 entry specification.
> + * @param[out] encap
> + *   Structure to fill the gathered IPV6 address data.
> + */
> +static void
> +flow_tcf_parse_vxlan_encap_ipv6(const struct rte_flow_item_ipv6 *spec,
> +                             struct flow_tcf_vxlan_encap *encap)
> +{
> +     /* Item must be validated before. No redundant checks. */
> +     assert(spec);
> +     memcpy(encap->ipv6.dst, spec->hdr.dst_addr, sizeof(encap->ipv6.dst));
> +     memcpy(encap->ipv6.src, spec->hdr.src_addr, sizeof(encap->ipv6.src));
> +     encap->mask |= FLOW_TCF_ENCAP_IPV6_SRC |
> +                    FLOW_TCF_ENCAP_IPV6_DST;
> +}
> +
> +/**
> + * Helper function to process RTE_FLOW_ITEM_TYPE_UDP entry in configuration
> + * of action RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP. Fills the UDP port fields
> + * in the encapsulation parameters structure. The item must be prevalidated,
> + * no any validation checks performed by function.
> + *
> + * @param[in] spec
> + *   RTE_FLOW_ITEM_TYPE_UDP entry specification.
> + * @param[in] mask
> + *   RTE_FLOW_ITEM_TYPE_UDP entry mask.
> + * @param[out] encap
> + *   Structure to fill the gathered UDP port data.
> + */
> +static void
> +flow_tcf_parse_vxlan_encap_udp(const struct rte_flow_item_udp *spec,
> +                            const struct rte_flow_item_udp *mask,
> +                            struct flow_tcf_vxlan_encap *encap)
> +{
> +     assert(spec);
> +     encap->udp.dst = spec->hdr.dst_port;
> +     encap->mask |= FLOW_TCF_ENCAP_UDP_DST;
> +     if (!mask || mask->hdr.src_port != RTE_BE16(0x0000)) {
> +             encap->udp.src = spec->hdr.src_port;
> +             encap->mask |= FLOW_TCF_ENCAP_IPV4_SRC;
> +     }
> +}
> +
> +/**
> + * Helper function to process RTE_FLOW_ITEM_TYPE_VXLAN entry in configuration
> + * of action RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP. Fills the VNI fields
> + * in the encapsulation parameters structure. The item must be prevalidated,
> + * no any validation checks performed by function.
> + *
> + * @param[in] spec
> + *   RTE_FLOW_ITEM_TYPE_VXLAN entry specification.
> + * @param[out] encap
> + *   Structure to fill the gathered VNI address data.
> + */
> +static void
> +flow_tcf_parse_vxlan_encap_vni(const struct rte_flow_item_vxlan *spec,
> +                            struct flow_tcf_vxlan_encap *encap)
> +{
> +     /* Item must be validated before. Do not redundant checks. */
> +     assert(spec);
> +     memcpy(encap->vxlan.vni, spec->vni, sizeof(encap->vxlan.vni));
> +     encap->mask |= FLOW_TCF_ENCAP_VXLAN_VNI;
> +}
> +
> +/**
> + * Populate consolidated encapsulation object from list of pattern items.
> + *
> + * Helper function to process configuration of action such as
> + * RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP. The item list should be
> + * validated, there is no way to return an meaningful error.
> + *
> + * @param[in] action
> + *   RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP action object.
> + *   List of pattern items to gather data from.
> + * @param[out] src
> + *   Structure to fill gathered data.
> + */
> +static void
> +flow_tcf_vxlan_encap_parse(const struct rte_flow_action *action,
> +                        struct flow_tcf_vxlan_encap *encap)
> +{
> +     union {
> +             const struct rte_flow_item_eth *eth;
> +             const struct rte_flow_item_ipv4 *ipv4;
> +             const struct rte_flow_item_ipv6 *ipv6;
> +             const struct rte_flow_item_udp *udp;
> +             const struct rte_flow_item_vxlan *vxlan;
> +     } spec, mask;
> +     const struct rte_flow_item *items;
> +
> +     assert(action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP);
> +     assert(action->conf);
> +
> +     items = ((const struct rte_flow_action_vxlan_encap *)
> +                                     action->conf)->definition;
> +     assert(items);
> +     for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
> +             switch (items->type) {
> +             case RTE_FLOW_ITEM_TYPE_VOID:
> +                     break;
> +             case RTE_FLOW_ITEM_TYPE_ETH:
> +                     mask.eth = items->mask;
> +                     spec.eth = items->spec;
> +                     flow_tcf_parse_vxlan_encap_eth
> +                                             (spec.eth, mask.eth, encap);
> +                     break;
> +             case RTE_FLOW_ITEM_TYPE_IPV4:
> +                     spec.ipv4 = items->spec;
> +                     flow_tcf_parse_vxlan_encap_ipv4(spec.ipv4, encap);
> +                     break;
> +             case RTE_FLOW_ITEM_TYPE_IPV6:
> +                     spec.ipv6 = items->spec;
> +                     flow_tcf_parse_vxlan_encap_ipv6(spec.ipv6, encap);
> +                     break;
> +             case RTE_FLOW_ITEM_TYPE_UDP:
> +                     mask.udp = items->mask;
> +                     spec.udp = items->spec;
> +                     flow_tcf_parse_vxlan_encap_udp
> +                                             (spec.udp, mask.udp, encap);
> +                     break;
> +             case RTE_FLOW_ITEM_TYPE_VXLAN:
> +                     spec.vxlan = items->spec;
> +                     flow_tcf_parse_vxlan_encap_vni(spec.vxlan, encap);
> +                     break;
> +             default:
> +                     assert(false);
> +                     DRV_LOG(WARNING,
> +                             "unsupported item %p type %d,"
> +                             " items must be validated"
> +                             " before flow creation",
> +                             (const void *)items, items->type);
> +                     encap->mask = 0;
> +                     return;
> +             }
> +     }
> +}
> +
> +/**
>   * Translate flow for Linux TC flower and construct Netlink message.
>   *
>   * @param[in] priv
> @@ -2795,6 +3030,7 @@ struct pedit_parser {
>               const struct rte_flow_item_ipv6 *ipv6;
>               const struct rte_flow_item_tcp *tcp;
>               const struct rte_flow_item_udp *udp;
> +             const struct rte_flow_item_vxlan *vxlan;
>       } spec, mask;
>       union {
>               const struct rte_flow_action_port_id *port_id;
> @@ -2805,6 +3041,14 @@ struct pedit_parser {
>               const struct rte_flow_action_of_set_vlan_pcp *
>                       of_set_vlan_pcp;
>       } conf;
> +     union {
> +             struct flow_tcf_tunnel_hdr *hdr;
> +             struct flow_tcf_vxlan_decap *vxlan;
> +     } decap;
> +     union {
> +             struct flow_tcf_tunnel_hdr *hdr;
> +             struct flow_tcf_vxlan_encap *vxlan;
> +     } encap;
>       struct flow_tcf_ptoi ptoi[PTOI_TABLE_SZ_MAX(dev)];
>       struct nlmsghdr *nlh = dev_flow->tcf.nlh;
>       struct tcmsg *tcm = dev_flow->tcf.tcm;
> @@ -2822,6 +3066,16 @@ struct pedit_parser {
>  
>       claim_nonzero(flow_tcf_build_ptoi_table(dev, ptoi,
>                                               PTOI_TABLE_SZ_MAX(dev)));
> +     encap.hdr = NULL;
> +     decap.hdr = NULL;

Please do this initialization in the declaration above. E.g.,

        union {
                struct flow_tcf_tunnel_hdr *hdr;
                struct flow_tcf_vxlan_decap *vxlan;
        } decap = {
                .hdr = NULL,
        };

> +     if (dev_flow->flow->actions & MLX5_FLOW_ACTION_VXLAN_ENCAP) {
> +             encap.vxlan = dev_flow->tcf.vxlan_encap;
> +             encap.vxlan->hdr.type = FLOW_TCF_TUNACT_VXLAN_ENCAP;
> +     }
> +     if (dev_flow->flow->actions & MLX5_FLOW_ACTION_VXLAN_DECAP) {
> +             decap.vxlan = dev_flow->tcf.vxlan_decap;
> +             decap.vxlan->hdr.type = FLOW_TCF_TUNACT_VXLAN_DECAP;
> +     }

Like I asked in the previous patch, please set the type in _prepare(), then this
part can be like:

        if (dev_flow->tcf.tunnel->type == FLOW_TCF_TUNACT_VXLAN_ENCAP)
                encap.vxlan = dev_flow->tcf.vxlan_encap;
        if (dev_flow->flow->actions & MLX5_FLOW_ACTION_VXLAN_DECAP)
                decap.vxlan = dev_flow->tcf.vxlan_decap;

>       nlh = dev_flow->tcf.nlh;
>       tcm = dev_flow->tcf.tcm;
>       /* Prepare API must have been called beforehand. */
> @@ -2839,7 +3093,6 @@ struct pedit_parser {
>               mnl_attr_put_u32(nlh, TCA_CHAIN, attr->group);
>       mnl_attr_put_strz(nlh, TCA_KIND, "flower");
>       na_flower = mnl_attr_nest_start(nlh, TCA_OPTIONS);
> -     mnl_attr_put_u32(nlh, TCA_FLOWER_FLAGS, TCA_CLS_FLAGS_SKIP_SW);
>       for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
>               unsigned int i;
>  
> @@ -2867,7 +3120,9 @@ struct pedit_parser {
>                       tcm->tcm_ifindex = ptoi[i].ifindex;
>                       break;
>               case RTE_FLOW_ITEM_TYPE_ETH:
> -                     item_flags |= MLX5_FLOW_LAYER_OUTER_L2;
> +                     item_flags |= (item_flags & MLX5_FLOW_LAYER_VXLAN) ?
> +                                             MLX5_FLOW_LAYER_INNER_L2 :
> +                                             MLX5_FLOW_LAYER_OUTER_L2;

Indentation.

>                       mask.eth = flow_tcf_item_mask
>                               (items, &rte_flow_item_eth_mask,
>                                &flow_tcf_mask_supported.eth,
> @@ -2878,6 +3133,14 @@ struct pedit_parser {
>                       if (mask.eth == &flow_tcf_mask_empty.eth)
>                               break;
>                       spec.eth = items->spec;
> +                     if (decap.vxlan &&
> +                         !(item_flags & MLX5_FLOW_LAYER_VXLAN)) {
> +                             DRV_LOG(WARNING,
> +                                     "outer L2 addresses cannot be forced"
> +                                     " for vxlan decapsulation, parameter"
> +                                     " ignored");
> +                             break;
> +                     }
>                       if (mask.eth->type) {
>                               mnl_attr_put_u16(nlh, TCA_FLOWER_KEY_ETH_TYPE,
>                                                spec.eth->type);
> @@ -2899,8 +3162,11 @@ struct pedit_parser {
>                                            ETHER_ADDR_LEN,
>                                            mask.eth->src.addr_bytes);
>                       }
> +                     assert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);
>                       break;
>               case RTE_FLOW_ITEM_TYPE_VLAN:
> +                     assert(!encap.hdr);
> +                     assert(!decap.hdr);
>                       item_flags |= MLX5_FLOW_LAYER_OUTER_VLAN;
>                       mask.vlan = flow_tcf_item_mask
>                               (items, &rte_flow_item_vlan_mask,
> @@ -2932,6 +3198,7 @@ struct pedit_parser {
>                                                rte_be_to_cpu_16
>                                                (spec.vlan->tci &
>                                                 RTE_BE16(0x0fff)));
> +                     assert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);
>                       break;
>               case RTE_FLOW_ITEM_TYPE_IPV4:
>                       item_flags |= MLX5_FLOW_LAYER_OUTER_L3_IPV4;
> @@ -2942,36 +3209,52 @@ struct pedit_parser {
>                                sizeof(flow_tcf_mask_supported.ipv4),
>                                error);
>                       assert(mask.ipv4);
> -                     if (!eth_type_set || !vlan_eth_type_set)
> -                             mnl_attr_put_u16(nlh,
> +                     spec.ipv4 = items->spec;
> +                     if (!decap.vxlan) {
> +                             if (!eth_type_set && !vlan_eth_type_set)
> +                                     mnl_attr_put_u16(nlh,
>                                                vlan_present ?
>                                                TCA_FLOWER_KEY_VLAN_ETH_TYPE :
>                                                TCA_FLOWER_KEY_ETH_TYPE,
>                                                RTE_BE16(ETH_P_IP));

Indentation.

> -                     eth_type_set = 1;
> -                     vlan_eth_type_set = 1;
> -                     if (mask.ipv4 == &flow_tcf_mask_empty.ipv4)
> -                             break;
> -                     spec.ipv4 = items->spec;
> -                     if (mask.ipv4->hdr.next_proto_id) {
> -                             mnl_attr_put_u8(nlh, TCA_FLOWER_KEY_IP_PROTO,
> -                                             spec.ipv4->hdr.next_proto_id);
> -                             ip_proto_set = 1;
> +                             eth_type_set = 1;
> +                             vlan_eth_type_set = 1;
> +                             if (mask.ipv4 == &flow_tcf_mask_empty.ipv4)
> +                                     break;
> +                             if (mask.ipv4->hdr.next_proto_id) {
> +                                     mnl_attr_put_u8
> +                                             (nlh, TCA_FLOWER_KEY_IP_PROTO,
> +                                              spec.ipv4->hdr.next_proto_id);
> +                                     ip_proto_set = 1;
> +                             }
> +                     } else {
> +                             assert(mask.ipv4 != &flow_tcf_mask_empty.ipv4);
>                       }
>                       if (mask.ipv4->hdr.src_addr) {
> -                             mnl_attr_put_u32(nlh, TCA_FLOWER_KEY_IPV4_SRC,
> -                                              spec.ipv4->hdr.src_addr);
> -                             mnl_attr_put_u32(nlh,
> -                                              TCA_FLOWER_KEY_IPV4_SRC_MASK,
> -                                              mask.ipv4->hdr.src_addr);
> +                             mnl_attr_put_u32
> +                                     (nlh, decap.vxlan ?
> +                                      TCA_FLOWER_KEY_ENC_IPV4_SRC :
> +                                      TCA_FLOWER_KEY_IPV4_SRC,
> +                                      spec.ipv4->hdr.src_addr);
> +                             mnl_attr_put_u32
> +                                     (nlh, decap.vxlan ?
> +                                      TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK :
> +                                      TCA_FLOWER_KEY_IPV4_SRC_MASK,
> +                                      mask.ipv4->hdr.src_addr);
>                       }
>                       if (mask.ipv4->hdr.dst_addr) {
> -                             mnl_attr_put_u32(nlh, TCA_FLOWER_KEY_IPV4_DST,
> -                                              spec.ipv4->hdr.dst_addr);
> -                             mnl_attr_put_u32(nlh,
> -                                              TCA_FLOWER_KEY_IPV4_DST_MASK,
> -                                              mask.ipv4->hdr.dst_addr);
> +                             mnl_attr_put_u32
> +                                     (nlh, decap.vxlan ?
> +                                      TCA_FLOWER_KEY_ENC_IPV4_DST :
> +                                      TCA_FLOWER_KEY_IPV4_DST,
> +                                      spec.ipv4->hdr.dst_addr);
> +                             mnl_attr_put_u32
> +                                     (nlh, decap.vxlan ?
> +                                      TCA_FLOWER_KEY_ENC_IPV4_DST_MASK :
> +                                      TCA_FLOWER_KEY_IPV4_DST_MASK,
> +                                      mask.ipv4->hdr.dst_addr);
>                       }
> +                     assert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);
>                       break;
>               case RTE_FLOW_ITEM_TYPE_IPV6:
>                       item_flags |= MLX5_FLOW_LAYER_OUTER_L3_IPV6;
> @@ -2982,38 +3265,53 @@ struct pedit_parser {
>                                sizeof(flow_tcf_mask_supported.ipv6),
>                                error);
>                       assert(mask.ipv6);
> -                     if (!eth_type_set || !vlan_eth_type_set)
> -                             mnl_attr_put_u16(nlh,
> -                                              vlan_present ?
> -                                              TCA_FLOWER_KEY_VLAN_ETH_TYPE :
> -                                              TCA_FLOWER_KEY_ETH_TYPE,
> -                                              RTE_BE16(ETH_P_IPV6));
> -                     eth_type_set = 1;
> -                     vlan_eth_type_set = 1;
> -                     if (mask.ipv6 == &flow_tcf_mask_empty.ipv6)
> -                             break;
>                       spec.ipv6 = items->spec;
> -                     if (mask.ipv6->hdr.proto) {
> -                             mnl_attr_put_u8(nlh, TCA_FLOWER_KEY_IP_PROTO,
> -                                             spec.ipv6->hdr.proto);
> -                             ip_proto_set = 1;
> +                     if (!decap.vxlan) {
> +                             if (!eth_type_set || !vlan_eth_type_set) {
> +                                     mnl_attr_put_u16(nlh,
> +                                             vlan_present ?
> +                                             TCA_FLOWER_KEY_VLAN_ETH_TYPE :
> +                                             TCA_FLOWER_KEY_ETH_TYPE,
> +                                             RTE_BE16(ETH_P_IPV6));

Indentation.

> +                             }
> +                             eth_type_set = 1;
> +                             vlan_eth_type_set = 1;
> +                             if (mask.ipv6 == &flow_tcf_mask_empty.ipv6)
> +                                     break;
> +                             if (mask.ipv6->hdr.proto) {
> +                                     mnl_attr_put_u8
> +                                             (nlh, TCA_FLOWER_KEY_IP_PROTO,
> +                                              spec.ipv6->hdr.proto);
> +                                     ip_proto_set = 1;
> +                             }
> +                     } else {
> +                             assert(mask.ipv6 != &flow_tcf_mask_empty.ipv6);
>                       }
>                       if (!IN6_IS_ADDR_UNSPECIFIED(mask.ipv6->hdr.src_addr)) {
> -                             mnl_attr_put(nlh, TCA_FLOWER_KEY_IPV6_SRC,
> -                                          sizeof(spec.ipv6->hdr.src_addr),
> +                             mnl_attr_put(nlh, decap.vxlan ?
> +                                          TCA_FLOWER_KEY_ENC_IPV6_SRC :
> +                                          TCA_FLOWER_KEY_IPV6_SRC,
> +                                          IPV6_ADDR_LEN,
>                                            spec.ipv6->hdr.src_addr);
> -                             mnl_attr_put(nlh, TCA_FLOWER_KEY_IPV6_SRC_MASK,
> -                                          sizeof(mask.ipv6->hdr.src_addr),
> +                             mnl_attr_put(nlh, decap.vxlan ?
> +                                          TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK :
> +                                          TCA_FLOWER_KEY_IPV6_SRC_MASK,
> +                                          IPV6_ADDR_LEN,
>                                            mask.ipv6->hdr.src_addr);
>                       }
>                       if (!IN6_IS_ADDR_UNSPECIFIED(mask.ipv6->hdr.dst_addr)) {
> -                             mnl_attr_put(nlh, TCA_FLOWER_KEY_IPV6_DST,
> -                                          sizeof(spec.ipv6->hdr.dst_addr),
> +                             mnl_attr_put(nlh, decap.vxlan ?
> +                                          TCA_FLOWER_KEY_ENC_IPV6_DST :
> +                                          TCA_FLOWER_KEY_IPV6_DST,
> +                                          IPV6_ADDR_LEN,
>                                            spec.ipv6->hdr.dst_addr);
> -                             mnl_attr_put(nlh, TCA_FLOWER_KEY_IPV6_DST_MASK,
> -                                          sizeof(mask.ipv6->hdr.dst_addr),
> +                             mnl_attr_put(nlh, decap.vxlan ?
> +                                          TCA_FLOWER_KEY_ENC_IPV6_DST_MASK :
> +                                          TCA_FLOWER_KEY_IPV6_DST_MASK,
> +                                          IPV6_ADDR_LEN,
>                                            mask.ipv6->hdr.dst_addr);
>                       }
> +                     assert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);
>                       break;
>               case RTE_FLOW_ITEM_TYPE_UDP:
>                       item_flags |= MLX5_FLOW_LAYER_OUTER_L4_UDP;
> @@ -3024,26 +3322,45 @@ struct pedit_parser {
>                                sizeof(flow_tcf_mask_supported.udp),
>                                error);
>                       assert(mask.udp);
> -                     if (!ip_proto_set)
> -                             mnl_attr_put_u8(nlh, TCA_FLOWER_KEY_IP_PROTO,
> -                                             IPPROTO_UDP);
> -                     if (mask.udp == &flow_tcf_mask_empty.udp)
> -                             break;
>                       spec.udp = items->spec;
> +                     if (!decap.vxlan) {
> +                             if (!ip_proto_set)
> +                                     mnl_attr_put_u8
> +                                             (nlh, TCA_FLOWER_KEY_IP_PROTO,
> +                                             IPPROTO_UDP);
> +                             if (mask.udp == &flow_tcf_mask_empty.udp)
> +                                     break;
> +                     } else {
> +                             assert(mask.udp != &flow_tcf_mask_empty.udp);
> +                             decap.vxlan->udp_port =
> +                                     rte_be_to_cpu_16
> +                                             (spec.udp->hdr.dst_port);
> +                     }
>                       if (mask.udp->hdr.src_port) {
> -                             mnl_attr_put_u16(nlh, TCA_FLOWER_KEY_UDP_SRC,
> -                                              spec.udp->hdr.src_port);
> -                             mnl_attr_put_u16(nlh,
> -                                              TCA_FLOWER_KEY_UDP_SRC_MASK,
> -                                              mask.udp->hdr.src_port);
> +                             mnl_attr_put_u16
> +                                     (nlh, decap.vxlan ?
> +                                      TCA_FLOWER_KEY_ENC_UDP_SRC_PORT :
> +                                      TCA_FLOWER_KEY_UDP_SRC,
> +                                      spec.udp->hdr.src_port);
> +                             mnl_attr_put_u16
> +                                     (nlh, decap.vxlan ?
> +                                      TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK :
> +                                      TCA_FLOWER_KEY_UDP_SRC_MASK,
> +                                      mask.udp->hdr.src_port);
>                       }
>                       if (mask.udp->hdr.dst_port) {
> -                             mnl_attr_put_u16(nlh, TCA_FLOWER_KEY_UDP_DST,
> -                                              spec.udp->hdr.dst_port);
> -                             mnl_attr_put_u16(nlh,
> -                                              TCA_FLOWER_KEY_UDP_DST_MASK,
> -                                              mask.udp->hdr.dst_port);
> +                             mnl_attr_put_u16
> +                                     (nlh, decap.vxlan ?
> +                                      TCA_FLOWER_KEY_ENC_UDP_DST_PORT :
> +                                      TCA_FLOWER_KEY_UDP_DST,
> +                                      spec.udp->hdr.dst_port);
> +                             mnl_attr_put_u16
> +                                     (nlh, decap.vxlan ?
> +                                      TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK :
> +                                      TCA_FLOWER_KEY_UDP_DST_MASK,
> +                                      mask.udp->hdr.dst_port);
>                       }
> +                     assert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);
>                       break;
>               case RTE_FLOW_ITEM_TYPE_TCP:
>                       item_flags |= MLX5_FLOW_LAYER_OUTER_L4_TCP;
> @@ -3086,6 +3403,16 @@ struct pedit_parser {
>                                        rte_cpu_to_be_16
>                                               (mask.tcp->hdr.tcp_flags));
>                       }
> +                     assert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);
> +                     break;
> +             case RTE_FLOW_ITEM_TYPE_VXLAN:
> +                     assert(decap.vxlan);
> +                     item_flags |= MLX5_FLOW_LAYER_VXLAN;
> +                     spec.vxlan = items->spec;
> +                     mnl_attr_put_u32(nlh,
> +                                      TCA_FLOWER_KEY_ENC_KEY_ID,
> +                                      vxlan_vni_as_be32(spec.vxlan->vni));
> +                     assert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);
>                       break;
>               default:
>                       return rte_flow_error_set(error, ENOTSUP,
> @@ -3119,6 +3446,14 @@ struct pedit_parser {
>                       mnl_attr_put_strz(nlh, TCA_ACT_KIND, "mirred");
>                       na_act = mnl_attr_nest_start(nlh, TCA_ACT_OPTIONS);
>                       assert(na_act);
> +                     if (encap.hdr) {
> +                             assert(dev_flow->tcf.tunnel);
> +                             dev_flow->tcf.tunnel->ifindex_ptr =
> +                                     &((struct tc_mirred *)
> +                                     mnl_attr_get_payload
> +                                     (mnl_nlmsg_get_payload_tail
> +                                             (nlh)))->ifindex;
> +                     }
>                       mnl_attr_put(nlh, TCA_MIRRED_PARMS,
>                                    sizeof(struct tc_mirred),
>                                    &(struct tc_mirred){
> @@ -3236,6 +3571,74 @@ struct pedit_parser {
>                                       conf.of_set_vlan_pcp->vlan_pcp;
>                       }
>                       break;
> +             case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
> +                     assert(decap.vxlan);
> +                     assert(dev_flow->tcf.tunnel);
> +                     dev_flow->tcf.tunnel->ifindex_ptr =
> +                             (unsigned int *)&tcm->tcm_ifindex;
> +                     na_act_index =
> +                             mnl_attr_nest_start(nlh, na_act_index_cur++);
> +                     assert(na_act_index);
> +                     mnl_attr_put_strz(nlh, TCA_ACT_KIND, "tunnel_key");
> +                     na_act = mnl_attr_nest_start(nlh, TCA_ACT_OPTIONS);
> +                     assert(na_act);
> +                     mnl_attr_put(nlh, TCA_TUNNEL_KEY_PARMS,
> +                             sizeof(struct tc_tunnel_key),
> +                             &(struct tc_tunnel_key){
> +                                     .action = TC_ACT_PIPE,
> +                                     .t_action = TCA_TUNNEL_KEY_ACT_RELEASE,
> +                                     });
> +                     mnl_attr_nest_end(nlh, na_act);
> +                     mnl_attr_nest_end(nlh, na_act_index);
> +                     assert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);
> +                     break;
> +             case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
> +                     assert(encap.vxlan);
> +                     flow_tcf_vxlan_encap_parse(actions, encap.vxlan);
> +                     na_act_index =
> +                             mnl_attr_nest_start(nlh, na_act_index_cur++);
> +                     assert(na_act_index);
> +                     mnl_attr_put_strz(nlh, TCA_ACT_KIND, "tunnel_key");
> +                     na_act = mnl_attr_nest_start(nlh, TCA_ACT_OPTIONS);
> +                     assert(na_act);
> +                     mnl_attr_put(nlh, TCA_TUNNEL_KEY_PARMS,
> +                             sizeof(struct tc_tunnel_key),
> +                             &(struct tc_tunnel_key){
> +                                     .action = TC_ACT_PIPE,
> +                                     .t_action = TCA_TUNNEL_KEY_ACT_SET,
> +                                     });
> +                     if (encap.vxlan->mask & FLOW_TCF_ENCAP_UDP_DST)
> +                             mnl_attr_put_u16(nlh,
> +                                      TCA_TUNNEL_KEY_ENC_DST_PORT,
> +                                      encap.vxlan->udp.dst);
> +                     if (encap.vxlan->mask & FLOW_TCF_ENCAP_IPV4_SRC)
> +                             mnl_attr_put_u32(nlh,
> +                                      TCA_TUNNEL_KEY_ENC_IPV4_SRC,
> +                                      encap.vxlan->ipv4.src);
> +                     if (encap.vxlan->mask & FLOW_TCF_ENCAP_IPV4_DST)
> +                             mnl_attr_put_u32(nlh,
> +                                      TCA_TUNNEL_KEY_ENC_IPV4_DST,
> +                                      encap.vxlan->ipv4.dst);
> +                     if (encap.vxlan->mask & FLOW_TCF_ENCAP_IPV6_SRC)
> +                             mnl_attr_put(nlh,
> +                                      TCA_TUNNEL_KEY_ENC_IPV6_SRC,
> +                                      sizeof(encap.vxlan->ipv6.src),
> +                                      &encap.vxlan->ipv6.src);
> +                     if (encap.vxlan->mask & FLOW_TCF_ENCAP_IPV6_DST)
> +                             mnl_attr_put(nlh,
> +                                      TCA_TUNNEL_KEY_ENC_IPV6_DST,
> +                                      sizeof(encap.vxlan->ipv6.dst),
> +                                      &encap.vxlan->ipv6.dst);
> +                     if (encap.vxlan->mask & FLOW_TCF_ENCAP_VXLAN_VNI)
> +                             mnl_attr_put_u32(nlh,
> +                                      TCA_TUNNEL_KEY_ENC_KEY_ID,
> +                                      vxlan_vni_as_be32
> +                                             (encap.vxlan->vxlan.vni));
> +                     mnl_attr_put_u8(nlh, TCA_TUNNEL_KEY_NO_CSUM, 0);
> +                     mnl_attr_nest_end(nlh, na_act);
> +                     mnl_attr_nest_end(nlh, na_act_index);
> +                     assert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);
> +                     break;
>               case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
>               case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
>               case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
> @@ -3262,7 +3665,13 @@ struct pedit_parser {
>       assert(na_flower);
>       assert(na_flower_act);
>       mnl_attr_nest_end(nlh, na_flower_act);
> +     mnl_attr_put_u32(nlh, TCA_FLOWER_FLAGS,
> +             decap.vxlan ? 0 : TCA_CLS_FLAGS_SKIP_SW);

Indentation.

Thanks,
Yongseok

>       mnl_attr_nest_end(nlh, na_flower);
> +     if (dev_flow->tcf.tunnel && dev_flow->tcf.tunnel->ifindex_ptr)
> +             dev_flow->tcf.tunnel->ifindex_org =
> +                     *dev_flow->tcf.tunnel->ifindex_ptr;
> +     assert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);
>       return 0;
>  }
>  
> -- 
> 1.8.3.1
> 

Reply via email to