From patchwork Sat Dec 29 19:55:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slava Ovsiienko X-Patchwork-Id: 49362 X-Patchwork-Delegate: shahafs@mellanox.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 3436A5F2D; Sat, 29 Dec 2018 20:55:56 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by dpdk.org (Postfix) with ESMTP id 6E0F65B40 for ; Sat, 29 Dec 2018 20:55:52 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from viacheslavo@mellanox.com) with ESMTPS (AES256-SHA encrypted); 29 Dec 2018 21:55:49 +0200 Received: from pegasus12.mtr.labs.mlnx. (pegasus12.mtr.labs.mlnx [10.210.17.40]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id wBTJtkdW002527; Sat, 29 Dec 2018 21:55:49 +0200 From: Viacheslav Ovsiienko To: shahafs@mellanox.com Cc: dev@dpdk.org Date: Sat, 29 Dec 2018 19:55:37 +0000 Message-Id: <1546113340-30356-3-git-send-email-viacheslavo@mellanox.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1546113340-30356-1-git-send-email-viacheslavo@mellanox.com> References: <1546113340-30356-1-git-send-email-viacheslavo@mellanox.com> Subject: [dpdk-dev] [PATCH 2/5] net/mlx5: introduce encapsulation rules container X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Currently the VXLAN encapsulation neigh/local rules are stored in the list contained in the VTEP device structure. Encapsulation VTEP device is attached to outer interface and stored rules are related to this underlying interface. We are going to use unattached VXLAN devices for encapsulation (kernel does not use attached interface to find egress one), so we should introduce the structure to keep interface related neigh/local rules instead of VTEP structure. This patch introduces internal tcf_irule structure, and its create/delete methods. Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_flow_tcf.c | 108 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5_flow_tcf.c b/drivers/net/mlx5/mlx5_flow_tcf.c index b4734a0..a6dca08 100644 --- a/drivers/net/mlx5/mlx5_flow_tcf.c +++ b/drivers/net/mlx5/mlx5_flow_tcf.c @@ -431,6 +431,15 @@ struct tcf_local_rule { }; }; +/** Outer interface VXLAN encapsulation rules container. */ +struct tcf_irule { + LIST_ENTRY(tcf_irule) next; + LIST_HEAD(, tcf_neigh_rule) neigh; + LIST_HEAD(, tcf_local_rule) local; + uint32_t refcnt; + unsigned int ifouter; /**< Own interface index. */ +}; + /** VXLAN virtual netdev. */ struct tcf_vtep { LIST_ENTRY(tcf_vtep) next; @@ -458,6 +467,7 @@ struct flow_tcf_vxlan_decap { struct flow_tcf_vxlan_encap { struct flow_tcf_tunnel_hdr hdr; + struct tcf_irule *iface; uint32_t mask; uint8_t ip_tos; uint8_t ip_ttl_hop; @@ -4971,11 +4981,90 @@ struct tcf_nlcb_context { return 0; } +/* VXLAN encap rule database for outer interfaces. */ +static LIST_HEAD(, tcf_irule) iface_list_vxlan = LIST_HEAD_INITIALIZER(); + /* VTEP device list is shared between PMD port instances. */ static LIST_HEAD(, tcf_vtep) vtep_list_vxlan = LIST_HEAD_INITIALIZER(); static pthread_mutex_t vtep_list_mutex = PTHREAD_MUTEX_INITIALIZER; /** + * Acquire the VXLAN encap rules container for specified interface. + * First looks for the container in the existing ones list, creates + * and initializes the new container if existing not found. + * + * @param[in] tcf + * Context object initialized by mlx5_flow_tcf_context_create(). + * @param[in] ifouter + * Network interface index to create VXLAN encap rules on. + * @param[out] error + * Perform verbose error reporting if not NULL. + * @return + * Rule container pointer on success, + * NULL otherwise and rte_errno is set. + */ +static struct tcf_irule* +flow_tcf_encap_irule_acquire(struct mlx5_flow_tcf_context *tcf, + unsigned int ifouter, + struct rte_flow_error *error) +{ + struct tcf_irule *iface; + + /* Look whether the container for encap rules is created. */ + assert(ifouter); + LIST_FOREACH(iface, &iface_list_vxlan, next) { + if (iface->ifouter == ifouter) + break; + } + if (iface) { + /* Container already exists, just increment the reference. */ + iface->refcnt++; + return iface; + } + /* Not found, we should create the new container. */ + iface = rte_zmalloc(__func__, sizeof(*iface), + alignof(struct tcf_irule)); + if (!iface) { + rte_flow_error_set(error, ENOMEM, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "unable to allocate memory for container"); + return NULL; + } + *iface = (struct tcf_irule){ + .local = LIST_HEAD_INITIALIZER(), + .neigh = LIST_HEAD_INITIALIZER(), + .ifouter = ifouter, + .refcnt = 1, + }; + /* Interface cleanup for new container created. */ + flow_tcf_encap_iface_cleanup(tcf, ifouter); + flow_tcf_encap_local_cleanup(tcf, ifouter); + flow_tcf_encap_neigh_cleanup(tcf, ifouter); + LIST_INSERT_HEAD(&iface_list_vxlan, iface, next); + return iface; +} + +/** + * Releases VXLAN encap rules container by pointer. Decrements the + * reference cointer and deletes the container if counter is zero. + * + * @param[in] irule + * VXLAN rule container pointer to release. + */ +static void +flow_tcf_encap_irule_release(struct tcf_irule *iface) +{ + assert(iface->refcnt); + if (--iface->refcnt == 0) { + /* Reference counter is zero, delete the container. */ + assert(LIST_EMPTY(&iface->local)); + assert(LIST_EMPTY(&iface->neigh)); + LIST_REMOVE(iface, next); + rte_free(iface); + } +} + +/** * Deletes VTEP network device. * * @param[in] tcf @@ -5247,6 +5336,7 @@ struct tcf_nlcb_context { { static uint16_t encap_port = MLX5_VXLAN_PORT_MIN - 1; struct tcf_vtep *vtep; + struct tcf_irule *iface; int ret; assert(ifouter); @@ -5296,6 +5386,13 @@ struct tcf_nlcb_context { } assert(vtep->ifouter == ifouter); assert(vtep->ifindex); + iface = flow_tcf_encap_irule_acquire(tcf, ifouter, error); + if (!iface) { + if (--vtep->refcnt == 0) + flow_tcf_vtep_delete(tcf, vtep); + return NULL; + } + dev_flow->tcf.vxlan_encap->iface = iface; /* Create local ipaddr with peer to specify the outer IPs. */ ret = flow_tcf_encap_local(tcf, vtep, dev_flow, true, error); if (!ret) { @@ -5306,6 +5403,8 @@ struct tcf_nlcb_context { dev_flow, false, error); } if (ret) { + dev_flow->tcf.vxlan_encap->iface = NULL; + flow_tcf_encap_irule_release(iface); if (--vtep->refcnt == 0) flow_tcf_vtep_delete(tcf, vtep); return NULL; @@ -5378,11 +5477,18 @@ struct tcf_nlcb_context { switch (dev_flow->tcf.tunnel->type) { case FLOW_TCF_TUNACT_VXLAN_DECAP: break; - case FLOW_TCF_TUNACT_VXLAN_ENCAP: + case FLOW_TCF_TUNACT_VXLAN_ENCAP: { + struct tcf_irule *iface; + /* Remove the encap ancillary rules first. */ + iface = dev_flow->tcf.vxlan_encap->iface; + assert(iface); flow_tcf_encap_neigh(tcf, vtep, dev_flow, false, NULL); flow_tcf_encap_local(tcf, vtep, dev_flow, false, NULL); + flow_tcf_encap_irule_release(iface); + dev_flow->tcf.vxlan_encap->iface = NULL; break; + } default: assert(false); DRV_LOG(WARNING, "Unsupported tunnel type");