From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from EUR01-HE1-obe.outbound.protection.outlook.com (mail-he1eur01on0072.outbound.protection.outlook.com [104.47.0.72]) by dpdk.org (Postfix) with ESMTP id 3F89D1B3B9 for ; Fri, 2 Nov 2018 01:01:35 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Mellanox.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=C6TXr/QbRb57c090Lv3x8ct3Mq0mKudplWheCIPhbY8=; b=MU+cSg27ma8jp3NJbSLHyWvW7ETrB+MGMcPD9kK7ergtWNDic5QK5Skn7yzrVyoAo+he5H8XX6qiv4zEjiUWGH83xl4tt+yqH7DBNUaqh1XGVCDDXvqSVysgEVhklSuXG30cFdDFqO2CY6d3ZChcuknmvXbYtTto9QYMkqQ7ep8= Received: from DB3PR0502MB3980.eurprd05.prod.outlook.com (52.134.72.27) by DB3PR0502MB4060.eurprd05.prod.outlook.com (52.134.72.153) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1273.25; Fri, 2 Nov 2018 00:01:33 +0000 Received: from DB3PR0502MB3980.eurprd05.prod.outlook.com ([fe80::f8a1:fcab:94f0:97cc]) by DB3PR0502MB3980.eurprd05.prod.outlook.com ([fe80::f8a1:fcab:94f0:97cc%4]) with mapi id 15.20.1273.030; Fri, 2 Nov 2018 00:01:33 +0000 From: Yongseok Koh To: Slava Ovsiienko CC: Shahaf Shuler , "dev@dpdk.org" Thread-Topic: [PATCH v3 13/13] net/mlx5: add e-switch VXLAN rule cleanup routines Thread-Index: AQHUcd0n6V7raTKn2EOcbO9ul4GG9qU7mqmA Date: Fri, 2 Nov 2018 00:01:33 +0000 Message-ID: <20181102000124.GN6118@mtidpdk.mti.labs.mlnx> References: <1539612815-47199-1-git-send-email-viacheslavo@mellanox.com> <1541074741-41368-1-git-send-email-viacheslavo@mellanox.com> <1541074741-41368-14-git-send-email-viacheslavo@mellanox.com> In-Reply-To: <1541074741-41368-14-git-send-email-viacheslavo@mellanox.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-clientproxiedby: BYAPR08CA0028.namprd08.prod.outlook.com (2603:10b6:a03:100::41) To DB3PR0502MB3980.eurprd05.prod.outlook.com (2603:10a6:8:10::27) authentication-results: spf=none (sender IP is ) smtp.mailfrom=yskoh@mellanox.com; x-ms-exchange-messagesentrepresentingtype: 1 x-originating-ip: [209.116.155.178] x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; DB3PR0502MB4060; 6:7hi7bjiOOdoGxjQ7qcTsRa5xEfFjtwdI6jAv0SK8GZoBjurCOeZvLJPRuywGGenvDL0/rz7XMsLo40p/fjoORavPF1vaZI7b5lSdy5rXWass/tfloMof2sRiUHeSHqFeTmm34Lh04+4RaAI2oCTEe6O/l5QeJr2F/U9BnV/qLSzWOsvbf4SBHXywGZ65HNB6l/ZTla3WNSL6N2kEbQo7KfRCgmVdjSzjGoIYbFSx6LNo6Td3ScvxMJUgBbpemocm/h7p2A0odAM5LufYOBzBFCUA0a/XKDRhTblom0Q10IEZb/9cRyvWVWq6WocAM/edCLFtD6BVkJHMwHDfvlmwxBdDZOvggqqjWYvpPBI1C3+S3kUbNDbmE4W/+oSRNa9c+ugeASXx80tOm3YpNOjjTKV0gakVF3YP0Yx559LGV9MSHKAouTNFbxhLE8s2PscUqZwxoFIXFbixjFbr/Md43A==; 5:x9Q+MEQGk30jcxkRweSkx7XgkGE9K98mVBnTUV11cDMv30mhWU5AQLqugRHahsx2BJhbBgo3k4vAH8Pv25zORyDP8KDzmC0PJSdb85Mdj2BM/B8E5NEqXmnucO/cHo7obi4fesUtIZ+JJMLQc3y4TI7AQsUXYuBPZJdM+FBQ2gg=; 7:S374GOP8XCyx9S1eiLwLj/jtaa8fyV6gWGmGMcpubv7/Nch3mr/hT0agwmdXDEECPiRtCGKU2YJT4mx1p3zD1vIXg61STpAQzCViwU18wfQuB9x2xKMDnq94wteieofaSBDtM2APR2+hwB9ZpWaXiA== x-ms-office365-filtering-correlation-id: 00624206-ac27-4a3e-8e99-08d640565983 x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: BCL:0; PCL:0; RULEID:(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600074)(711020)(4618075)(2017052603328)(7153060)(7193020); SRVR:DB3PR0502MB4060; x-ms-traffictypediagnostic: DB3PR0502MB4060: x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:; x-ms-exchange-senderadcheck: 1 x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(10201501046)(3002001)(93006095)(93001095)(3231382)(944501410)(52105095)(6055026)(148016)(149066)(150057)(6041310)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123564045)(20161123558120)(20161123562045)(20161123560045)(201708071742011)(7699051)(76991095); SRVR:DB3PR0502MB4060; BCL:0; PCL:0; RULEID:; SRVR:DB3PR0502MB4060; x-forefront-prvs: 08444C7C87 x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(376002)(346002)(396003)(136003)(39860400002)(366004)(199004)(189003)(6436002)(25786009)(86362001)(256004)(66066001)(5660300001)(446003)(11346002)(14454004)(476003)(3846002)(81166006)(6512007)(14444005)(9686003)(6246003)(5024004)(33656002)(53946003)(53936002)(54906003)(6486002)(2900100001)(229853002)(7736002)(8936002)(81156014)(8676002)(71190400001)(305945005)(71200400001)(4744004)(33896004)(99286004)(186003)(52116002)(2906002)(76176011)(4326008)(26005)(386003)(6506007)(102836004)(6116002)(97736004)(106356001)(6636002)(68736007)(105586002)(316002)(478600001)(1076002)(6862004)(486006)(21314003); DIR:OUT; SFP:1101; SCL:1; SRVR:DB3PR0502MB4060; H:DB3PR0502MB3980.eurprd05.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; received-spf: None (protection.outlook.com: mellanox.com does not designate permitted sender hosts) x-microsoft-antispam-message-info: K3DKVrpKG7q7SiVi+U2/vce4Oyg0uyp9U5KCNcxo3Dq+MFskz5XqABhWivuj18b28/4zjLdow+CYEeJPw4Kd0hdqHt0rwPwUER3gNFCetxPXhvCa8ygzJMWrdVfQQ13EjD1uUAdteLJV1HjPv4UC05vUtPQLaMVmCp28HbftT/TllfcnwJlwh09/t1VgubQDuIFlNEsYb+EhJXXtSvEd/vqP8QNvqrmVy4Ve8gG2MYYPwLYCI14FIFNhp2i5weYSeKDe6MlQ4LhwGM+E4XfBQSEysrWHPT84/SNj1dylngh8eV8PafgfUj4ESc0i1J7sdW0WP75RMVDDeE3oNe9kwhNnX5qd1Su41oymidNOr7A= spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-Type: text/plain; charset="us-ascii" Content-ID: <633BBE721EC08D469A8D192CD2629778@eurprd05.prod.outlook.com> Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-Network-Message-Id: 00624206-ac27-4a3e-8e99-08d640565983 X-MS-Exchange-CrossTenant-originalarrivaltime: 02 Nov 2018 00:01:33.7506 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB3PR0502MB4060 Subject: Re: [dpdk-dev] [PATCH v3 13/13] net/mlx5: add e-switch VXLAN rule cleanup routines 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: , X-List-Received-Date: Fri, 02 Nov 2018 00:01:35 -0000 On Thu, Nov 01, 2018 at 05:19:35AM -0700, Slava Ovsiienko wrote: > The last part of patchset contains the rule cleanup routines. > These ones is the part of outer interface initialization at > the moment of VXLAN VTEP attaching. These routines query > the list of attached VXLAN devices, the list of local IP > addresses with peer and link scope attribute and the list > of permanent neigh rules, then all found abovementioned > items on the specified outer device are flushed. >=20 > Suggested-by: Adrien Mazarguil > Signed-off-by: Viacheslav Ovsiienko > --- Acked-by: Yongseok Koh Thanks > drivers/net/mlx5/mlx5_flow_tcf.c | 495 +++++++++++++++++++++++++++++++++= +++++- > 1 file changed, 494 insertions(+), 1 deletion(-) >=20 > diff --git a/drivers/net/mlx5/mlx5_flow_tcf.c b/drivers/net/mlx5/mlx5_flo= w_tcf.c > index eae80ae..420816f 100644 > --- a/drivers/net/mlx5/mlx5_flow_tcf.c > +++ b/drivers/net/mlx5/mlx5_flow_tcf.c > @@ -3756,6 +3756,496 @@ struct pedit_parser { > #define MNL_REQUEST_SIZE RTE_MIN(RTE_MAX(sysconf(_SC_PAGESIZE), \ > MNL_REQUEST_SIZE_MIN), MNL_REQUEST_SIZE_MAX) > =20 > +/* Data structures used by flow_tcf_xxx_cb() routines. */ > +struct tcf_nlcb_buf { > + LIST_ENTRY(tcf_nlcb_buf) next; > + uint32_t size; > + alignas(struct nlmsghdr) > + uint8_t msg[]; /**< Netlink message data. */ > +}; > + > +struct tcf_nlcb_context { > + unsigned int ifindex; /**< Base interface index. */ > + uint32_t bufsize; > + LIST_HEAD(, tcf_nlcb_buf) nlbuf; > +}; > + > +/** > + * Allocate space for netlink command in buffer list > + * > + * @param[in, out] ctx > + * Pointer to callback context with command buffers list. > + * @param[in] size > + * Required size of data buffer to be allocated. > + * > + * @return > + * Pointer to allocated memory, aligned as message header. > + * NULL if some error occurred. > + */ > +static struct nlmsghdr * > +flow_tcf_alloc_nlcmd(struct tcf_nlcb_context *ctx, uint32_t size) > +{ > + struct tcf_nlcb_buf *buf; > + struct nlmsghdr *nlh; > + > + size =3D NLMSG_ALIGN(size); > + buf =3D LIST_FIRST(&ctx->nlbuf); > + if (buf && (buf->size + size) <=3D ctx->bufsize) { > + nlh =3D (struct nlmsghdr *)&buf->msg[buf->size]; > + buf->size +=3D size; > + return nlh; > + } > + if (size > ctx->bufsize) { > + DRV_LOG(WARNING, "netlink: too long command buffer requested"); > + return NULL; > + } > + buf =3D rte_malloc(__func__, > + ctx->bufsize + sizeof(struct tcf_nlcb_buf), > + alignof(struct tcf_nlcb_buf)); > + if (!buf) { > + DRV_LOG(WARNING, "netlink: no memory for command buffer"); > + return NULL; > + } > + LIST_INSERT_HEAD(&ctx->nlbuf, buf, next); > + buf->size =3D size; > + nlh =3D (struct nlmsghdr *)&buf->msg[0]; > + return nlh; > +} > + > +/** > + * Set NLM_F_ACK flags in the last netlink command in buffer. > + * Only last command in the buffer will be acked by system. > + * > + * @param[in, out] buf > + * Pointer to buffer with netlink commands. > + */ > +static void > +flow_tcf_setack_nlcmd(struct tcf_nlcb_buf *buf) > +{ > + struct nlmsghdr *nlh; > + uint32_t size =3D 0; > + > + assert(buf->size); > + do { > + nlh =3D (struct nlmsghdr *)&buf->msg[size]; > + size +=3D NLMSG_ALIGN(nlh->nlmsg_len); > + if (size >=3D buf->size) { > + nlh->nlmsg_flags |=3D NLM_F_ACK; > + break; > + } > + } while (true); > +} > + > +/** > + * Send the buffers with prepared netlink commands. Scans the list and > + * sends all found buffers. Buffers are sent and freed anyway in order > + * to prevent memory leakage if some every message in received packet. > + * > + * @param[in] tcf > + * Context object initialized by mlx5_flow_tcf_context_create(). > + * @param[in, out] ctx > + * Pointer to callback context with command buffers list. > + * > + * @return > + * Zero value on success, negative errno value otherwise > + * and rte_errno is set. > + */ > +static int > +flow_tcf_send_nlcmd(struct mlx5_flow_tcf_context *tcf, > + struct tcf_nlcb_context *ctx) > +{ > + struct tcf_nlcb_buf *bc, *bn; > + struct nlmsghdr *nlh; > + int ret =3D 0; > + > + bc =3D LIST_FIRST(&ctx->nlbuf); > + while (bc) { > + int rc; > + > + bn =3D LIST_NEXT(bc, next); > + if (bc->size) { > + flow_tcf_setack_nlcmd(bc); > + nlh =3D (struct nlmsghdr *)&bc->msg; > + rc =3D flow_tcf_nl_ack(tcf, nlh, bc->size, NULL, NULL); > + if (rc && !ret) > + ret =3D rc; > + } > + rte_free(bc); > + bc =3D bn; > + } > + LIST_INIT(&ctx->nlbuf); > + return ret; > +} > + > +/** > + * Collect local IP address rules with scope link attribute on specifie= d > + * network device. This is callback routine called by libmnl mnl_cb_run(= ) > + * in loop for every message in received packet. > + * > + * @param[in] nlh > + * Pointer to reply header. > + * @param[in, out] arg > + * Opaque data pointer for this callback. > + * > + * @return > + * A positive, nonzero value on success, negative errno value otherwis= e > + * and rte_errno is set. > + */ > +static int > +flow_tcf_collect_local_cb(const struct nlmsghdr *nlh, void *arg) > +{ > + struct tcf_nlcb_context *ctx =3D arg; > + struct nlmsghdr *cmd; > + struct ifaddrmsg *ifa; > + struct nlattr *na; > + struct nlattr *na_local =3D NULL; > + struct nlattr *na_peer =3D NULL; > + unsigned char family; > + > + if (nlh->nlmsg_type !=3D RTM_NEWADDR) { > + rte_errno =3D EINVAL; > + return -rte_errno; > + } > + ifa =3D mnl_nlmsg_get_payload(nlh); > + family =3D ifa->ifa_family; > + if (ifa->ifa_index !=3D ctx->ifindex || > + ifa->ifa_scope !=3D RT_SCOPE_LINK || > + !(ifa->ifa_flags & IFA_F_PERMANENT) || > + (family !=3D AF_INET && family !=3D AF_INET6)) > + return 1; > + mnl_attr_for_each(na, nlh, sizeof(*ifa)) { > + switch (mnl_attr_get_type(na)) { > + case IFA_LOCAL: > + na_local =3D na; > + break; > + case IFA_ADDRESS: > + na_peer =3D na; > + break; > + } > + if (na_local && na_peer) > + break; > + } > + if (!na_local || !na_peer) > + return 1; > + /* Local rule found with scope link, permanent and assigned peer. */ > + cmd =3D flow_tcf_alloc_nlcmd(ctx, MNL_ALIGN(sizeof(struct nlmsghdr)) + > + MNL_ALIGN(sizeof(struct ifaddrmsg)) + > + (family =3D=3D AF_INET6 > + ? 2 * SZ_NLATTR_DATA_OF(IPV6_ADDR_LEN) > + : 2 * SZ_NLATTR_TYPE_OF(uint32_t))); > + if (!cmd) { > + rte_errno =3D ENOMEM; > + return -rte_errno; > + } > + cmd =3D mnl_nlmsg_put_header(cmd); > + cmd->nlmsg_type =3D RTM_DELADDR; > + cmd->nlmsg_flags =3D NLM_F_REQUEST; > + ifa =3D mnl_nlmsg_put_extra_header(cmd, sizeof(*ifa)); > + ifa->ifa_flags =3D IFA_F_PERMANENT; > + ifa->ifa_scope =3D RT_SCOPE_LINK; > + ifa->ifa_index =3D ctx->ifindex; > + if (family =3D=3D AF_INET) { > + ifa->ifa_family =3D AF_INET; > + ifa->ifa_prefixlen =3D 32; > + mnl_attr_put_u32(cmd, IFA_LOCAL, mnl_attr_get_u32(na_local)); > + mnl_attr_put_u32(cmd, IFA_ADDRESS, mnl_attr_get_u32(na_peer)); > + } else { > + ifa->ifa_family =3D AF_INET6; > + ifa->ifa_prefixlen =3D 128; > + mnl_attr_put(cmd, IFA_LOCAL, IPV6_ADDR_LEN, > + mnl_attr_get_payload(na_local)); > + mnl_attr_put(cmd, IFA_ADDRESS, IPV6_ADDR_LEN, > + mnl_attr_get_payload(na_peer)); > + } > + return 1; > +} > + > +/** > + * Cleanup the local IP addresses on outer interface. > + * > + * @param[in] tcf > + * Context object initialized by mlx5_flow_tcf_context_create(). > + * @param[in] ifindex > + * Network inferface index to perform cleanup. > + */ > +static void > +flow_tcf_encap_local_cleanup(struct mlx5_flow_tcf_context *tcf, > + unsigned int ifindex) > +{ > + struct nlmsghdr *nlh; > + struct ifaddrmsg *ifa; > + struct tcf_nlcb_context ctx =3D { > + .ifindex =3D ifindex, > + .bufsize =3D MNL_REQUEST_SIZE, > + .nlbuf =3D LIST_HEAD_INITIALIZER(), > + }; > + int ret; > + > + assert(ifindex); > + /* > + * Seek and destroy leftovers of local IP addresses with > + * matching properties "scope link". > + */ > + nlh =3D mnl_nlmsg_put_header(tcf->buf); > + nlh->nlmsg_type =3D RTM_GETADDR; > + nlh->nlmsg_flags =3D NLM_F_REQUEST | NLM_F_DUMP; > + ifa =3D mnl_nlmsg_put_extra_header(nlh, sizeof(*ifa)); > + ifa->ifa_family =3D AF_UNSPEC; > + ifa->ifa_index =3D ifindex; > + ifa->ifa_scope =3D RT_SCOPE_LINK; > + ret =3D flow_tcf_nl_ack(tcf, nlh, 0, flow_tcf_collect_local_cb, &ctx); > + if (ret) > + DRV_LOG(WARNING, "netlink: query device list error %d", ret); > + ret =3D flow_tcf_send_nlcmd(tcf, &ctx); > + if (ret) > + DRV_LOG(WARNING, "netlink: device delete error %d", ret); > +} > + > +/** > + * Collect neigh permament rules on specified network device. > + * This is callback routine called by libmnl mnl_cb_run() in loop for > + * every message in received packet. > + * > + * @param[in] nlh > + * Pointer to reply header. > + * @param[in, out] arg > + * Opaque data pointer for this callback. > + * > + * @return > + * A positive, nonzero value on success, negative errno value otherwis= e > + * and rte_errno is set. > + */ > +static int > +flow_tcf_collect_neigh_cb(const struct nlmsghdr *nlh, void *arg) > +{ > + struct tcf_nlcb_context *ctx =3D arg; > + struct nlmsghdr *cmd; > + struct ndmsg *ndm; > + struct nlattr *na; > + struct nlattr *na_ip =3D NULL; > + struct nlattr *na_mac =3D NULL; > + unsigned char family; > + > + if (nlh->nlmsg_type !=3D RTM_NEWNEIGH) { > + rte_errno =3D EINVAL; > + return -rte_errno; > + } > + ndm =3D mnl_nlmsg_get_payload(nlh); > + family =3D ndm->ndm_family; > + if (ndm->ndm_ifindex !=3D (int)ctx->ifindex || > + !(ndm->ndm_state & NUD_PERMANENT) || > + (family !=3D AF_INET && family !=3D AF_INET6)) > + return 1; > + mnl_attr_for_each(na, nlh, sizeof(*ndm)) { > + switch (mnl_attr_get_type(na)) { > + case NDA_DST: > + na_ip =3D na; > + break; > + case NDA_LLADDR: > + na_mac =3D na; > + break; > + } > + if (na_mac && na_ip) > + break; > + } > + if (!na_mac || !na_ip) > + return 1; > + /* Neigh rule with permenent attribute found. */ > + cmd =3D flow_tcf_alloc_nlcmd(ctx, MNL_ALIGN(sizeof(struct nlmsghdr)) + > + MNL_ALIGN(sizeof(struct ndmsg)) + > + SZ_NLATTR_DATA_OF(ETHER_ADDR_LEN) + > + (family =3D=3D AF_INET6 > + ? SZ_NLATTR_DATA_OF(IPV6_ADDR_LEN) > + : SZ_NLATTR_TYPE_OF(uint32_t))); > + if (!cmd) { > + rte_errno =3D ENOMEM; > + return -rte_errno; > + } > + cmd =3D mnl_nlmsg_put_header(cmd); > + cmd->nlmsg_type =3D RTM_DELNEIGH; > + cmd->nlmsg_flags =3D NLM_F_REQUEST; > + ndm =3D mnl_nlmsg_put_extra_header(cmd, sizeof(*ndm)); > + ndm->ndm_ifindex =3D ctx->ifindex; > + ndm->ndm_state =3D NUD_PERMANENT; > + ndm->ndm_flags =3D 0; > + ndm->ndm_type =3D 0; > + if (family =3D=3D AF_INET) { > + ndm->ndm_family =3D AF_INET; > + mnl_attr_put_u32(cmd, NDA_DST, mnl_attr_get_u32(na_ip)); > + } else { > + ndm->ndm_family =3D AF_INET6; > + mnl_attr_put(cmd, NDA_DST, IPV6_ADDR_LEN, > + mnl_attr_get_payload(na_ip)); > + } > + mnl_attr_put(cmd, NDA_LLADDR, ETHER_ADDR_LEN, > + mnl_attr_get_payload(na_mac)); > + return 1; > +} > + > +/** > + * Cleanup the neigh rules on outer interface. > + * > + * @param[in] tcf > + * Context object initialized by mlx5_flow_tcf_context_create(). > + * @param[in] ifindex > + * Network inferface index to perform cleanup. > + */ > +static void > +flow_tcf_encap_neigh_cleanup(struct mlx5_flow_tcf_context *tcf, > + unsigned int ifindex) > +{ > + struct nlmsghdr *nlh; > + struct ndmsg *ndm; > + struct tcf_nlcb_context ctx =3D { > + .ifindex =3D ifindex, > + .bufsize =3D MNL_REQUEST_SIZE, > + .nlbuf =3D LIST_HEAD_INITIALIZER(), > + }; > + int ret; > + > + assert(ifindex); > + /* Seek and destroy leftovers of neigh rules. */ > + nlh =3D mnl_nlmsg_put_header(tcf->buf); > + nlh->nlmsg_type =3D RTM_GETNEIGH; > + nlh->nlmsg_flags =3D NLM_F_REQUEST | NLM_F_DUMP; > + ndm =3D mnl_nlmsg_put_extra_header(nlh, sizeof(*ndm)); > + ndm->ndm_family =3D AF_UNSPEC; > + ndm->ndm_ifindex =3D ifindex; > + ndm->ndm_state =3D NUD_PERMANENT; > + ret =3D flow_tcf_nl_ack(tcf, nlh, 0, flow_tcf_collect_neigh_cb, &ctx); > + if (ret) > + DRV_LOG(WARNING, "netlink: query device list error %d", ret); > + ret =3D flow_tcf_send_nlcmd(tcf, &ctx); > + if (ret) > + DRV_LOG(WARNING, "netlink: device delete error %d", ret); > +} > + > +/** > + * Collect indices of VXLAN encap/decap interfaces associated with devic= e. > + * This is callback routine called by libmnl mnl_cb_run() in loop for > + * every message in received packet. > + * > + * @param[in] nlh > + * Pointer to reply header. > + * @param[in, out] arg > + * Opaque data pointer for this callback. > + * > + * @return > + * A positive, nonzero value on success, negative errno value otherwis= e > + * and rte_errno is set. > + */ > +static int > +flow_tcf_collect_vxlan_cb(const struct nlmsghdr *nlh, void *arg) > +{ > + struct tcf_nlcb_context *ctx =3D arg; > + struct nlmsghdr *cmd; > + struct ifinfomsg *ifm; > + struct nlattr *na; > + struct nlattr *na_info =3D NULL; > + struct nlattr *na_vxlan =3D NULL; > + bool found =3D false; > + unsigned int vxindex; > + > + if (nlh->nlmsg_type !=3D RTM_NEWLINK) { > + rte_errno =3D EINVAL; > + return -rte_errno; > + } > + ifm =3D mnl_nlmsg_get_payload(nlh); > + if (!ifm->ifi_index) { > + rte_errno =3D EINVAL; > + return -rte_errno; > + } > + mnl_attr_for_each(na, nlh, sizeof(*ifm)) > + if (mnl_attr_get_type(na) =3D=3D IFLA_LINKINFO) { > + na_info =3D na; > + break; > + } > + if (!na_info) > + return 1; > + mnl_attr_for_each_nested(na, na_info) { > + switch (mnl_attr_get_type(na)) { > + case IFLA_INFO_KIND: > + if (!strncmp("vxlan", mnl_attr_get_str(na), > + mnl_attr_get_len(na))) > + found =3D true; > + break; > + case IFLA_INFO_DATA: > + na_vxlan =3D na; > + break; > + } > + if (found && na_vxlan) > + break; > + } > + if (!found || !na_vxlan) > + return 1; > + found =3D false; > + mnl_attr_for_each_nested(na, na_vxlan) { > + if (mnl_attr_get_type(na) =3D=3D IFLA_VXLAN_LINK && > + mnl_attr_get_u32(na) =3D=3D ctx->ifindex) { > + found =3D true; > + break; > + } > + } > + if (!found) > + return 1; > + /* Attached VXLAN device found, store the command to delete. */ > + vxindex =3D ifm->ifi_index; > + cmd =3D flow_tcf_alloc_nlcmd(ctx, MNL_ALIGN(sizeof(struct nlmsghdr)) + > + MNL_ALIGN(sizeof(struct ifinfomsg))); > + if (!nlh) { > + rte_errno =3D ENOMEM; > + return -rte_errno; > + } > + cmd =3D mnl_nlmsg_put_header(cmd); > + cmd->nlmsg_type =3D RTM_DELLINK; > + cmd->nlmsg_flags =3D NLM_F_REQUEST; > + ifm =3D mnl_nlmsg_put_extra_header(cmd, sizeof(*ifm)); > + ifm->ifi_family =3D AF_UNSPEC; > + ifm->ifi_index =3D vxindex; > + return 1; > +} > + > +/** > + * Cleanup the outer interface. Removes all found vxlan devices > + * attached to specified index, flushes the meigh and local IP > + * datavase. > + * > + * @param[in] tcf > + * Context object initialized by mlx5_flow_tcf_context_create(). > + * @param[in] ifindex > + * Network inferface index to perform cleanup. > + */ > +static void > +flow_tcf_encap_iface_cleanup(struct mlx5_flow_tcf_context *tcf, > + unsigned int ifindex) > +{ > + struct nlmsghdr *nlh; > + struct ifinfomsg *ifm; > + struct tcf_nlcb_context ctx =3D { > + .ifindex =3D ifindex, > + .bufsize =3D MNL_REQUEST_SIZE, > + .nlbuf =3D LIST_HEAD_INITIALIZER(), > + }; > + int ret; > + > + assert(ifindex); > + /* > + * Seek and destroy leftover VXLAN encap/decap interfaces with > + * matching properties. > + */ > + nlh =3D mnl_nlmsg_put_header(tcf->buf); > + nlh->nlmsg_type =3D RTM_GETLINK; > + nlh->nlmsg_flags =3D NLM_F_REQUEST | NLM_F_DUMP; > + ifm =3D mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm)); > + ifm->ifi_family =3D AF_UNSPEC; > + ret =3D flow_tcf_nl_ack(tcf, nlh, 0, flow_tcf_collect_vxlan_cb, &ctx); > + if (ret) > + DRV_LOG(WARNING, "netlink: query device list error %d", ret); > + ret =3D flow_tcf_send_nlcmd(tcf, &ctx); > + if (ret) > + DRV_LOG(WARNING, "netlink: device delete error %d", ret); > +} > + > /** > * Emit Netlink message to add/remove local address to the outer device. > * The address being added is visible within the link only (scope link). > @@ -4325,7 +4815,7 @@ struct pedit_parser { > rte_flow_error_set(error, ENOTSUP, > RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, > "netlink: failed to create VTEP, " > - "VXLAN metadata are not supported by kernel"); > + "vxlan metadata are not supported by kernel"); > return NULL; > } > #endif /* HAVE_IFLA_VXLAN_COLLECT_METADATA */ > @@ -4415,6 +4905,9 @@ struct pedit_parser { > uint16_t pcnt; > =20 > /* Not found, we should create the new attached VTEP. */ > + flow_tcf_encap_iface_cleanup(tcf, ifouter); > + flow_tcf_encap_local_cleanup(tcf, ifouter); > + flow_tcf_encap_neigh_cleanup(tcf, ifouter); > for (pcnt =3D 0; pcnt <=3D (MLX5_VXLAN_PORT_MAX > - MLX5_VXLAN_PORT_MIN); pcnt++) { > encap_port++; > --=20 > 1.8.3.1 >=20