From mboxrd@z Thu Jan 1 00:00:00 1970 From: Slava Ovsiienko Subject: [PATCH v5 07/13] net/mlx5: add VXLAN support to flow prepare routine Date: Sat, 3 Nov 2018 06:18:40 +0000 Message-ID: <1541225876-8817-8-git-send-email-viacheslavo@mellanox.com> References: <1541181152-15788-2-git-send-email-viacheslavo@mellanox.com> <1541225876-8817-1-git-send-email-viacheslavo@mellanox.com> Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Cc: "dev@dpdk.org" , Yongseok Koh , Slava Ovsiienko To: Shahaf Shuler Return-path: Received: from EUR02-VE1-obe.outbound.protection.outlook.com (mail-eopbgr20070.outbound.protection.outlook.com [40.107.2.70]) by dpdk.org (Postfix) with ESMTP id B7CE65B1E for ; Sat, 3 Nov 2018 07:18:41 +0100 (CET) In-Reply-To: <1541225876-8817-1-git-send-email-viacheslavo@mellanox.com> Content-Language: en-US List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The e-switch Flow prepare function is updated to support VXLAN encapsulation/and decapsulation actions. The function calculates buffer size for Netlink message and Flow description structures, including optional ones for tunneling purposes. Suggested-by: Adrien Mazarguil Signed-off-by: Viacheslav Ovsiienko Acked-by: Yongseok Koh --- drivers/net/mlx5/mlx5_flow_tcf.c | 137 +++++++++++++++++++++++++++++++++++= +++- 1 file changed, 134 insertions(+), 3 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_tcf.c b/drivers/net/mlx5/mlx5_flow_= tcf.c index 6299069..017f2bd 100644 --- a/drivers/net/mlx5/mlx5_flow_tcf.c +++ b/drivers/net/mlx5/mlx5_flow_tcf.c @@ -2422,7 +2422,7 @@ struct pedit_parser { case RTE_FLOW_ITEM_TYPE_IPV6: size +=3D SZ_NLATTR_TYPE_OF(uint16_t) + /* Ether type. */ SZ_NLATTR_TYPE_OF(uint8_t) + /* IP proto. */ - SZ_NLATTR_TYPE_OF(IPV6_ADDR_LEN) * 4; + SZ_NLATTR_DATA_OF(IPV6_ADDR_LEN) * 4; /* dst/src IP addr and mask. */ flags |=3D MLX5_FLOW_LAYER_OUTER_L3_IPV6; break; @@ -2438,6 +2438,10 @@ struct pedit_parser { /* dst/src port and mask. */ flags |=3D MLX5_FLOW_LAYER_OUTER_L4_TCP; break; + case RTE_FLOW_ITEM_TYPE_VXLAN: + size +=3D SZ_NLATTR_TYPE_OF(uint32_t); + flags |=3D MLX5_FLOW_LAYER_VXLAN; + break; default: DRV_LOG(WARNING, "unsupported item %p type %d," @@ -2451,6 +2455,69 @@ struct pedit_parser { } =20 /** + * Calculate size of memory to store the VXLAN encapsultion + * related items in the Netlink message buffer. Items list + * is specified by RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP action. + * The item list should be validated. + * + * @param[in] action + * RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP action object. + * List of pattern items to scan data from. + * + * @return + * The size the part of Netlink message buffer to store the + * VXLAN encapsulation item attributes. + */ +static int +flow_tcf_vxlan_encap_size(const struct rte_flow_action *action) +{ + const struct rte_flow_item *items; + int size =3D 0; + + assert(action->type =3D=3D RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP); + assert(action->conf); + + items =3D ((const struct rte_flow_action_vxlan_encap *) + action->conf)->definition; + assert(items); + for (; items->type !=3D RTE_FLOW_ITEM_TYPE_END; items++) { + switch (items->type) { + case RTE_FLOW_ITEM_TYPE_VOID: + break; + case RTE_FLOW_ITEM_TYPE_ETH: + /* This item does not require message buffer. */ + break; + case RTE_FLOW_ITEM_TYPE_IPV4: + size +=3D SZ_NLATTR_DATA_OF(IPV4_ADDR_LEN) * 2; + break; + case RTE_FLOW_ITEM_TYPE_IPV6: + size +=3D SZ_NLATTR_DATA_OF(IPV6_ADDR_LEN) * 2; + break; + case RTE_FLOW_ITEM_TYPE_UDP: { + const struct rte_flow_item_udp *udp =3D items->mask; + + size +=3D SZ_NLATTR_TYPE_OF(uint16_t); + if (!udp || udp->hdr.src_port !=3D RTE_BE16(0x0000)) + size +=3D SZ_NLATTR_TYPE_OF(uint16_t); + break; + } + case RTE_FLOW_ITEM_TYPE_VXLAN: + size +=3D SZ_NLATTR_TYPE_OF(uint32_t); + break; + default: + assert(false); + DRV_LOG(WARNING, + "unsupported item %p type %d," + " items must be validated" + " before flow creation", + (const void *)items, items->type); + return 0; + } + } + return size; +} + +/** * Calculate maximum size of memory for flow actions of Linux TC flower an= d * extract specified actions. * @@ -2519,6 +2586,29 @@ struct pedit_parser { SZ_NLATTR_TYPE_OF(uint16_t) + /* VLAN ID. */ SZ_NLATTR_TYPE_OF(uint8_t); /* VLAN prio. */ break; + case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: + size +=3D SZ_NLATTR_NEST + /* na_act_index. */ + SZ_NLATTR_STRZ_OF("tunnel_key") + + SZ_NLATTR_NEST + /* TCA_ACT_OPTIONS. */ + SZ_NLATTR_TYPE_OF(uint8_t); + size +=3D SZ_NLATTR_TYPE_OF(struct tc_tunnel_key); + size +=3D flow_tcf_vxlan_encap_size(actions) + + RTE_ALIGN_CEIL /* preceding encap params. */ + (sizeof(struct flow_tcf_vxlan_encap), + MNL_ALIGNTO); + flags |=3D MLX5_FLOW_ACTION_VXLAN_ENCAP; + break; + case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: + size +=3D SZ_NLATTR_NEST + /* na_act_index. */ + SZ_NLATTR_STRZ_OF("tunnel_key") + + SZ_NLATTR_NEST + /* TCA_ACT_OPTIONS. */ + SZ_NLATTR_TYPE_OF(uint8_t); + size +=3D SZ_NLATTR_TYPE_OF(struct tc_tunnel_key); + size +=3D RTE_ALIGN_CEIL /* preceding decap params. */ + (sizeof(struct flow_tcf_vxlan_decap), + MNL_ALIGNTO); + flags |=3D MLX5_FLOW_ACTION_VXLAN_DECAP; + 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: @@ -2594,12 +2684,15 @@ struct pedit_parser { uint64_t *item_flags, uint64_t *action_flags, struct rte_flow_error *error) { - size_t size =3D sizeof(struct mlx5_flow) + + size_t size =3D RTE_ALIGN_CEIL + (sizeof(struct mlx5_flow), + alignof(struct flow_tcf_tunnel_hdr)) + MNL_ALIGN(sizeof(struct nlmsghdr)) + MNL_ALIGN(sizeof(struct tcmsg)); struct mlx5_flow *dev_flow; struct nlmsghdr *nlh; struct tcmsg *tcm; + uint8_t *sp, *tun =3D NULL; =20 size +=3D flow_tcf_get_items_and_size(attr, items, item_flags); size +=3D flow_tcf_get_actions_and_size(actions, action_flags); @@ -2610,14 +2703,52 @@ struct pedit_parser { "not enough memory to create E-Switch flow"); return NULL; } - nlh =3D mnl_nlmsg_put_header((void *)(dev_flow + 1)); + sp =3D (uint8_t *)(dev_flow + 1); + if (*action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP) { + sp =3D RTE_PTR_ALIGN + (sp, alignof(struct flow_tcf_tunnel_hdr)); + tun =3D sp; + sp +=3D RTE_ALIGN_CEIL + (sizeof(struct flow_tcf_vxlan_encap), + MNL_ALIGNTO); +#ifndef NDEBUG + size -=3D RTE_ALIGN_CEIL + (sizeof(struct flow_tcf_vxlan_encap), + MNL_ALIGNTO); +#endif + } else if (*action_flags & MLX5_FLOW_ACTION_VXLAN_DECAP) { + sp =3D RTE_PTR_ALIGN + (sp, alignof(struct flow_tcf_tunnel_hdr)); + tun =3D sp; + sp +=3D RTE_ALIGN_CEIL + (sizeof(struct flow_tcf_vxlan_decap), + MNL_ALIGNTO); +#ifndef NDEBUG + size -=3D RTE_ALIGN_CEIL + (sizeof(struct flow_tcf_vxlan_decap), + MNL_ALIGNTO); +#endif + } else { + sp =3D RTE_PTR_ALIGN(sp, MNL_ALIGNTO); + } + nlh =3D mnl_nlmsg_put_header(sp); tcm =3D mnl_nlmsg_put_extra_header(nlh, sizeof(*tcm)); *dev_flow =3D (struct mlx5_flow){ .tcf =3D (struct mlx5_flow_tcf){ +#ifndef NDEBUG + .nlsize =3D size - RTE_ALIGN_CEIL + (sizeof(struct mlx5_flow), + alignof(struct flow_tcf_tunnel_hdr)), +#endif + .tunnel =3D (struct flow_tcf_tunnel_hdr *)tun, .nlh =3D nlh, .tcm =3D tcm, }, }; + if (*action_flags & MLX5_FLOW_ACTION_VXLAN_DECAP) + dev_flow->tcf.tunnel->type =3D FLOW_TCF_TUNACT_VXLAN_DECAP; + else if (*action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP) + dev_flow->tcf.tunnel->type =3D FLOW_TCF_TUNACT_VXLAN_ENCAP; /* * Generate a reasonably unique handle based on the address of the * target buffer. --=20 1.8.3.1