From patchwork Mon Oct 15 14:13:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slava Ovsiienko X-Patchwork-Id: 46848 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 0290B2BF5; Mon, 15 Oct 2018 16:14:19 +0200 (CEST) Received: from EUR03-AM5-obe.outbound.protection.outlook.com (mail-eopbgr30089.outbound.protection.outlook.com [40.107.3.89]) by dpdk.org (Postfix) with ESMTP id D13B323D for ; Mon, 15 Oct 2018 16:14:10 +0200 (CEST) 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=Q2q0UMamfwKFo1qXuyxMAapcrc/ySa8x0h8jBoP5On8=; b=Xp5EymBtFemg7OwGQKbM0B2cfITjpZ+aVViQY9in7E3R+Ls7BIFtvKlWCW5I4h3nYbJa3ZSLd7oPIvOYXQdCgpFoAKP/h3ptt9rPEqvujKMp4BAE7q05EQmdzErrdWFyTkxMizSDJHxixFezG5tH1raUYsh1wy4xQbWl/dCFo5g= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=viacheslavo@mellanox.com; Received: from mellanox.com (37.142.13.130) by VI1PR05MB3277.eurprd05.prod.outlook.com (2603:10a6:802:1c::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1228.24; Mon, 15 Oct 2018 14:14:09 +0000 From: Viacheslav Ovsiienko To: shahafs@mellanox.com, yskoh@mellanox.com Cc: dev@dpdk.org, Viacheslav Ovsiienko Date: Mon, 15 Oct 2018 14:13:29 +0000 Message-Id: <1539612815-47199-2-git-send-email-viacheslavo@mellanox.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1539612815-47199-1-git-send-email-viacheslavo@mellanox.com> References: <1538461807-37507-1-git-send-email-viacheslavo@mellanox.com> <1539612815-47199-1-git-send-email-viacheslavo@mellanox.com> MIME-Version: 1.0 X-Originating-IP: [37.142.13.130] X-ClientProxiedBy: CWLP265CA0084.GBRP265.PROD.OUTLOOK.COM (2603:10a6:401:50::24) To VI1PR05MB3277.eurprd05.prod.outlook.com (2603:10a6:802:1c::22) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 98e61dbb-5966-4573-2b1a-08d632a879bb 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:VI1PR05MB3277; X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 3:5hBugUCZXHXSuu6qDIRFTIA0XUqqzx3ZbFwLb7cMNcVYVKWZ8C/jmE8Ml04kdQJQJztv3t/xJhLu0jXPUQKS4qCQa6L7v55ngpRM03mF0DIaGmJw89ySbJYr5GKG/a2QJfZUwszF5EQvqAOKt1IhuEhOmvmpVOiro3kbSvKbZ951UbRcSca+w0CwOtBuTMglQCtg7nsvtvKKRwUD2IHg8LdX5RmRYUln1RNT6rG9G47Zl131qi8iNGratuPYg84y; 25:P/1JqzyF9g4T4JYu3owzlA+nWzrRDXR1JfiS5QsNLDbW4aTWwXY9gTNFYcG/QvZ4jud6nV1blk7El51W00gwltwWaF+XuAxZz3S6RenZFBIrJRaMIrzUvZ/VPXQQd4JxmPLlwoTu1wmhNeEXOLLA1HeWInsSDj6JCokDFmx5G2Nc4XmX7wIKYT1tj+dK14o3OPGhEAiOT3pLFlkhq5Ntj7f5nrxfoJqAzgSfddFn8ndTn+h62dijCPbtVPitLiZ8BJfearhdzQonbDkkERVIfG/Ob504Mt6Gmrae8msqvHjusHzmUgaKyrgE8f7DLckR65G36Z4c3ReOGzVUBZKlsg==; 31:KtShIT95vIN5/4rsy6OJk4TZmser6YWxWUmxrqZiK7e7yeJoqHYC+xLCnfd49AXaXbu91wkGtXzq3OR4LowaWYa4+Gy1NdLa4SG4+R9J2cgtWYSWL0qDnCkCsDjOBTABlI1PnU2OaybanIBusAyqNcdewkUUOUtbk9kdF0iMkg59uqSwn0kvcpBq6rME+xny8lstBsOYP+rHJs2/WEDgWILl5t4Uq2vzkPB4ypdp+1U= X-MS-TrafficTypeDiagnostic: VI1PR05MB3277: X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 20:Ly//bLPAXnUG+gyoLLSn9XtpTsPFaxOhQOqP88eVadvgXi4iB0qkxN4IWIOSyJCMkRYdVScwxXDsOciBfwycgKzzXmZ/F35N0dToNQC7P37+qsJEuEZ2xLPHMNb6dYnJafBKvbHOYBMrk8PJq9sSQvFu6suZruEpJUwLDEfru/7dgov6BGQrZD5MQNvl0jCYPs62ekLcEr5NkVSolktShjNLBlabs6/+DQ2nC/JjYpIvCXwKC65Q8Hwx3rVslFArOnALbWJJdmLuuAbq3TbpDs2qHTNBZPHKXzJA4utIM7klJ4qhIh5PG0UNYwSi3qUrGEHECH24NrKbg2fCq04E38CqKZajm0ylhi+iO5DA+cG+6xULhgwAg8vyElzWHe+0z5qo2OJluaY6Q45wXwKzHlsblcDe8Ml2pcWHXqrZXMdtMoQNd+X+1+XXjpdmlyh8FPgaYvkE3BfV0RN+aLuQI//yh1mz/B5damPzG+2x8iISv/IKaBw1MPZDZeq+CFcD; 4:7sS0o2rC9EJWCVuChJAGPrApXBmbnkRiUCvx4WftL7UU+Ud/eSd5Dc2WUUKyTrCcvltdZyEYEB5d+sIEyeEaDYwOxvcjM7RJbHFeXI/qqtgVxhmnOgUGJSZEk1oJ855nwbxOi4ErOvGRUxoeZvq0oD9F75SoKGtrEMYlDRHDWLPH+2moLVcWoAicKxImW4I3M7nVk3NyqxciLJguvouD1WoBInrFb8EX439fjXn8F+KfeDF9X2aP0qfiYh0pBwMZ9cK3eYtTOl7m5pC/OetizQ== 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)(3002001)(3231355)(944501410)(52105095)(10201501046)(93006095)(93001095)(6055026)(149066)(150057)(6041310)(20161123560045)(20161123558120)(20161123562045)(20161123564045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(201708071742011)(7699051); SRVR:VI1PR05MB3277; BCL:0; PCL:0; RULEID:; SRVR:VI1PR05MB3277; X-Forefront-PRVS: 0826B2F01B X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(136003)(39860400002)(376002)(346002)(366004)(396003)(199004)(189003)(107886003)(16526019)(66066001)(7736002)(8676002)(47776003)(106356001)(51416003)(7696005)(52116002)(25786009)(68736007)(105586002)(186003)(16586007)(305945005)(8936002)(3846002)(81166006)(81156014)(6116002)(386003)(50226002)(6666004)(50466002)(11346002)(5024004)(86362001)(575784001)(446003)(76176011)(97736004)(6636002)(21086003)(36756003)(2906002)(33026002)(4720700003)(69596002)(53936002)(55016002)(48376002)(85306007)(478600001)(476003)(8886007)(316002)(26005)(4326008)(4744004)(486006)(2616005)(5660300001)(956004); DIR:OUT; SFP:1101; SCL:1; SRVR:VI1PR05MB3277; H:mellanox.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-Exchange-Diagnostics: =?us-ascii?Q?1; VI1PR05MB3277; 23:vQ0uII02yEuP4XgG+yghqEJUpelKpGPQrezNJh2kY?= HStRSNDe0A+Qukv1UZeiNlVoZwnKCPGHo8KHc6tPzK/IKRvH56sgwXFC31WKL0jDfxWcKSlp+ccb8vdaFIXK1qx6QA1SOdJLQw7grxgR5AQFkp7mgHk4RoyUvFqFWSZGC2jCjbT0DD5ykMvOOguWidgHPzb8kTHdhl0Oka5TLrqhnpMK8uF5MnhvpHFGcl6uaesOEZ46QphRy2hEt1ZPxQLGQYXtZn+ti1f/ovpyEaeJB0DG8tIDbZG4rPXK/STYeCgqBechfNjgYyiLzjCkicF4t2309nxe8IlbNvmwNOyaHxsRfQtlRGqeo5N1Tf8DLfOvH+eaM+pDPL8ebNHF3BhXpUk43qHavgApo1PAXZJsD6BwLIaSVyBASidYRlW5Md5vSvqN13TL0W+ybUfyq7Ddkm8AznId80i5DydI/MF20xNsXvPYWC3MFoxcIVaHvA8pM0JZJFhBXbpdAskYabuCWzyFpmHEj4diRQff5no1Y7YFmWADMzvIw09kA84syALq7MfQHsLth/cUqcxV9+UryEsIamMkrYkUHrSRQDL2KifKQmwmI/DoRuXpsGq0tnW/RXje/fEXyM4rvRSNQ2aVfd3DYbP4dq/5DSLc5Nj8vUoEoe8lUqec9k84PZuw/XGZasmtatg+Cg+aUAVpPFz+Ul4IFqSur5UJBffIBlLH7wTIEyEqy7Wl5Eg78IsGdHErEUaEUBVg+pJ9aadxKhMrwAaBw/Ze4iJFDwPDIX//cuRLOKFSMGRpWz4EnFZjYwQq2SXWDt6LfLiB7fL+hhhs+zBbyDPz1nFU9BBIB57VbiAbQZTaaur6aeuHTqWjdzRcLWJ0eMtrepBwUiuQPLHCZIux+NK+ZDmIUJW91e0LdERi7pZx8y9VWXQKdNP80sAF7cNCEXomue2iPSQqghsOK6SIrRavHcY2XE4NWUL3bMhZODp+g9PSgt0NBGofe3G5/tCaiibT7aKCLcxid/QXdP/7VH3Skq0Ots47//oLvS2ct5nb0BXfsaMMhdRpXv9Mrf5J93PLo0/qHoPcNXhPjzBjTmsAIWKw0XWnvqyolPgIwOwaHzQ1xrlM71G6mP0QDlXjXASomw6fMdulO+BJ4vsdcSi+Z3ZxjeG832EZhYD6TKMKCGrLhtWQmxoAeS92DREdyrz5jezsxm/jZJB3R8CPiKbzLm82mzxlfsWr/ObPi/q0lRUrf82npaYtW35EbZBVAJHzuabUc3bV0HtBupjQzxOJEI9+L8YtTbcIF97F0LIa4oaKj0xDH5WkISBceggZD8puHa0JToYmnjuk+SSo5bBlUmdh8fsQh2JBw== X-Microsoft-Antispam-Message-Info: /IV760hls6Z1qfJN/8/SAgRjBS5GIuYlcAWaHRUhFzI8Qx0AnJigitm+pYW7yImYzzJNrww27YASmGicso9xVMV5z3MAomS5UC9Pb1z+rUG6iH1UWLj7suFEJJM1anaRy6Qzl/VA3MxQlSg9KOwTslSFvd4zxav4PkGyOSZU9LY0uQPNjgfB6P+k8gkSpjfsHsJVQ/VfdmMaWI94L8yX1pg3iKMJSayyzQK5d6j6EvNpEIi6gyhWGUQ79ku/1L777LoT1G1xg6bdtXCkMrfrb/xCjHeJ5QIGFbY1yFMDo9Nv7lATpZuY2gSbWdS5VeTigSGX5IpJr2RfNjhmZBgggs9X6I0BXe3BZpFaXegcwHc= X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 6:pz30+BtS1U+8L9DUdnCVBKk1R6TekqAqxxdv4Jc6LhJHN/FA7+eFQGYpMlOWaUmOxTOOce3H7LAw1Mx4dO/76BOiGED/eD4+BeAo4oEwF+G2UeT8FsyY047V/U9da2TFOtreq7gxqu1/WVCNswcqykd9QqxsTdq46DGC4H8sYOU38K/BrHUfMryTewSjbhKm8DMlsJK70+u5Q36Q5KBUuGjaLzvMVn9ihtQ2pixFlRbZmnx7+XdiBynxL5b4cKBlQsBs8AXW8rbmChFeOEK5QG7AQ13DyftkhemuOwJ7ewxnt7Xy8lREw8JRYDyZCbM+HnhqfX7jHrjSUiaJdtcDZXXYrDWUPD732zFNevpNpYcGqEiAmM/34bfpxacHNXwnu829pOj63WPIs1vvoBdwX3A0j9Y/R9lujzIyyW3DyzgS4xkyMcxGnWACORdSaBBE8lgSNFTnCYgvSmGf5GpI4A==; 5:kkcsv5IrD3zivzbiozpLP5erj6ouVEkhP5vrQSdGdiZNPfFXvNVYXzH8+wRuzI6iwxpA/viiWOMWDcmPnJXnzJgtUptYnV49zJ/IW/jam++UDWQpL2b9Mrf4GH3SmMFa7sfBeCVGv3A2Sp46wjgHrBVcMF78CsoIyXu4tITjj5w=; 7:xUKzvIzIqZ9GkI2kasNthxP7MuQtvVV+iuTmeGHTpWv43rXm5euZlL+nWbIFqie50eT9mKPVi1qQAq/3xGloN1dTeh0ducyoZMHgV23SWFCAdDlf1VLkjOt9ygWe8WXcAfuhzGMk0QsjBKfTiQNvzL1ORF5olggyZTpFPR4TYLAZlWBFZq66HAXWBfjDztc+++yeHfVtvFFO8am8F6OX/hQA6CagwNnLgzkxKAj+gYwuoAUTRZkYT6MRXgMB1WSX SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Oct 2018 14:14:09.1926 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 98e61dbb-5966-4573-2b1a-08d632a879bb X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR05MB3277 Subject: [dpdk-dev] [PATCH v2 1/7] net/mlx5: e-switch VXLAN configuration and definitions 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" This part of patchset adds configuration changes in makefile and meson.build for Mellanox MLX5 PMD. Also necessary defenitions for VXLAN support are made and appropriate data structures are presented. Suggested-by: Adrien Mazarguil Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/Makefile | 80 ++++++++++++++++++ drivers/net/mlx5/meson.build | 32 +++++++ drivers/net/mlx5/mlx5_flow.h | 11 +++ drivers/net/mlx5/mlx5_flow_tcf.c | 175 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 298 insertions(+) diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile index 1e9c0b4..fec7779 100644 --- a/drivers/net/mlx5/Makefile +++ b/drivers/net/mlx5/Makefile @@ -207,6 +207,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh enum IFLA_PHYS_PORT_NAME \ $(AUTOCONF_OUTPUT) $Q sh -- '$<' '$@' \ + HAVE_IFLA_VXLAN_COLLECT_METADATA \ + linux/if_link.h \ + enum IFLA_VXLAN_COLLECT_METADATA \ + $(AUTOCONF_OUTPUT) + $Q sh -- '$<' '$@' \ HAVE_TCA_CHAIN \ linux/rtnetlink.h \ enum TCA_CHAIN \ @@ -367,6 +372,81 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh enum TCA_VLAN_PUSH_VLAN_PRIORITY \ $(AUTOCONF_OUTPUT) $Q sh -- '$<' '$@' \ + HAVE_TCA_FLOWER_KEY_ENC_KEY_ID \ + linux/pkt_cls.h \ + enum TCA_FLOWER_KEY_ENC_KEY_ID \ + $(AUTOCONF_OUTPUT) + $Q sh -- '$<' '$@' \ + HAVE_TCA_FLOWER_KEY_ENC_IPV4_SRC \ + linux/pkt_cls.h \ + enum TCA_FLOWER_KEY_ENC_IPV4_SRC \ + $(AUTOCONF_OUTPUT) + $Q sh -- '$<' '$@' \ + HAVE_TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK \ + linux/pkt_cls.h \ + enum TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK \ + $(AUTOCONF_OUTPUT) + $Q sh -- '$<' '$@' \ + HAVE_TCA_FLOWER_KEY_ENC_IPV4_DST \ + linux/pkt_cls.h \ + enum TCA_FLOWER_KEY_ENC_IPV4_DST \ + $(AUTOCONF_OUTPUT) + $Q sh -- '$<' '$@' \ + HAVE_TCA_FLOWER_KEY_ENC_IPV4_DST_MASK \ + linux/pkt_cls.h \ + enum TCA_FLOWER_KEY_ENC_IPV4_DST_MASK \ + $(AUTOCONF_OUTPUT) + $Q sh -- '$<' '$@' \ + HAVE_TCA_FLOWER_KEY_ENC_IPV6_SRC \ + linux/pkt_cls.h \ + enum TCA_FLOWER_KEY_ENC_IPV6_SRC \ + $(AUTOCONF_OUTPUT) + $Q sh -- '$<' '$@' \ + HAVE_TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK \ + linux/pkt_cls.h \ + enum TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK \ + $(AUTOCONF_OUTPUT) + $Q sh -- '$<' '$@' \ + HAVE_TCA_FLOWER_KEY_ENC_IPV6_DST \ + linux/pkt_cls.h \ + enum TCA_FLOWER_KEY_ENC_IPV6_DST \ + $(AUTOCONF_OUTPUT) + $Q sh -- '$<' '$@' \ + HAVE_TCA_FLOWER_KEY_ENC_IPV6_DST_MASK \ + linux/pkt_cls.h \ + enum TCA_FLOWER_KEY_ENC_IPV6_DST_MASK \ + $(AUTOCONF_OUTPUT) + $Q sh -- '$<' '$@' \ + HAVE_TCA_FLOWER_KEY_ENC_UDP_SRC_PORT \ + linux/pkt_cls.h \ + enum TCA_FLOWER_KEY_ENC_UDP_SRC_PORT \ + $(AUTOCONF_OUTPUT) + $Q sh -- '$<' '$@' \ + HAVE_TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK \ + linux/pkt_cls.h \ + enum TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK \ + $(AUTOCONF_OUTPUT) + $Q sh -- '$<' '$@' \ + HAVE_TCA_FLOWER_KEY_ENC_UDP_DST_PORT \ + linux/pkt_cls.h \ + enum TCA_FLOWER_KEY_ENC_UDP_DST_PORT \ + $(AUTOCONF_OUTPUT) + $Q sh -- '$<' '$@' \ + HAVE_TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK \ + linux/pkt_cls.h \ + enum TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK \ + $(AUTOCONF_OUTPUT) + $Q sh -- '$<' '$@' \ + HAVE_TC_ACT_TUNNEL_KEY \ + linux/tc_act/tc_tunnel_key.h \ + define TCA_ACT_TUNNEL_KEY \ + $(AUTOCONF_OUTPUT) + $Q sh -- '$<' '$@' \ + HAVE_TCA_TUNNEL_KEY_ENC_DST_PORT \ + linux/tc_act/tc_tunnel_key.h \ + enum TCA_TUNNEL_KEY_ENC_DST_PORT \ + $(AUTOCONF_OUTPUT) + $Q sh -- '$<' '$@' \ HAVE_TC_ACT_PEDIT \ linux/tc_act/tc_pedit.h \ enum TCA_PEDIT_KEY_EX_HDR_TYPE_UDP \ diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build index c192d44..43aabf2 100644 --- a/drivers/net/mlx5/meson.build +++ b/drivers/net/mlx5/meson.build @@ -126,6 +126,8 @@ if build 'IFLA_PHYS_SWITCH_ID' ], [ 'HAVE_IFLA_PHYS_PORT_NAME', 'linux/if_link.h', 'IFLA_PHYS_PORT_NAME' ], + [ 'HAVE_IFLA_VXLAN_COLLECT_METADATA', 'linux/if_link.h', + 'IFLA_VXLAN_COLLECT_METADATA' ], [ 'HAVE_TCA_CHAIN', 'linux/rtnetlink.h', 'TCA_CHAIN' ], [ 'HAVE_TCA_FLOWER_ACT', 'linux/pkt_cls.h', @@ -190,6 +192,36 @@ if build 'TC_ACT_GOTO_CHAIN' ], [ 'HAVE_TC_ACT_VLAN', 'linux/tc_act/tc_vlan.h', 'TCA_VLAN_PUSH_VLAN_PRIORITY' ], + [ 'HAVE_TCA_FLOWER_KEY_ENC_KEY_ID', 'linux/pkt_cls.h', + 'TCA_FLOWER_KEY_ENC_KEY_ID' ], + [ 'HAVE_TCA_FLOWER_KEY_ENC_IPV4_SRC', 'linux/pkt_cls.h', + 'TCA_FLOWER_KEY_ENC_IPV4_SRC' ], + [ 'HAVE_TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK', 'linux/pkt_cls.h', + 'TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK' ], + [ 'HAVE_TCA_FLOWER_KEY_ENC_IPV4_DST', 'linux/pkt_cls.h', + 'TCA_FLOWER_KEY_ENC_IPV4_DST' ], + [ 'HAVE_TCA_FLOWER_KEY_ENC_IPV4_DST_MASK', 'linux/pkt_cls.h', + 'TCA_FLOWER_KEY_ENC_IPV4_DST_MASK' ], + [ 'HAVE_TCA_FLOWER_KEY_ENC_IPV6_SRC', 'linux/pkt_cls.h', + 'TCA_FLOWER_KEY_ENC_IPV6_SRC' ], + [ 'HAVE_TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK', 'linux/pkt_cls.h', + 'TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK' ], + [ 'HAVE_TCA_FLOWER_KEY_ENC_IPV6_DST', 'linux/pkt_cls.h', + 'TCA_FLOWER_KEY_ENC_IPV6_DST' ], + [ 'HAVE_TCA_FLOWER_KEY_ENC_IPV6_DST_MASK', 'linux/pkt_cls.h', + 'TCA_FLOWER_KEY_ENC_IPV6_DST_MASK' ], + [ 'HAVE_TCA_FLOWER_KEY_ENC_UDP_SRC_PORT', 'linux/pkt_cls.h', + 'TCA_FLOWER_KEY_ENC_UDP_SRC_PORT' ], + [ 'HAVE_TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK', 'linux/pkt_cls.h', + 'TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK' ], + [ 'HAVE_TCA_FLOWER_KEY_ENC_UDP_DST_PORT', 'linux/pkt_cls.h', + 'TCA_FLOWER_KEY_ENC_UDP_DST_PORT' ], + [ 'HAVE_TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK', 'linux/pkt_cls.h', + 'TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK' ], + [ 'HAVE_TC_ACT_TUNNEL_KEY', 'linux/tc_act/tc_tunnel_key.h', + 'TCA_ACT_TUNNEL_KEY' ], + [ 'HAVE_TCA_TUNNEL_KEY_ENC_DST_PORT', 'linux/tc_act/tc_tunnel_key.h', + 'TCA_TUNNEL_KEY_ENC_DST_PORT' ], [ 'HAVE_TC_ACT_PEDIT', 'linux/tc_act/tc_pedit.h', 'TCA_PEDIT_KEY_EX_HDR_TYPE_UDP' ], [ 'HAVE_RDMA_NL_NLDEV', 'rdma/rdma_netlink.h', diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index 840d645..b838ab0 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -85,6 +85,8 @@ #define MLX5_FLOW_ACTION_SET_TP_SRC (1u << 15) #define MLX5_FLOW_ACTION_SET_TP_DST (1u << 16) #define MLX5_FLOW_ACTION_JUMP (1u << 17) +#define MLX5_ACTION_VXLAN_ENCAP (1u << 11) +#define MLX5_ACTION_VXLAN_DECAP (1u << 12) #define MLX5_FLOW_FATE_ACTIONS \ (MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS) @@ -182,8 +184,17 @@ struct mlx5_flow_dv { struct mlx5_flow_tcf { struct nlmsghdr *nlh; struct tcmsg *tcm; + uint32_t nlsize; /**< Size of NL message buffer. */ + uint32_t applied:1; /**< Whether rule is currently applied. */ + uint64_t item_flags; /**< Item flags. */ + uint64_t action_flags; /**< Action flags. */ uint64_t hits; uint64_t bytes; + union { /**< Tunnel encap/decap descriptor. */ + struct mlx5_flow_tcf_tunnel_hdr *tunnel; + struct mlx5_flow_tcf_vxlan_decap *vxlan_decap; + struct mlx5_flow_tcf_vxlan_encap *vxlan_encap; + }; }; /* Verbs specification header. */ diff --git a/drivers/net/mlx5/mlx5_flow_tcf.c b/drivers/net/mlx5/mlx5_flow_tcf.c index 5c46f35..8f9c78a 100644 --- a/drivers/net/mlx5/mlx5_flow_tcf.c +++ b/drivers/net/mlx5/mlx5_flow_tcf.c @@ -54,6 +54,37 @@ struct tc_vlan { #endif /* HAVE_TC_ACT_VLAN */ +#ifdef HAVE_TC_ACT_TUNNEL_KEY + +#include + +#ifndef HAVE_TCA_TUNNEL_KEY_ENC_DST_PORT +#define TCA_TUNNEL_KEY_ENC_DST_PORT 9 +#endif + +#else /* HAVE_TC_ACT_TUNNEL_KEY */ + +#define TCA_ACT_TUNNEL_KEY 17 +#define TCA_TUNNEL_KEY_ACT_SET 1 +#define TCA_TUNNEL_KEY_ACT_RELEASE 2 +#define TCA_TUNNEL_KEY_PARMS 2 +#define TCA_TUNNEL_KEY_ENC_IPV4_SRC 3 +#define TCA_TUNNEL_KEY_ENC_IPV4_DST 4 +#define TCA_TUNNEL_KEY_ENC_IPV6_SRC 5 +#define TCA_TUNNEL_KEY_ENC_IPV6_DST 6 +#define TCA_TUNNEL_KEY_ENC_KEY_ID 7 +#define TCA_TUNNEL_KEY_ENC_DST_PORT 9 +#define TCA_TUNNEL_KEY_NO_CSUM 10 + +struct tc_tunnel_key { + tc_gen; + int t_action; +}; + +#endif /* HAVE_TC_ACT_TUNNEL_KEY */ + + + #ifdef HAVE_TC_ACT_PEDIT #include @@ -210,6 +241,45 @@ struct tc_pedit_sel { #ifndef HAVE_TCA_FLOWER_KEY_VLAN_ETH_TYPE #define TCA_FLOWER_KEY_VLAN_ETH_TYPE 25 #endif +#ifndef HAVE_TCA_FLOWER_KEY_ENC_KEY_ID +#define TCA_FLOWER_KEY_ENC_KEY_ID 26 +#endif +#ifndef HAVE_TCA_FLOWER_KEY_ENC_IPV4_SRC +#define TCA_FLOWER_KEY_ENC_IPV4_SRC 27 +#endif +#ifndef HAVE_TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK +#define TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK 28 +#endif +#ifndef HAVE_TCA_FLOWER_KEY_ENC_IPV4_DST +#define TCA_FLOWER_KEY_ENC_IPV4_DST 29 +#endif +#ifndef HAVE_TCA_FLOWER_KEY_ENC_IPV4_DST_MASK +#define TCA_FLOWER_KEY_ENC_IPV4_DST_MASK 30 +#endif +#ifndef HAVE_TCA_FLOWER_KEY_ENC_IPV6_SRC +#define TCA_FLOWER_KEY_ENC_IPV6_SRC 31 +#endif +#ifndef HAVE_TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK +#define TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK 32 +#endif +#ifndef HAVE_TCA_FLOWER_KEY_ENC_IPV6_DST +#define TCA_FLOWER_KEY_ENC_IPV6_DST 33 +#endif +#ifndef HAVE_TCA_FLOWER_KEY_ENC_IPV6_DST_MASK +#define TCA_FLOWER_KEY_ENC_IPV6_DST_MASK 34 +#endif +#ifndef HAVE_TCA_FLOWER_KEY_ENC_UDP_SRC_PORT +#define TCA_FLOWER_KEY_ENC_UDP_SRC_PORT 43 +#endif +#ifndef HAVE_TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK +#define TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK 44 +#endif +#ifndef HAVE_TCA_FLOWER_KEY_ENC_UDP_DST_PORT +#define TCA_FLOWER_KEY_ENC_UDP_DST_PORT 45 +#endif +#ifndef HAVE_TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK +#define TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK 46 +#endif #ifndef HAVE_TCA_FLOWER_KEY_TCP_FLAGS #define TCA_FLOWER_KEY_TCP_FLAGS 71 #endif @@ -232,6 +302,111 @@ struct tc_pedit_sel { #define TP_PORT_LEN 2 /* Transport Port (UDP/TCP) Length */ #endif +#define MLX5_VXLAN_PORT_RANGE_MIN 30000 +#define MLX5_VXLAN_PORT_RANGE_MAX 60000 +#define MLX5_VXLAN_DEVICE_PFX "vmlx_" + +/** Tunnel action type, used for @p type in header structure. */ +enum mlx5_flow_tcf_tunact_type { + MLX5_FLOW_TCF_TUNACT_VXLAN_ENCAP, + MLX5_FLOW_TCF_TUNACT_VXLAN_DECAP, +}; + +/** Flags used for @p mask in tunnel action encap descriptors. */ +#define MLX5_FLOW_TCF_ENCAP_ETH_SRC (1u << 0) +#define MLX5_FLOW_TCF_ENCAP_ETH_DST (1u << 1) +#define MLX5_FLOW_TCF_ENCAP_IPV4_SRC (1u << 2) +#define MLX5_FLOW_TCF_ENCAP_IPV4_DST (1u << 3) +#define MLX5_FLOW_TCF_ENCAP_IPV6_SRC (1u << 4) +#define MLX5_FLOW_TCF_ENCAP_IPV6_DST (1u << 5) +#define MLX5_FLOW_TCF_ENCAP_UDP_SRC (1u << 6) +#define MLX5_FLOW_TCF_ENCAP_UDP_DST (1u << 7) +#define MLX5_FLOW_TCF_ENCAP_VXLAN_VNI (1u << 8) + +/** Neigh rule structure */ +struct tcf_neigh_rule { + LIST_ENTRY(tcf_neigh_rule) next; + uint32_t refcnt; + struct ether_addr eth; + uint16_t mask; + union { + struct { + rte_be32_t dst; + } ipv4; + struct { + uint8_t dst[16]; + } ipv6; + }; +}; + +/** Local rule structure */ +struct tcf_local_rule { + LIST_ENTRY(tcf_neigh_rule) next; + uint32_t refcnt; + uint16_t mask; + union { + struct { + rte_be32_t dst; + rte_be32_t src; + } ipv4; + struct { + uint8_t dst[16]; + uint8_t src[16]; + } ipv6; + }; +}; + +/** VXLAN virtual netdev. */ +struct mlx5_flow_tcf_vtep { + LIST_ENTRY(mlx5_flow_tcf_vtep) next; + LIST_HEAD(, tcf_neigh_rule) neigh; + LIST_HEAD(, tcf_local_rule) local; + uint32_t refcnt; + unsigned int ifindex; /**< Own interface index. */ + unsigned int ifouter; /**< Index of device attached to. */ + uint16_t port; + uint8_t created; +}; + +/** Tunnel descriptor header, common for all tunnel types. */ +struct mlx5_flow_tcf_tunnel_hdr { + uint32_t type; /**< Tunnel action type. */ + unsigned int ifindex_tun; /**< Tunnel endpoint interface. */ + unsigned int ifindex_org; /**< Original dst/src interface */ + unsigned int *ifindex_ptr; /**< Interface ptr in message. */ +}; + +struct mlx5_flow_tcf_vxlan_decap { + struct mlx5_flow_tcf_tunnel_hdr hdr; + uint16_t udp_port; +}; + +struct mlx5_flow_tcf_vxlan_encap { + struct mlx5_flow_tcf_tunnel_hdr hdr; + uint32_t mask; + struct { + struct ether_addr dst; + struct ether_addr src; + } eth; + union { + struct { + rte_be32_t dst; + rte_be32_t src; + } ipv4; + struct { + uint8_t dst[16]; + uint8_t src[16]; + } ipv6; + }; +struct { + rte_be16_t src; + rte_be16_t dst; + } udp; + struct { + uint8_t vni[3]; + } vxlan; +}; + /** * Structure for holding netlink context. * Note the size of the message buffer which is MNL_SOCKET_BUFFER_SIZE. From patchwork Mon Oct 15 14:13:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slava Ovsiienko X-Patchwork-Id: 46849 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 9E57432A5; Mon, 15 Oct 2018 16:14:21 +0200 (CEST) Received: from EUR03-AM5-obe.outbound.protection.outlook.com (mail-eopbgr30059.outbound.protection.outlook.com [40.107.3.59]) by dpdk.org (Postfix) with ESMTP id 0F0322BD3 for ; Mon, 15 Oct 2018 16:14:12 +0200 (CEST) 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=fo+FW9rHnbNYZ3SmvkDAdw2gT2ilnn7Tfq14v6F4grA=; b=PJaivglL11gcUpVuaXEJUp5/XcD21BfeXRikt8VzHit7zd6GBF2Se0Qmb5TfBGOEsuTsJBR0pzV95Kg2w2c5Yjpx97SPf+DcD/AfNwCrCYXIiAKgPlhsXG0zRQ+GRYkXcnHq/NIxJNGpziEvB0PCSXOdClM948kpHIq+bla048U= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=viacheslavo@mellanox.com; Received: from mellanox.com (37.142.13.130) by VI1PR05MB3277.eurprd05.prod.outlook.com (2603:10a6:802:1c::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1228.24; Mon, 15 Oct 2018 14:14:10 +0000 From: Viacheslav Ovsiienko To: shahafs@mellanox.com, yskoh@mellanox.com Cc: dev@dpdk.org, Viacheslav Ovsiienko Date: Mon, 15 Oct 2018 14:13:30 +0000 Message-Id: <1539612815-47199-3-git-send-email-viacheslavo@mellanox.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1539612815-47199-1-git-send-email-viacheslavo@mellanox.com> References: <1538461807-37507-1-git-send-email-viacheslavo@mellanox.com> <1539612815-47199-1-git-send-email-viacheslavo@mellanox.com> MIME-Version: 1.0 X-Originating-IP: [37.142.13.130] X-ClientProxiedBy: CWLP265CA0084.GBRP265.PROD.OUTLOOK.COM (2603:10a6:401:50::24) To VI1PR05MB3277.eurprd05.prod.outlook.com (2603:10a6:802:1c::22) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 9ce0e8ad-b668-49b2-ae38-08d632a87a5f 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:VI1PR05MB3277; X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 3:w0PD4lLYakyqLcNzlL9f6Sl+09GsIQ6f2oGPQWTOYnIGKaCBB525VJBRLjU+eyKUVwBrZFMHoJ82bKaxb3w3G6ASDeSMuu4uT1Xk0aFb2yfmp4LisEjO44nVh0Vr1IH1W4QVXUva6kj8IOWeWQ1NI5iZUtCSHZgXTJKyMeraMyhzkcT0hvVtRvJoqEj4+P1PKyc6NyAza3GRtmgp90sqb1UPLPf3WQJU7DwVo3SMAFr9gAMX2bRTVr/nLND8KgSN; 25:ILbo0hjvzOVbOOvd881Grt912UjrkGq29j+vpojZM5IfkHcqO08nVSVfMPfhXqs6v2Wr5zeZ4MQWUF0pIfzMoi4LuU/oG1JmwZSfoQNpvXh0S4rOpR4io3UwwUjdLmQZnZBrboKk+nfZDzuI/zZLrhCgV52kawE/laJhpuWns6td7ScNm4yeGVYAs/oCCOzzGrunQQrMRNihgf90Z++FF32AHoMDtwBe4hc4Z0QP3JSglMiMjRz/j4klkNwOkMGVwJOuviTENOivmE8blS+OuG53YcjEu76R1/RL13nUyXqBzxOGZVsmHy5mnraBlAQfcwmy7PUccmcTL5VKnyXqlA==; 31:laL/IfjXjZNsEEPMeLmUWNQMuU3RAGJMEBVchgBGfT41s6Mv0yD6axrwPC17zXjE+CBpL7N/TvNzRrnScJDA+MeqFJ6Lm6jI9/cPQBo+YNCuHVz16oZmJ2UYqSumPylujYc3FqHNX72bf92zgrZEiGtT0xCHU10eTy/ABE+bPlQAx2VOZ77fygwZ4NiqbyJ6W+qBLpiCtaE8RJS0KmHS5FGWiV7c5Id9ZWEXe2Es4Hw= X-MS-TrafficTypeDiagnostic: VI1PR05MB3277: X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 20:D9RPHMTBtkfz0OojFDBQgxyRjRaiVz8WfD6fdW8CAQYk4hUD++BTCJJQVclm2WiHA4zWywetsJ8nJOAdRpYorkeP8q47FAbKD2HNpjUFdLZTwz4M4YFmc91WtMT2CdIAEGRXcgtjdUWrjTIfo5MKUEj4oqVkjuIhJxO/bsSCVwvsTXQ9OW6hiP1G19pTsnrcFZBgVepe9wM+RQ0G18sbjkl7D1o8+EgyNPVGHriHrAqaxq+CG34NPi+Vl5engodTQHmx3+P9JOU7RH62yObfOh1nIZFK249g6h83egYTkTkoNX/DcJj3Ftbq0STU6E7TkP9Uv9qh28ek1KEUydoIOJEt8EkWIvyuG2wjgkFAq6sxBLRId4u6DpA+ZTcEPaUYn0eq6KARNHMt0UdtUUF9RofRWxtkQHB056OqQFoROTZyRgevzYmDWojBzpkSGUQ91cikNOc1ZvEvPCmLNINJUk5XoGrt9qEoI7GlgHj5iBMJtf4OmKGm9h/qJmFS3IwQ; 4:ORNrw5KdJ+xFotlO+Rk4skXpIFBwnxHFrdrnGnOygt0C4GP+7lUcWMOeLZ4TEBYqK5OwL2FdtC4WUck88nNNp0hlcFSKgF3NrToRgXkq0nF2QaN+2YFQYoOQ5XDImCFw+H45F5fR+ss8WQZsMyktMmyyvDeg8k09EXW/jFjNdTphUgaeFz6Lw5Ch/KJMay8+7O9Joy4j8oHt7hni/1GTWY3FaAOwxbjLatcHZ3dwM4kcjXOWJFxdRcfzNiTzknYYfhp42MewmIcW0Xvf/VSjTw== 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)(3002001)(3231355)(944501410)(52105095)(10201501046)(93006095)(93001095)(6055026)(149066)(150057)(6041310)(20161123560045)(20161123558120)(20161123562045)(20161123564045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(201708071742011)(7699051); SRVR:VI1PR05MB3277; BCL:0; PCL:0; RULEID:; SRVR:VI1PR05MB3277; X-Forefront-PRVS: 0826B2F01B X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(136003)(39860400002)(376002)(346002)(366004)(396003)(199004)(189003)(107886003)(16526019)(66066001)(7736002)(8676002)(47776003)(106356001)(51416003)(7696005)(52116002)(25786009)(68736007)(105586002)(186003)(16586007)(305945005)(8936002)(3846002)(81166006)(81156014)(6116002)(386003)(50226002)(6666004)(50466002)(11346002)(86362001)(14444005)(446003)(76176011)(97736004)(6636002)(21086003)(36756003)(2906002)(33026002)(4720700003)(69596002)(53936002)(55016002)(48376002)(85306007)(478600001)(476003)(8886007)(316002)(26005)(4326008)(4744004)(486006)(2616005)(5660300001)(956004); DIR:OUT; SFP:1101; SCL:1; SRVR:VI1PR05MB3277; H:mellanox.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-Exchange-Diagnostics: =?us-ascii?Q?1; VI1PR05MB3277; 23:A9Qc/7x/bqO4Uzd8NWlw1VPw2sPzIiKyXYr2QHUSU?= YHRZhUTI7ixslk+/fhH3whpxgfnCugdes8hESkQtZ1npriI6vUTkTTc4jgPkvC7QHoBbo+HDM5H4LVFIfDvM6bGuJVxHSi6E9lOeqCW2Cq87Zf7iUoQdqAepD3O9V6NckC1ojXkb98LT6X4oX4CiFBz2SrLJcjIwZUq/kEgoZWEW62uWdLsalCQiUAW6I2Q6dxp+L9CUNmfsDxb59mmz8DcFhevtOkS4SmEfEHkCFceS1rf/ZfeVMGvSLwXoUghJuGxYoMP2kXwXlSTSHCFv7jZa9kMEpayJdXhKXDxzMPASG5DO9PSi6pd1awE30E1f/5Obj9WgFWKgScsWe9Cx+yxRWEw0tfYmkqTSCOj9gyzkWUjZ0sh2bkhFrwupjyUfTjrJKiBsJUg0jMox1A/s6pe7E09ODI0SIoaVSzXAdZ2zi7rUL28qxljLbCCAxkn/xC02CHBwAmqaddC6b1rxLijS6IbySrCKo1xlTB8cHVrPgB51CNkMqIDMu9P/pP0wqFcSKcXFYMolnP2MfBZXeQinSo0ynp4ZEgChRUNzQcN0HFm97XKMHWCc+haqZvJw27ryJ066jzhj/wenHTvJnAyl/8LdZHwgVuHAyrZhXw09qLzdwpxlIHDO8yJpa7utc1EWQHxRXttTuAKYwyEacM890erWw2chLXoxNSLZ5iT+PEo5KwkUWtw8uxofTuBwBdgIwrkg7aYM+108c6yC/7ifU8I+S3p6Y5c1KC4Ha3ZQPZr/ecxoqEre1SNorEC0kyxN1liYXi5AywQOXH3Drvdva90BO3YrOosifOKaEr00eOoTTWk2TT/oS6gMmh2Gv9cFIhNemnPcyFHLt7EvBJggMw6yRPJBmiYA0QcRd1Nm89fgWRe9uGlp9NayJ+janlnHP5ocZMJLcfKSjinVv/cqjWEPlW+fashx5f0mXsyqU50GgwQNnv7rsOYIpMBXb9ABow98fnj+Dsy1YUXkOuawA3h/wpKju7sHD2L4T+UKhTISAcoyryiS/74APEY8GwVaOlRf4ltowfVy2xKiGGPj0obbH5UeR9wV8JBDxtKNzKQdONm1NAd0m8gvDRdjR7gv8nxi007CFa0Tmgl64jQ7XRhN2TJc/VzRpkRXL/KHOlMFahPH3sFgrm2qlBgPUXugnzKgchq2ZdJT89kh2UKDycDQE4oJc6msnt/iZwKZ4ewZ2Et/092t6VheiwXmpHVIl7OSuv+PD9+Xb+YARfVnmyC6RvuoKFKfOh6I2HSpVycRjFtlajzSGJNklEvxL3sgd4MG4cGIF3k+q4zDAsF X-Microsoft-Antispam-Message-Info: NOi0jWiM90xgrYRa9Vqr55HrF2W+1lj+pIPEvtKJPsen6G4nZsU5N+CgAe0Dw1oWjVhb5O7xIqO5dzdNyObF0W1Orso37kZg86yALX0w18ruSRqwR5gtREarTH0v4HBAKpJ8KWmgkAbVhPC1F1e5/a/423Qg2r9kyZ8ylYoiFsAzNQOQZX4O9psWOt7ccUE7jkhoZIc7ISr4b9PvW22xWOnd6g8QEXAax5NTp4mKqnS6zOF6QzFvIkMRNsyaX/387Oz2wbszbAOIZ2jkT/+v3zlK1rvWOndQoYV/7H6FfUp6KM8simgCnS+N9mjpmkFwptVc7AA1WcycSTB2RTStW/UljMc97TnBxhWoUjpu/kY= X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 6:XTalhnb5B367xfnDLaXZOVg5QaGr/J3UOLzCi/fvKbKQcVAN0kcBYoM5H6BZl0u9qf7aTcNAECMLTS/9iG7NmaAtR0UAkY2PFlTUsYbshkwGRhFrXNPO9NePTlWjtFY7rbxPK1ZWVfOUjDCuhj73c3WlzbxAMuddPNLWg4zh4ZFjPhla76kVW1tl94LeSY2EHarbQWILlPGnU1HiFuCErHMuDn9pkQFQpo+cXJ1e1CB4IGHUrlmtUmXGmRq9//uMv2eGnmpoxyTk03/GurBQebIC6al3+KTYb0MYGs2UgCGrJPemEIVyWcGVC/03AMbEM7U9HMlJ3iRyIvku0G7orzZwxWlyGJeMxH5ixBoc3NrzqJTNxoLHp5BL/tnov7bRJJhY3jPz9nIm1u2fWJ0Eqc8yAmch5EbqOeHfSpgqoCLhzeA8KoMyuU0B0bVECKG2yYsqTQ0NgrI2tKNF93CYrA==; 5:N1XwxZ8+P1/djqWjysqJ94qGCmW/2Fm6eVwjF+594rkGENUv0DFQg4FLHtDmuOaELonNh/8DzXc+gmmZ8LbUoKZVRU5joxtd0X2qAKdf7AtcWOw9xx7tqUXQQEdchRCIf4BUzNv+azsagiefyrErggRN8tRtGzeAuVQCk+14GpY=; 7:R9N3YGuKOnEMQGMW/LTQD3xc4BvTKNKTj9S/s3Xcxjf36N7XWafIyz9kKZO2KCX7UOrXU2V5j7SgS0MBfmjzaP+3tS4UY0bs583EsRKCr2INI9YzEgm2oZkzBeZEGWhjGhFW91OQGdgHKS2zYhxtJMbKVkxCPizkxGwR1mMm9tK/Ncrsy6JMO3qJalCNNqaDkfNTY3uOdzeiovZNUNIBYF8nL3md7WHSD26keBo/B1XLVYVuqfiCGwJv2yQxjcJx SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Oct 2018 14:14:10.2082 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 9ce0e8ad-b668-49b2-ae38-08d632a87a5f X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR05MB3277 Subject: [dpdk-dev] [PATCH v2 2/7] net/mlx5: e-switch VXLAN flow validation routine 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" This part of patchset adds support for flow item/action lists validation. The following entities are now supported: - RTE_FLOW_ITEM_TYPE_VXLAN, contains the tunnel VNI - RTE_FLOW_ACTION_TYPE_VXLAN_DECAP, if this action is specified the items in the flow items list treated as outer network parameters for tunnel outer header match. The ethernet layer addresses always are treated as inner ones. - RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP, contains the item list to build the encapsulation header. In current implementation the values is the subject for some constraints: - outer source MAC address will be always unconditionally set to the one of MAC addresses of outer egress interface - no way to specify source UDP port - all abovementioned parameters are ignored if specified in the rule, warning messages are sent to the log Suggested-by: Adrien Mazarguil Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_flow_tcf.c | 711 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 705 insertions(+), 6 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_tcf.c b/drivers/net/mlx5/mlx5_flow_tcf.c index 8f9c78a..0055417 100644 --- a/drivers/net/mlx5/mlx5_flow_tcf.c +++ b/drivers/net/mlx5/mlx5_flow_tcf.c @@ -430,6 +430,7 @@ struct mlx5_flow_tcf_context { struct rte_flow_item_ipv6 ipv6; struct rte_flow_item_tcp tcp; struct rte_flow_item_udp udp; + struct rte_flow_item_vxlan vxlan; } flow_tcf_mask_empty; /** Supported masks for known item types. */ @@ -441,6 +442,7 @@ struct mlx5_flow_tcf_context { struct rte_flow_item_ipv6 ipv6; struct rte_flow_item_tcp tcp; struct rte_flow_item_udp udp; + struct rte_flow_item_vxlan vxlan; } flow_tcf_mask_supported = { .port_id = { .id = 0xffffffff, @@ -478,6 +480,9 @@ struct mlx5_flow_tcf_context { .src_port = RTE_BE16(0xffff), .dst_port = RTE_BE16(0xffff), }, + .vxlan = { + .vni = "\xff\xff\xff", + }, }; #define SZ_NLATTR_HDR MNL_ALIGN(sizeof(struct nlattr)) @@ -943,6 +948,615 @@ struct pedit_parser { } /** + * Validate VXLAN_ENCAP action RTE_FLOW_ITEM_TYPE_ETH item for E-Switch. + * + * @param[in] item + * Pointer to the itemn structure. + * @param[out] error + * Pointer to the error structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + **/ +static int +flow_tcf_validate_vxlan_encap_eth(const struct rte_flow_item *item, + struct rte_flow_error *error) +{ + const struct rte_flow_item_eth *spec = item->spec; + const struct rte_flow_item_eth *mask = item->mask; + + if (!spec) + /* + * Specification for L2 addresses can be empty + * because these ones are optional and not + * required directly by tc rule. + */ + return 0; + if (!mask) + /* If mask is not specified use the default one. */ + mask = &rte_flow_item_eth_mask; + if (memcmp(&mask->dst, + &flow_tcf_mask_empty.eth.dst, + sizeof(flow_tcf_mask_empty.eth.dst))) { + if (memcmp(&mask->dst, + &rte_flow_item_eth_mask.dst, + sizeof(rte_flow_item_eth_mask.dst))) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, + "no support for partial mask on" + " \"eth.dst\" field"); + } + if (memcmp(&mask->src, + &flow_tcf_mask_empty.eth.src, + sizeof(flow_tcf_mask_empty.eth.src))) { + if (memcmp(&mask->src, + &rte_flow_item_eth_mask.src, + sizeof(rte_flow_item_eth_mask.src))) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, + "no support for partial mask on" + " \"eth.src\" field"); + } + if (mask->type != RTE_BE16(0x0000)) { + if (mask->type != RTE_BE16(0xffff)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, + "no support for partial mask on" + " \"eth.type\" field"); + DRV_LOG(WARNING, + "outer ethernet type field " + "cannot be forced for VXLAN " + "encapsulation, parameter ignored"); + } + return 0; +} + +/** + * Validate VXLAN_ENCAP action RTE_FLOW_ITEM_TYPE_IPV4 item for E-Switch. + * + * @param[in] item + * Pointer to the itemn structure. + * @param[out] error + * Pointer to the error structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + **/ +static int +flow_tcf_validate_vxlan_encap_ipv4(const struct rte_flow_item *item, + struct rte_flow_error *error) +{ + const struct rte_flow_item_ipv4 *spec = item->spec; + const struct rte_flow_item_ipv4 *mask = item->mask; + + if (!spec) + /* + * Specification for L3 addresses cannot be empty + * because it is required by tunnel_key parameter. + */ + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "NULL outer L3 address specification " + " for VXLAN encapsulation"); + if (!mask) + mask = &rte_flow_item_ipv4_mask; + if (mask->hdr.dst_addr != RTE_BE32(0x00000000)) { + if (mask->hdr.dst_addr != RTE_BE32(0xffffffff)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, + "no support for partial mask on" + " \"ipv4.hdr.dst_addr\" field"); + /* More L3 address validations can be put here. */ + } else { + /* + * Kernel uses the destination L3 address to determine + * the routing path and obtain the L2 destination + * address, so L3 destination address must be + * specified in the tc rule. + */ + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "outer L3 destination address must be " + "specified for VXLAN encapsulation"); + } + if (mask->hdr.src_addr != RTE_BE32(0x00000000)) { + if (mask->hdr.src_addr != RTE_BE32(0xffffffff)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, + "no support for partial mask on" + " \"ipv4.hdr.src_addr\" field"); + /* More L3 address validations can be put here. */ + } else { + /* + * Kernel uses the source L3 address to select the + * interface for egress encapsulated traffic, so + * it must be specified in the tc rule. + */ + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "outer L3 source address must be " + "specified for VXLAN encapsulation"); + } + return 0; +} + +/** + * Validate VXLAN_ENCAP action RTE_FLOW_ITEM_TYPE_IPV6 item for E-Switch. + * + * @param[in] item + * Pointer to the itemn structure. + * @param[out] error + * Pointer to the error structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_ernno is set. + **/ +static int +flow_tcf_validate_vxlan_encap_ipv6(const struct rte_flow_item *item, + struct rte_flow_error *error) +{ + const struct rte_flow_item_ipv6 *spec = item->spec; + const struct rte_flow_item_ipv6 *mask = item->mask; + + if (!spec) + /* + * Specification for L3 addresses cannot be empty + * because it is required by tunnel_key parameter. + */ + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "NULL outer L3 address specification " + " for VXLAN encapsulation"); + if (!mask) + mask = &rte_flow_item_ipv6_mask; + if (memcmp(&mask->hdr.dst_addr, + &flow_tcf_mask_empty.ipv6.hdr.dst_addr, + sizeof(flow_tcf_mask_empty.ipv6.hdr.dst_addr))) { + if (memcmp(&mask->hdr.dst_addr, + &rte_flow_item_ipv6_mask.hdr.dst_addr, + sizeof(rte_flow_item_ipv6_mask.hdr.dst_addr))) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, + "no support for partial mask on" + " \"ipv6.hdr.dst_addr\" field"); + /* More L3 address validations can be put here. */ + } else { + /* + * Kernel uses the destination L3 address to determine + * the routing path and obtain the L2 destination + * address (heigh or gate), so L3 destination address + * must be specified within the tc rule. + */ + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "outer L3 destination address must be " + "specified for VXLAN encapsulation"); + } + if (memcmp(&mask->hdr.src_addr, + &flow_tcf_mask_empty.ipv6.hdr.src_addr, + sizeof(flow_tcf_mask_empty.ipv6.hdr.src_addr))) { + if (memcmp(&mask->hdr.src_addr, + &rte_flow_item_ipv6_mask.hdr.src_addr, + sizeof(rte_flow_item_ipv6_mask.hdr.src_addr))) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, + "no support for partial mask on" + " \"ipv6.hdr.src_addr\" field"); + /* More L3 address validation can be put here. */ + } else { + /* + * Kernel uses the source L3 address to select the + * interface for egress encapsulated traffic, so + * it must be specified in the tc rule. + */ + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "outer L3 source address must be " + "specified for VXLAN encapsulation"); + } + return 0; +} + +/** + * Validate VXLAN_ENCAP action RTE_FLOW_ITEM_TYPE_UDP item for E-Switch. + * + * @param[in] item + * Pointer to the itemn structure. + * @param[out] error + * Pointer to the error structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_ernno is set. + **/ +static int +flow_tcf_validate_vxlan_encap_udp(const struct rte_flow_item *item, + struct rte_flow_error *error) +{ + const struct rte_flow_item_udp *spec = item->spec; + const struct rte_flow_item_udp *mask = item->mask; + + if (!spec) + /* + * Specification for UDP ports cannot be empty + * because it is required by tunnel_key parameter. + */ + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "NULL UDP port specification " + " for VXLAN encapsulation"); + if (!mask) + mask = &rte_flow_item_udp_mask; + if (mask->hdr.dst_port != RTE_BE16(0x0000)) { + if (mask->hdr.dst_port != RTE_BE16(0xffff)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, + "no support for partial mask on" + " \"udp.hdr.dst_port\" field"); + if (!spec->hdr.dst_port) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "zero encap remote UDP port"); + } else { + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "outer UDP remote port must be " + "specified for VXLAN encapsulation"); + } + if (mask->hdr.src_port != RTE_BE16(0x0000)) { + if (mask->hdr.src_port != RTE_BE16(0xffff)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, + "no support for partial mask on" + " \"udp.hdr.src_port\" field"); + DRV_LOG(WARNING, + "outer UDP source port cannot be " + "forced for VXLAN encapsulation, " + "parameter ignored"); + } + return 0; +} + +/** + * Validate VXLAN_ENCAP action RTE_FLOW_ITEM_TYPE_VXLAN item for E-Switch. + * + * @param[in] item + * Pointer to the itemn structure. + * @param[out] error + * Pointer to the error structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_ernno is set. + **/ +static int +flow_tcf_validate_vxlan_encap_vni(const struct rte_flow_item *item, + struct rte_flow_error *error) +{ + const struct rte_flow_item_vxlan *spec = item->spec; + const struct rte_flow_item_vxlan *mask = item->mask; + + if (!spec) + /* Outer VNI is required by tunnel_key parameter. */ + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "NULL VNI specification " + " for VXLAN encapsulation"); + if (!mask) + mask = &rte_flow_item_vxlan_mask; + if (mask->vni[0] != 0 || + mask->vni[1] != 0 || + mask->vni[2] != 0) { + if (mask->vni[0] != 0xff || + mask->vni[1] != 0xff || + mask->vni[2] != 0xff) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, + "no support for partial mask on" + " \"vxlan.vni\" field"); + if (spec->vni[0] == 0 && + spec->vni[1] == 0 && + spec->vni[2] == 0) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "VXLAN vni cannot be 0"); + } else { + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "outer VNI must be specified " + "for VXLAN encapsulation"); + } + return 0; +} + +/** + * Validate VXLAN_ENCAP action item list for E-Switch. + * + * @param[in] action + * Pointer to the VXLAN_ENCAP action structure. + * @param[out] error + * Pointer to the error structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_ernno is set. + **/ +static int +flow_tcf_validate_vxlan_encap(const struct rte_flow_action *action, + struct rte_flow_error *error) +{ + const struct rte_flow_item *items; + int ret; + uint32_t item_flags = 0; + + assert(action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP); + if (!action->conf) + return rte_flow_error_set + (error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, + action, "Missing VXLAN tunnel " + "action configuration"); + items = ((const struct rte_flow_action_vxlan_encap *) + action->conf)->definition; + if (!items) + return rte_flow_error_set + (error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, + action, "Missing VXLAN tunnel " + "encapsulation parameters"); + 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: + ret = mlx5_flow_validate_item_eth(items, item_flags, + error); + if (ret < 0) + return ret; + ret = flow_tcf_validate_vxlan_encap_eth(items, error); + if (ret < 0) + return ret; + item_flags |= MLX5_FLOW_LAYER_OUTER_L2; + break; + break; + case RTE_FLOW_ITEM_TYPE_IPV4: + ret = mlx5_flow_validate_item_ipv4(items, item_flags, + error); + if (ret < 0) + return ret; + ret = flow_tcf_validate_vxlan_encap_ipv4(items, error); + if (ret < 0) + return ret; + item_flags |= MLX5_FLOW_LAYER_OUTER_L3_IPV4; + break; + case RTE_FLOW_ITEM_TYPE_IPV6: + ret = mlx5_flow_validate_item_ipv6(items, item_flags, + error); + if (ret < 0) + return ret; + ret = flow_tcf_validate_vxlan_encap_ipv6(items, error); + if (ret < 0) + return ret; + item_flags |= MLX5_FLOW_LAYER_OUTER_L3_IPV6; + break; + case RTE_FLOW_ITEM_TYPE_UDP: + ret = mlx5_flow_validate_item_udp(items, item_flags, + 0xFF, error); + if (ret < 0) + return ret; + ret = flow_tcf_validate_vxlan_encap_udp(items, error); + if (ret < 0) + return ret; + item_flags |= MLX5_FLOW_LAYER_OUTER_L4_UDP; + break; + case RTE_FLOW_ITEM_TYPE_VXLAN: + ret = mlx5_flow_validate_item_vxlan(items, + item_flags, error); + if (ret < 0) + return ret; + ret = flow_tcf_validate_vxlan_encap_vni(items, error); + if (ret < 0) + return ret; + item_flags |= MLX5_FLOW_LAYER_VXLAN; + break; + default: + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM, items, + "VXLAN encap item not supported"); + } + } + if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L3)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "no outer L3 layer found" + " for VXLAN encapsulation"); + if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "no outer L4 layer found" + " for VXLAN encapsulation"); + if (!(item_flags & MLX5_FLOW_LAYER_VXLAN)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "no VXLAN VNI found" + " for VXLAN encapsulation"); + return 0; +} + +/** + * Validate VXLAN_DECAP action outer tunnel items for E-Switch. + * + * @param[in] item_flags + * Mask of provided outer tunnel parameters + * @param[in] ipv4 + * Outer IPv4 address item (if any, NULL otherwise). + * @param[in] ipv6 + * Outer IPv6 address item (if any, NULL otherwise). + * @param[in] udp + * Outer UDP layer item (if any, NULL otherwise). + * @param[out] error + * Pointer to the error structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_ernno is set. + **/ +static int +flow_tcf_validate_vxlan_decap(uint32_t item_flags, + const struct rte_flow_action *action, + const struct rte_flow_item *ipv4, + const struct rte_flow_item *ipv6, + const struct rte_flow_item *udp, + struct rte_flow_error *error) +{ + if (!ipv4 && !ipv6) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "no outer L3 layer found" + " for VXLAN decapsulation"); + if (ipv4) { + const struct rte_flow_item_ipv4 *spec = ipv4->spec; + const struct rte_flow_item_ipv4 *mask = ipv4->mask; + + if (!spec) + /* + * Specification for L3 addresses cannot be empty + * because it is required as decap parameter. + */ + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, ipv4, + "NULL outer L3 address specification " + " for VXLAN decapsulation"); + if (!mask) + mask = &rte_flow_item_ipv4_mask; + if (mask->hdr.dst_addr != RTE_BE32(0x00000000)) { + if (mask->hdr.dst_addr != RTE_BE32(0xffffffff)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, + "no support for partial mask on" + " \"ipv4.hdr.dst_addr\" field"); + /* More L3 address validations can be put here. */ + } else { + /* + * Kernel uses the destination L3 address + * to determine the ingress network interface + * for traffic being decapculated. + */ + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, ipv4, + "outer L3 destination address must be " + "specified for VXLAN decapsulation"); + } + /* Source L3 address is optional for decap. */ + if (mask->hdr.src_addr != RTE_BE32(0x00000000)) + if (mask->hdr.src_addr != RTE_BE32(0xffffffff)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, + "no support for partial mask on" + " \"ipv4.hdr.src_addr\" field"); + } else { + const struct rte_flow_item_ipv6 *spec = ipv6->spec; + const struct rte_flow_item_ipv6 *mask = ipv6->mask; + + if (!spec) + /* + * Specification for L3 addresses cannot be empty + * because it is required as decap parameter. + */ + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, ipv6, + "NULL outer L3 address specification " + " for VXLAN decapsulation"); + if (!mask) + mask = &rte_flow_item_ipv6_mask; + if (memcmp(&mask->hdr.dst_addr, + &flow_tcf_mask_empty.ipv6.hdr.dst_addr, + sizeof(flow_tcf_mask_empty.ipv6.hdr.dst_addr))) { + if (memcmp(&mask->hdr.dst_addr, + &rte_flow_item_ipv6_mask.hdr.dst_addr, + sizeof(rte_flow_item_ipv6_mask.hdr.dst_addr))) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, + "no support for partial mask on" + " \"ipv6.hdr.dst_addr\" field"); + /* More L3 address validations can be put here. */ + } else { + /* + * Kernel uses the destination L3 address + * to determine the ingress network interface + * for traffic being decapculated. + */ + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, ipv6, + "outer L3 destination address must be " + "specified for VXLAN decapsulation"); + } + /* Source L3 address is optional for decap. */ + if (memcmp(&mask->hdr.src_addr, + &flow_tcf_mask_empty.ipv6.hdr.src_addr, + sizeof(flow_tcf_mask_empty.ipv6.hdr.src_addr))) { + if (memcmp(&mask->hdr.src_addr, + &rte_flow_item_ipv6_mask.hdr.src_addr, + sizeof(mask->hdr.src_addr))) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, + "no support for partial mask on" + " \"ipv6.hdr.src_addr\" field"); + } + } + if (!udp) { + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "no outer L4 layer found" + " for VXLAN decapsulation"); + } else { + const struct rte_flow_item_udp *spec = udp->spec; + const struct rte_flow_item_udp *mask = udp->mask; + + if (!spec) + /* + * Specification for UDP ports cannot be empty + * because it is required as decap parameter. + */ + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, udp, + "NULL UDP port specification " + " for VXLAN decapsulation"); + if (!mask) + mask = &rte_flow_item_udp_mask; + if (mask->hdr.dst_port != RTE_BE16(0x0000)) { + if (mask->hdr.dst_port != RTE_BE16(0xffff)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, + "no support for partial mask on" + " \"udp.hdr.dst_port\" field"); + if (!spec->hdr.dst_port) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, udp, + "zero decap local UDP port"); + } else { + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, udp, + "outer UDP destination port must be " + "specified for VXLAN decapsulation"); + } + if (mask->hdr.src_port != RTE_BE16(0x0000)) { + if (mask->hdr.src_port != RTE_BE16(0xffff)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, + "no support for partial mask on" + " \"udp.hdr.src_port\" field"); + DRV_LOG(WARNING, + "outer UDP local port cannot be " + "forced for VXLAN encapsulation, " + "parameter ignored"); + } + } + if (!(item_flags & MLX5_FLOW_LAYER_VXLAN)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "no VXLAN VNI found" + " for VXLAN decapsulation"); + /* VNI is already validated, extra check can be put here. */ + return 0; +} + +/** * Validate flow for E-Switch. * * @param[in] priv @@ -974,7 +1588,8 @@ struct pedit_parser { const struct rte_flow_item_ipv6 *ipv6; const struct rte_flow_item_tcp *tcp; const struct rte_flow_item_udp *udp; - } spec, mask; + const struct rte_flow_item_vxlan *vxlan; + } spec, mask; union { const struct rte_flow_action_port_id *port_id; const struct rte_flow_action_jump *jump; @@ -983,9 +1598,13 @@ struct pedit_parser { of_set_vlan_vid; const struct rte_flow_action_of_set_vlan_pcp * of_set_vlan_pcp; + const struct rte_flow_action_vxlan_encap *vxlan_encap; const struct rte_flow_action_set_ipv4 *set_ipv4; const struct rte_flow_action_set_ipv6 *set_ipv6; } conf; + const struct rte_flow_item *ipv4 = NULL; /* storage to check */ + const struct rte_flow_item *ipv6 = NULL; /* outer tunnel. */ + const struct rte_flow_item *udp = NULL; /* parameters. */ uint32_t item_flags = 0; uint32_t action_flags = 0; uint8_t next_protocol = -1; @@ -1114,7 +1733,6 @@ struct pedit_parser { error); if (ret < 0) return ret; - item_flags |= MLX5_FLOW_LAYER_OUTER_L3_IPV4; mask.ipv4 = flow_tcf_item_mask (items, &rte_flow_item_ipv4_mask, &flow_tcf_mask_supported.ipv4, @@ -1135,13 +1753,22 @@ struct pedit_parser { next_protocol = ((const struct rte_flow_item_ipv4 *) (items->spec))->hdr.next_proto_id; + if (item_flags & MLX5_FLOW_LAYER_OUTER_L3_IPV4) { + /* + * Multiple outer items are not allowed as + * tunnel parameters, will raise an error later. + */ + ipv4 = NULL; + } else { + ipv4 = items; + item_flags |= MLX5_FLOW_LAYER_OUTER_L3_IPV4; + } break; case RTE_FLOW_ITEM_TYPE_IPV6: ret = mlx5_flow_validate_item_ipv6(items, item_flags, error); if (ret < 0) return ret; - item_flags |= MLX5_FLOW_LAYER_OUTER_L3_IPV6; mask.ipv6 = flow_tcf_item_mask (items, &rte_flow_item_ipv6_mask, &flow_tcf_mask_supported.ipv6, @@ -1162,13 +1789,22 @@ struct pedit_parser { next_protocol = ((const struct rte_flow_item_ipv6 *) (items->spec))->hdr.proto; + if (item_flags & MLX5_FLOW_LAYER_OUTER_L3_IPV6) { + /* + *Multiple outer items are not allowed as + * tunnel parameters + */ + ipv6 = NULL; + } else { + ipv6 = items; + item_flags |= MLX5_FLOW_LAYER_OUTER_L3_IPV6; + } break; case RTE_FLOW_ITEM_TYPE_UDP: ret = mlx5_flow_validate_item_udp(items, item_flags, next_protocol, error); if (ret < 0) return ret; - item_flags |= MLX5_FLOW_LAYER_OUTER_L4_UDP; mask.udp = flow_tcf_item_mask (items, &rte_flow_item_udp_mask, &flow_tcf_mask_supported.udp, @@ -1177,6 +1813,12 @@ struct pedit_parser { error); if (!mask.udp) return -rte_errno; + if (item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP) { + udp = NULL; + } else { + udp = items; + item_flags |= MLX5_FLOW_LAYER_OUTER_L4_UDP; + } break; case RTE_FLOW_ITEM_TYPE_TCP: ret = mlx5_flow_validate_item_tcp @@ -1186,7 +1828,6 @@ struct pedit_parser { error); if (ret < 0) return ret; - item_flags |= MLX5_FLOW_LAYER_OUTER_L4_TCP; mask.tcp = flow_tcf_item_mask (items, &rte_flow_item_tcp_mask, &flow_tcf_mask_supported.tcp, @@ -1195,11 +1836,36 @@ struct pedit_parser { error); if (!mask.tcp) return -rte_errno; + item_flags |= MLX5_FLOW_LAYER_OUTER_L4_TCP; + break; + case RTE_FLOW_ITEM_TYPE_VXLAN: + ret = mlx5_flow_validate_item_vxlan(items, + item_flags, error); + if (ret < 0) + return ret; + mask.vxlan = flow_tcf_item_mask + (items, &rte_flow_item_vxlan_mask, + &flow_tcf_mask_supported.vxlan, + &flow_tcf_mask_empty.vxlan, + sizeof(flow_tcf_mask_supported.vxlan), + error); + if (!mask.vxlan) + return -rte_errno; + if (mask.vxlan->vni[0] != 0xff || + mask.vxlan->vni[1] != 0xff || + mask.vxlan->vni[2] != 0xff) + return rte_flow_error_set + (error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM_MASK, + mask.vxlan, + "no support for partial or " + "empty mask on \"vxlan.vni\" field"); + item_flags |= MLX5_FLOW_LAYER_VXLAN; break; default: return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, - NULL, "item not supported"); + items, "item not supported"); } } for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { @@ -1271,6 +1937,33 @@ struct pedit_parser { " set action must follow push action"); current_action_flag = MLX5_FLOW_ACTION_OF_SET_VLAN_PCP; break; + case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: + if (action_flags & (MLX5_ACTION_VXLAN_ENCAP + | MLX5_ACTION_VXLAN_DECAP)) + return rte_flow_error_set + (error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, actions, + "can't have multiple vxlan actions"); + ret = flow_tcf_validate_vxlan_encap(actions, error); + if (ret < 0) + return ret; + action_flags |= MLX5_ACTION_VXLAN_ENCAP; + break; + case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: + if (action_flags & (MLX5_ACTION_VXLAN_ENCAP + | MLX5_ACTION_VXLAN_DECAP)) + return rte_flow_error_set + (error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, actions, + "can't have multiple vxlan actions"); + ret = flow_tcf_validate_vxlan_decap(item_flags, + actions, + ipv4, ipv6, udp, + error); + if (ret < 0) + return ret; + action_flags |= MLX5_ACTION_VXLAN_DECAP; + break; case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC: current_action_flag = MLX5_FLOW_ACTION_SET_IPV4_SRC; break; @@ -1391,6 +2084,12 @@ struct pedit_parser { return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, actions, "no fate action is found"); + if ((item_flags & MLX5_FLOW_LAYER_VXLAN) && + !(action_flags & MLX5_ACTION_VXLAN_DECAP)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, NULL, + "VNI pattern should be followed " + " by VXLAN_DECAP action"); return 0; } From patchwork Mon Oct 15 14:13:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slava Ovsiienko X-Patchwork-Id: 46850 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 C99B74C9C; Mon, 15 Oct 2018 16:14:23 +0200 (CEST) Received: from EUR03-AM5-obe.outbound.protection.outlook.com (mail-eopbgr30040.outbound.protection.outlook.com [40.107.3.40]) by dpdk.org (Postfix) with ESMTP id 3EDB92BF4 for ; Mon, 15 Oct 2018 16:14:13 +0200 (CEST) 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=2xs5QygSkS+1/gM7G2kfW3jgbZyTCbr10LERx9BTyBs=; b=VH+Fqn5xIITJBsbhAFvUhUdlrliRBVaJ1nLS0uTX9NSk+ZDBGruYqiamWRXf9SYnqX3sCd18BKz6m0dEm6qBqzkYWL/6MwpIAxlGye5b4dojZ0vFDr6Mt/qYjHy75j6+BSU0j931Lj1TXUS9T2ThaWuQqreBcCWEkV9D+5iQY1c= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=viacheslavo@mellanox.com; Received: from mellanox.com (37.142.13.130) by VI1PR05MB3277.eurprd05.prod.outlook.com (2603:10a6:802:1c::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1228.24; Mon, 15 Oct 2018 14:14:11 +0000 From: Viacheslav Ovsiienko To: shahafs@mellanox.com, yskoh@mellanox.com Cc: dev@dpdk.org, Viacheslav Ovsiienko Date: Mon, 15 Oct 2018 14:13:31 +0000 Message-Id: <1539612815-47199-4-git-send-email-viacheslavo@mellanox.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1539612815-47199-1-git-send-email-viacheslavo@mellanox.com> References: <1538461807-37507-1-git-send-email-viacheslavo@mellanox.com> <1539612815-47199-1-git-send-email-viacheslavo@mellanox.com> MIME-Version: 1.0 X-Originating-IP: [37.142.13.130] X-ClientProxiedBy: CWLP265CA0084.GBRP265.PROD.OUTLOOK.COM (2603:10a6:401:50::24) To VI1PR05MB3277.eurprd05.prod.outlook.com (2603:10a6:802:1c::22) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 6dc06759-0f29-4bc2-80d4-08d632a87af3 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:VI1PR05MB3277; X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 3:Css0pc8+z+Pb+1tHHOkZkIR+QGAjdPS2hVQLbL4c3K5UOk8yWTz8GGBgXKzmIvlNgt+zOr+1JQbRAvCKTa18+uMZG8fYrHmh8uq5YhUPPro4XgWxy/ieUxn1AR0t5SOZMtcgO1sAy+s6MMZAAoBtcc1rz3hw8kBz9Tb+c3rKix5HECUSp2kyODY2kNWMM1DJtAEFDAOt4aftELuhR5mSV2A/AX8Mr+hscNCKLeKux0aCNyNprb2XYWG5xR0kEH0n; 25:I2yNO+E25UWACqSS6tGj70XpK5h7eZ2mgqO4mQSz7bhFlaZ8fLs3GcRG4UXS0CDVkquyxuVr4ULfBTUyCaC3PbPVEFYoXVoaXkOwM5BSCbimF8EOze+yxd++AyKJZ1mh3kcpZauykVjD5CiMVQ2+oalk2bp6kHjqWX3LwnaORj2Yr1rrUANaat50CWeevXGOf5PE9ui5r+yy1J0QuwkJJUIA1x1XTl2ck0YNS+ff34B6wOu6qYE4gbR09PCbv9//+SM5z1BUjk7idXLdA2Z0SMhl31ftQ+vuXM2RWp/jPnmPD24OCBsE1pTRNPxzCptvgfJQNFwPKpDYnGrPAX0dfA==; 31:S05ZNhE9Uh5+klDSbIrAWtefAJwu2TyX0fvoV6diwEm1LBog3iZV+RqBiUAy98RZcCpBl5s/3wpVipPTM4UvzSdokAOrxQ/xUhQL0UpkDZ426w52ZQvFa7D2jIfOUmFrQRhJn9FvcrVY7A+sIo45Pl+cP9VrIQyg1ky20DRA7w+JK+ZhhgXxKuwSNgjVVd+gX6RXvHVlkaIKUQT5nahF8ZHDWkh6KTNFCUdgMl+7RjQ= X-MS-TrafficTypeDiagnostic: VI1PR05MB3277: X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 20:deQh7rrM08JdVLgB+6tT7Z41p1Fvv6XyaXgXNRlQ05tsdq1ca2H8aGy/2XfMTfu4T9d9szDTxgvKi7e8GxHF8ROvMNSs6d/4BUXhZaMVAxIjVlTjw79/g9ge6ZsKnreOdjPOkMVv5qPvSX2ICGQQ6F79ZuoeO9QGqlicCIbrsjbygH8KCPjpxfIl0E02oRBTE6Be6ztnJ+pVkJ/EnTzLVXFhY1qumj1GNZhjZNss36MN+gOzh7VaCEVAC0IkOahJi1cK+Ft3c1Ai9gxdJNJdMmzoqoP5nV+4ndNf51YW/t37ujEnHAxiQrJTzxfxORdgEicJN4lsukngpDYWCT/I/vj5qLwM1vh3+1q6gN4S/MM6svCd/JTreX67BsSXOCF0NxUsT9JUGhDG2Fbk1joPa/UPmghR7Cq+27dLGWLZw/Hif0uFCcEQ9c39JBMHqJuWVd+6iHkUrDvImGSbF3LNjWsGioUUNMWqbYSzvIHATkdz4ws660SC+ooYpiFLyG/l; 4:lZcneHYeoXYBmlKgMt74Ib/d8QINetuNVFwUjsEv4ijY8RswGbZgY1+YncRTuHp/Q7qpDwEbHLUnMnrtSIH+SqLoWCWANOjsioODb3PMfjegscqo1W2YoyZqIGXSnOEuooU52mKAAhWEmEVXHiF4+9bFp0/Xp+GZge4Li73oBHq3avzl5DI/Qn976AZcMQU0Ti0hQg3SvfJ3gD50AcRdYluzNin3WjIUmFSWhn+xGWOw6CSIEwL6OfVxO2jKqDOw4u3vqtWO2XMtoI1zBh+IcA== 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)(3002001)(3231355)(944501410)(52105095)(10201501046)(93006095)(93001095)(6055026)(149066)(150057)(6041310)(20161123560045)(20161123558120)(20161123562045)(20161123564045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(201708071742011)(7699051); SRVR:VI1PR05MB3277; BCL:0; PCL:0; RULEID:; SRVR:VI1PR05MB3277; X-Forefront-PRVS: 0826B2F01B X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(979002)(136003)(39860400002)(376002)(346002)(366004)(396003)(199004)(189003)(52314003)(107886003)(16526019)(66066001)(7736002)(8676002)(47776003)(106356001)(51416003)(7696005)(52116002)(25786009)(68736007)(105586002)(186003)(16586007)(305945005)(8936002)(3846002)(81166006)(81156014)(6116002)(386003)(50226002)(6666004)(50466002)(11346002)(86362001)(575784001)(14444005)(446003)(76176011)(97736004)(6636002)(21086003)(36756003)(2906002)(33026002)(4720700003)(69596002)(53936002)(55016002)(48376002)(85306007)(478600001)(476003)(8886007)(316002)(26005)(4326008)(4744004)(486006)(2616005)(5660300001)(956004)(969003)(989001)(999001)(1009001)(1019001); DIR:OUT; SFP:1101; SCL:1; SRVR:VI1PR05MB3277; H:mellanox.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-Exchange-Diagnostics: =?us-ascii?Q?1; VI1PR05MB3277; 23:a/GuOw/R+dT6c6GlrTaYHOlTs5fHFBBzmW13icwFg?= isdXDnUZ1p+ddJLZslbrsuBfSk1wO5bwdXIL5OKOoGIOHLVoY/YN4Fmg3cFwEapYEbcJSYnHlIp7wq44m8W7kcCUg23YGbzZpxkpm/TMr9AzdcCe40clokafGIkR1YcRAv/FW+1HAW2V9MEcJWGXwDCldh3boDz24vZ6kSmz65SKwTvfdeIE0WAruRa8WsS6Hk5BaQmnahh9M4fsT73Daz/uPF0S1+MJHc1KMU3z3ndNQrJBd1Rl0sc4M8jcqNhn9AcS6a7S/oFMAoN/HUY5bityc3q80hZzXB8bKbPXVm//A2f/2vMrRpQW9u+AihEeBtEm7loMPpDRDpm1N7fkqNn56MsVcWE9aqUnERIWGKX74WyGT8meoSZvU8pU4Y5ELlGVTm7Fmkbxl8iI6gAZQmg/0CNbfoZ8ueWEo/rTzGv0SbwgMFAMjaChqNVxrk6gv1AvzlXEzBrsV2ATfFC5xzgy8iZMU6hXa5E3S6NN5qOPN+DU43CeP62bpXMZNIv7KFjF1EN6VxibPAhndmTDoCmCzbXTU+alxG1UIO4rEkmUmIWK1COS09HyLTVAg7Wk3jmSUhAve8hV1yc81kSrDW7D1c7Zq2d3ATgCyQZJYoMWmjtnG8N8EGPbMOpTQ0HDlUigIqT85BN/ljQstoO5jcs7L3r5mKXEA5vKYdqKUXhsEZ5brqoz+ZnXEGqhGFmNyOJF2UoJVzqtRhRxm7FjF9fLwzooVjd01BePLFkT1vPIUvNVq7xCJYHA8to/q7cL+705b/1QQy8HElf/vApIG5e5MXzRtsBwLYglNgmZYrnovFYTbIuO5qlCFcGzmG6e/K6O5FOFvk7DfFo9OnTUrcJqX7dSV1Aw1WLej0VW/E6yA0EtXmRO4Qh5HY2MpM5HXKeluqI1+bISRxex5aHazEUcDUewU7lw3Pj/6gslKHRJm8d2kdHHxi6lcKeoulMtoqbDyJOVXgOQOgoK58gnTN2D97xxlN92BVEHKBC4jtxOSU4kbKVl6uHQmXXgWXxL8RajVZCvwaoUW+7EDUFfuPJfA4m01ic3q1vib0ZCofiEiWLm+2bhPh4eGqxCY6eWxvWUAt/SJ74i4EulHeSa+oIH1xrUAUSOQ76DsLgB4ylW2zVqwvLC5M7J1nn4Mr+euKqBJzD27crwtXTYk8ljgoHi2KMfQHukmwrXOEdOYdry4D5ITOHDJqUOk2KvH64e4TE3AVj6Arl6P/I9COS3o0w6c13Hgw5U8dKB2U3h+eus/BoardkpU7ih/4k4Pi1Mm74d2Sce1J4to8S0ULb3lkCYW2Fpk6NghjJg4m7eJwYCSK7/eqN67jK1F3WM9QVEUctnJK1RKOD3WMbnoWjxkyYjhGXH0isSzDPwsq7h78znH5nos36DIiEE3fxFuesYBexO1uOUhIzbHuLZ4EJHOspNAVZyNXRd40Jcvdg3Ged4w== X-Microsoft-Antispam-Message-Info: Ztn7tuDJuiNK4MqyJvBzoD05d8luecpv4yA0GTMVuC9oR9DStrobXQx/oNQ/RZj3DkQ83noRdgXZRBnDe+oo1s6/9k2VXh+Y3sP26tgNc89AQ0U9Syd4fBleMslkDTRLcItA3U5EfX9dN4tui5vcxax6Ft6759HHqnDwB8TIRiTrtFH59Y8OwZyzflTTv0Ca64FKSnsXeBU+YSSffsdyI7djjqJb/QkDQNgys5CMEPI1XxwCRM7ldenIFKqw7DTtgzU3bjpLuCBeQp14wawjyHrL+YXaKUmb0ZIVzs33L6KmQJRkCokCwzLBRypjwlxmlDcrFrq2HyQX4yR00DJKDvkSdy6QDoc481YNxp0AtLQ= X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 6:fc8RZlaaD5iBT4g1yHXsywIdoekrlzhpGyOT9wOL832Zu2vdMGz3zVzb7VfmZWAShj7jZ7i8H/QUAMCJr7G8V1uc+3u/i2be2nj4gW55lm27vRN6VWEq1aSvsqRt6mOjsEv6Srz3q5n6JI8xAHPJHxEyc5XPa4bQqD3O/omFyAnKwu86MjRmIAzTiQGZNV84qDpoj0gt5v8hJzLHRjUSgOEQ+5xV8ynqDBi2x1EI0+3E1VB6MTkxUZC1YtMxLj2Zi8jg0tG5zPVQXN701pYoUJnA3IILEEuI81kD+5mWr8G/lyxDapZuhIcHyQUxA82+aqCK+UnHGVWfLUpp6ZloWM72OzJSqLpKjTj96cCZUm44JKk4OPEQWZhim4rdjLzibeDTM05ZoYI7TzhB3YWT4nxA1a4BXmg58V/qvk+krCKkLn+UZH6rXfC1Lx5LB/++RqfWAZ14JNnSVw01ccvBag==; 5:t5UuNxBTe0b6BNCSzvAg/biZuEfGbTwdvwGK+jRJAQxejWjWNQU5yDbdfDDoT3BBjtI9mw5vt4G8nkMhLCXQN+eJ3htJWNyHr7myenr426VqmG7VXDVR6uz3axbrpdFleloadayMtvJZAHMdwP1iitRW9dnTEmY+13QkslGI7xs=; 7:qBo0GM9TbpmDPQ7aRrmDLMYU+UFp94U3RwtR7dupY0Glna0SB76P00W6zilWnQ/IDY9gvCySCN+lE/F7KA4Q3h3jfgHqhthtlJp8KK4Drap7zSEXL+mDz1I/hw7WbGRrJ1soRmZSdTSAL9MEERhkO6D6EIUTN1Cbc3oN86ejv4o60xn1qF6CBmLlZuB4Biiy/1apmrRXg+v91fR4lh4p0w3QUQt0nrhajbsr+BIp/5yM6LKj7JdeBkmgbskSuRNv SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Oct 2018 14:14:11.1770 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 6dc06759-0f29-4bc2-80d4-08d632a87af3 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR05MB3277 Subject: [dpdk-dev] [PATCH v2 3/7] net/mlx5: e-switch VXLAN flow translation routine 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" This part of patchset adds support of VXLAN-related items and actions to the flow translation routine. If some of them are specified in the rule, the extra space for tunnel description structure is allocated. 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 Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_flow_tcf.c | 641 +++++++++++++++++++++++++++++++++++---- 1 file changed, 578 insertions(+), 63 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_tcf.c b/drivers/net/mlx5/mlx5_flow_tcf.c index 0055417..660d45e 100644 --- a/drivers/net/mlx5/mlx5_flow_tcf.c +++ b/drivers/net/mlx5/mlx5_flow_tcf.c @@ -2094,6 +2094,265 @@ struct pedit_parser { } /** + * 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. + * + * @return + * The size needed the Netlink message tunnel_key + * parameter buffer to store the item attributes. + */ +static int +flow_tcf_parse_vxlan_encap_eth(const struct rte_flow_item_eth *spec, + const struct rte_flow_item_eth *mask, + struct mlx5_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 |= MLX5_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 |= MLX5_FLOW_TCF_ENCAP_ETH_SRC; + } + /* + * No space allocated for ethernet addresses within Netlink + * message tunnel_key record - these ones are not + * supported by tc. + */ + return 0; +} + +/** + * 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. + * + * @return + * The size needed the Netlink message tunnel_key + * parameter buffer to store the item attributes. + */ +static int +flow_tcf_parse_vxlan_encap_ipv4(const struct rte_flow_item_ipv4 *spec, + struct mlx5_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 |= MLX5_FLOW_TCF_ENCAP_IPV4_SRC | + MLX5_FLOW_TCF_ENCAP_IPV4_DST; + return 2 * SZ_NLATTR_TYPE_OF(uint32_t); +} + +/** + * 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. + * + * @return + * The size needed the Netlink message tunnel_key + * parameter buffer to store the item attributes. + */ +static int +flow_tcf_parse_vxlan_encap_ipv6(const struct rte_flow_item_ipv6 *spec, + struct mlx5_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 |= MLX5_FLOW_TCF_ENCAP_IPV6_SRC | + MLX5_FLOW_TCF_ENCAP_IPV6_DST; + return SZ_NLATTR_DATA_OF(IPV6_ADDR_LEN) * 2; +} + +/** + * 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. + * + * @return + * The size needed the Netlink message tunnel_key + * parameter buffer to store the item attributes. + */ +static int +flow_tcf_parse_vxlan_encap_udp(const struct rte_flow_item_udp *spec, + const struct rte_flow_item_udp *mask, + struct mlx5_flow_tcf_vxlan_encap *encap) +{ + int size = SZ_NLATTR_TYPE_OF(uint16_t); + + assert(spec); + encap->udp.dst = spec->hdr.dst_port; + encap->mask |= MLX5_FLOW_TCF_ENCAP_UDP_DST; + if (!mask || mask->hdr.src_port != RTE_BE16(0x0000)) { + encap->udp.src = spec->hdr.src_port; + size += SZ_NLATTR_TYPE_OF(uint16_t); + encap->mask |= MLX5_FLOW_TCF_ENCAP_IPV4_SRC; + } + return size; +} + +/** + * 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. + * + * @return + * The size needed the Netlink message tunnel_key + * parameter buffer to store the item attributes. + */ +static int +flow_tcf_parse_vxlan_encap_vni(const struct rte_flow_item_vxlan *spec, + struct mlx5_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 |= MLX5_FLOW_TCF_ENCAP_VXLAN_VNI; + return SZ_NLATTR_TYPE_OF(uint32_t); +} + +/** + * 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. + * + * @return + * The size the part of Netlink message buffer to store the item + * attributes on success, zero otherwise. The mask field in + * result structure reflects correctly parsed items. + */ +static int +flow_tcf_vxlan_encap_parse(const struct rte_flow_action *action, + struct mlx5_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; + int size = 0; + + 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; + size += flow_tcf_parse_vxlan_encap_eth(spec.eth, + mask.eth, + encap); + break; + case RTE_FLOW_ITEM_TYPE_IPV4: + spec.ipv4 = items->spec; + size += flow_tcf_parse_vxlan_encap_ipv4(spec.ipv4, + encap); + break; + case RTE_FLOW_ITEM_TYPE_IPV6: + spec.ipv6 = items->spec; + size += flow_tcf_parse_vxlan_encap_ipv6(spec.ipv6, + encap); + break; + case RTE_FLOW_ITEM_TYPE_UDP: + mask.udp = items->mask; + spec.udp = items->spec; + size += flow_tcf_parse_vxlan_encap_udp(spec.udp, + mask.udp, + encap); + break; + case RTE_FLOW_ITEM_TYPE_VXLAN: + spec.vxlan = items->spec; + size += 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 0; + } + } + return size; +} + +/** * Calculate maximum size of memory for flow items of Linux TC flower and * extract specified items. * @@ -2148,7 +2407,7 @@ struct pedit_parser { case RTE_FLOW_ITEM_TYPE_IPV6: size += 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 |= MLX5_FLOW_LAYER_OUTER_L3_IPV6; break; @@ -2164,6 +2423,10 @@ struct pedit_parser { /* dst/src port and mask. */ flags |= MLX5_FLOW_LAYER_OUTER_L4_TCP; break; + case RTE_FLOW_ITEM_TYPE_VXLAN: + size += SZ_NLATTR_TYPE_OF(uint32_t); + flags |= MLX5_FLOW_LAYER_VXLAN; + break; default: DRV_LOG(WARNING, "unsupported item %p type %d," @@ -2184,13 +2447,16 @@ struct pedit_parser { * Pointer to the list of actions. * @param[out] action_flags * Pointer to the detected actions. + * @param[out] tunnel + * Pointer to tunnel encapsulation parameters structure to fill. * * @return * Maximum size of memory for actions. */ static int flow_tcf_get_actions_and_size(const struct rte_flow_action actions[], - uint64_t *action_flags) + uint64_t *action_flags, + void *tunnel) { int size = 0; uint64_t flags = 0; @@ -2246,6 +2512,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 += 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 += SZ_NLATTR_TYPE_OF(struct tc_tunnel_key); + size += flow_tcf_vxlan_encap_parse(actions, tunnel) + + RTE_ALIGN_CEIL /* preceding encap params. */ + (sizeof(struct mlx5_flow_tcf_vxlan_encap), + MNL_ALIGNTO); + flags |= MLX5_ACTION_VXLAN_ENCAP; + break; + case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: + size += 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 += SZ_NLATTR_TYPE_OF(struct tc_tunnel_key); + size += RTE_ALIGN_CEIL /* preceding decap params. */ + (sizeof(struct mlx5_flow_tcf_vxlan_decap), + MNL_ALIGNTO); + flags |= MLX5_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: @@ -2289,6 +2578,26 @@ 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 rte_be32_t +vxlan_vni_as_be32(const uint8_t vni[3]) +{ + rte_be32_t ret; + + ret = vni[0]; + ret = (ret << 8) | vni[1]; + ret = (ret << 8) | vni[2]; + return RTE_BE32(ret); +} + +/** * Prepare a flow object for Linux TC flower. It calculates the maximum size of * memory required, allocates the memory, initializes Netlink message headers * and set unique TC message handle. @@ -2323,22 +2632,54 @@ struct pedit_parser { struct mlx5_flow *dev_flow; struct nlmsghdr *nlh; struct tcmsg *tcm; + struct mlx5_flow_tcf_vxlan_encap encap = {.mask = 0}; + uint8_t *sp, *tun = NULL; size += flow_tcf_get_items_and_size(attr, items, item_flags); - size += flow_tcf_get_actions_and_size(actions, action_flags); - dev_flow = rte_zmalloc(__func__, size, MNL_ALIGNTO); + size += flow_tcf_get_actions_and_size(actions, action_flags, &encap); + dev_flow = rte_zmalloc(__func__, size, + RTE_MAX(alignof(struct mlx5_flow_tcf_tunnel_hdr), + (size_t)MNL_ALIGNTO)); if (!dev_flow) { rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "not enough memory to create E-Switch flow"); return NULL; } - nlh = mnl_nlmsg_put_header((void *)(dev_flow + 1)); + sp = (uint8_t *)(dev_flow + 1); + if (*action_flags & MLX5_ACTION_VXLAN_ENCAP) { + tun = sp; + sp += RTE_ALIGN_CEIL + (sizeof(struct mlx5_flow_tcf_vxlan_encap), + MNL_ALIGNTO); + size -= RTE_ALIGN_CEIL + (sizeof(struct mlx5_flow_tcf_vxlan_encap), + MNL_ALIGNTO); + encap.hdr.type = MLX5_FLOW_TCF_TUNACT_VXLAN_ENCAP; + memcpy(tun, &encap, + sizeof(struct mlx5_flow_tcf_vxlan_encap)); + } else if (*action_flags & MLX5_ACTION_VXLAN_DECAP) { + tun = sp; + sp += RTE_ALIGN_CEIL + (sizeof(struct mlx5_flow_tcf_vxlan_decap), + MNL_ALIGNTO); + size -= RTE_ALIGN_CEIL + (sizeof(struct mlx5_flow_tcf_vxlan_decap), + MNL_ALIGNTO); + encap.hdr.type = MLX5_FLOW_TCF_TUNACT_VXLAN_DECAP; + memcpy(tun, &encap, + sizeof(struct mlx5_flow_tcf_vxlan_decap)); + } + nlh = mnl_nlmsg_put_header(sp); tcm = mnl_nlmsg_put_extra_header(nlh, sizeof(*tcm)); *dev_flow = (struct mlx5_flow){ .tcf = (struct mlx5_flow_tcf){ + .nlsize = size, .nlh = nlh, .tcm = tcm, + .tunnel = (struct mlx5_flow_tcf_tunnel_hdr *)tun, + .item_flags = *item_flags, + .action_flags = *action_flags, }, }; /* @@ -2392,6 +2733,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; @@ -2402,6 +2744,14 @@ struct pedit_parser { const struct rte_flow_action_of_set_vlan_pcp * of_set_vlan_pcp; } conf; + union { + struct mlx5_flow_tcf_tunnel_hdr *hdr; + struct mlx5_flow_tcf_vxlan_decap *vxlan; + } decap; + union { + struct mlx5_flow_tcf_tunnel_hdr *hdr; + struct mlx5_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; @@ -2418,6 +2768,12 @@ struct pedit_parser { claim_nonzero(flow_tcf_build_ptoi_table(dev, ptoi, PTOI_TABLE_SZ_MAX(dev))); + encap.hdr = NULL; + decap.hdr = NULL; + if (dev_flow->tcf.action_flags & MLX5_ACTION_VXLAN_ENCAP) + encap.vxlan = dev_flow->tcf.vxlan_encap; + if (dev_flow->tcf.action_flags & MLX5_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. */ @@ -2435,7 +2791,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; @@ -2479,6 +2834,12 @@ struct pedit_parser { spec.eth->type); eth_type_set = 1; } + /* + * L2 addresses/masks should be sent anyway, + * including VXLAN encap/decap cases, sometimes + * kernel returns an error if no L2 address + * provided and skip_sw flag is set + */ if (!is_zero_ether_addr(&mask.eth->dst)) { mnl_attr_put(nlh, TCA_FLOWER_KEY_ETH_DST, ETHER_ADDR_LEN, @@ -2495,8 +2856,19 @@ struct pedit_parser { ETHER_ADDR_LEN, mask.eth->src.addr_bytes); } - break; + if (decap.hdr) { + DRV_LOG(INFO, + "ethernet addresses are treated " + "as inner ones for tunnel decapsulation"); + } + assert(dev_flow->tcf.nlsize >= nlh->nlmsg_len); + break; case RTE_FLOW_ITEM_TYPE_VLAN: + if (encap.hdr || decap.hdr) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM, NULL, + "outer VLAN is not " + "supported for tunnels"); item_flags |= MLX5_FLOW_LAYER_OUTER_VLAN; mask.vlan = flow_tcf_item_mask (items, &rte_flow_item_vlan_mask, @@ -2528,6 +2900,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; @@ -2538,36 +2911,53 @@ 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, - vlan_present ? - TCA_FLOWER_KEY_VLAN_ETH_TYPE : - TCA_FLOWER_KEY_ETH_TYPE, - RTE_BE16(ETH_P_IP)); - 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, + 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)); + } + 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; + 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; @@ -2578,38 +2968,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)); + } + 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, + mnl_attr_put(nlh, decap.vxlan ? + TCA_FLOWER_KEY_ENC_IPV6_SRC : + TCA_FLOWER_KEY_IPV6_SRC, sizeof(spec.ipv6->hdr.src_addr), spec.ipv6->hdr.src_addr); - mnl_attr_put(nlh, TCA_FLOWER_KEY_IPV6_SRC_MASK, + mnl_attr_put(nlh, decap.vxlan ? + TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK : + TCA_FLOWER_KEY_IPV6_SRC_MASK, sizeof(mask.ipv6->hdr.src_addr), mask.ipv6->hdr.src_addr); } if (!IN6_IS_ADDR_UNSPECIFIED(mask.ipv6->hdr.dst_addr)) { - mnl_attr_put(nlh, TCA_FLOWER_KEY_IPV6_DST, + mnl_attr_put(nlh, decap.vxlan ? + TCA_FLOWER_KEY_ENC_IPV6_DST : + TCA_FLOWER_KEY_IPV6_DST, sizeof(spec.ipv6->hdr.dst_addr), spec.ipv6->hdr.dst_addr); - mnl_attr_put(nlh, TCA_FLOWER_KEY_IPV6_DST_MASK, + mnl_attr_put(nlh, decap.vxlan ? + TCA_FLOWER_KEY_ENC_IPV6_DST_MASK : + TCA_FLOWER_KEY_IPV6_DST_MASK, sizeof(mask.ipv6->hdr.dst_addr), 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; @@ -2620,26 +3025,44 @@ 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_BE16(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; @@ -2682,7 +3105,15 @@ 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); + 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); default: return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, @@ -2715,6 +3146,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){ @@ -2724,6 +3163,7 @@ struct pedit_parser { }); 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_JUMP: conf.jump = actions->conf; @@ -2741,6 +3181,7 @@ struct pedit_parser { }); 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_DROP: na_act_index = @@ -2827,6 +3268,76 @@ struct pedit_parser { (na_vlan_priority) = conf.of_set_vlan_pcp->vlan_pcp; } + assert(dev_flow->tcf.nlsize >= nlh->nlmsg_len); + 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); + 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 & MLX5_FLOW_TCF_ENCAP_UDP_DST) + mnl_attr_put_u16(nlh, + TCA_TUNNEL_KEY_ENC_DST_PORT, + encap.vxlan->udp.dst); + if (encap.vxlan->mask & MLX5_FLOW_TCF_ENCAP_IPV4_SRC) + mnl_attr_put_u32(nlh, + TCA_TUNNEL_KEY_ENC_IPV4_SRC, + encap.vxlan->ipv4.src); + if (encap.vxlan->mask & MLX5_FLOW_TCF_ENCAP_IPV4_DST) + mnl_attr_put_u32(nlh, + TCA_TUNNEL_KEY_ENC_IPV4_DST, + encap.vxlan->ipv4.dst); + if (encap.vxlan->mask & MLX5_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 & MLX5_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 & MLX5_FLOW_TCF_ENCAP_VXLAN_VNI) + mnl_attr_put_u32(nlh, + TCA_TUNNEL_KEY_ENC_KEY_ID, + vxlan_vni_as_be32 + (encap.vxlan->vxlan.vni)); +#ifdef TCA_TUNNEL_KEY_NO_CSUM + mnl_attr_put_u8(nlh, TCA_TUNNEL_KEY_NO_CSUM, 0); +#endif + 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: @@ -2850,7 +3361,11 @@ 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, + dev_flow->tcf.action_flags & MLX5_ACTION_VXLAN_DECAP + ? 0 : TCA_CLS_FLAGS_SKIP_SW); mnl_attr_nest_end(nlh, na_flower); + assert(dev_flow->tcf.nlsize >= nlh->nlmsg_len); return 0; } From patchwork Mon Oct 15 14:13:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slava Ovsiienko X-Patchwork-Id: 46851 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 D99144CA5; Mon, 15 Oct 2018 16:14:25 +0200 (CEST) Received: from EUR03-AM5-obe.outbound.protection.outlook.com (mail-eopbgr30056.outbound.protection.outlook.com [40.107.3.56]) by dpdk.org (Postfix) with ESMTP id 258AA2BF4 for ; Mon, 15 Oct 2018 16:14:14 +0200 (CEST) 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=FAkxRyI0HMX78Sue0juSB5dfAlejJiAqM1irBTVdyJg=; b=IMe8C0M1qDlCqhcfytZ3t6kWn4sCByureZXyxsZdcmB0MYnkB2WyUNJK2Aqe3Qo7EqQS//9XkilDu3NJi14JMCAlAz9SjJS/4j6cz97pJbEsYwFSlpHlJE9d4sQYauUczRGWoxWNWjHOZoEcByMYVOJ7iRFU2msNnyrtWOpPmkk= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=viacheslavo@mellanox.com; Received: from mellanox.com (37.142.13.130) by VI1PR05MB3277.eurprd05.prod.outlook.com (2603:10a6:802:1c::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1228.24; Mon, 15 Oct 2018 14:14:12 +0000 From: Viacheslav Ovsiienko To: shahafs@mellanox.com, yskoh@mellanox.com Cc: dev@dpdk.org, Viacheslav Ovsiienko Date: Mon, 15 Oct 2018 14:13:32 +0000 Message-Id: <1539612815-47199-5-git-send-email-viacheslavo@mellanox.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1539612815-47199-1-git-send-email-viacheslavo@mellanox.com> References: <1538461807-37507-1-git-send-email-viacheslavo@mellanox.com> <1539612815-47199-1-git-send-email-viacheslavo@mellanox.com> MIME-Version: 1.0 X-Originating-IP: [37.142.13.130] X-ClientProxiedBy: CWLP265CA0084.GBRP265.PROD.OUTLOOK.COM (2603:10a6:401:50::24) To VI1PR05MB3277.eurprd05.prod.outlook.com (2603:10a6:802:1c::22) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 55839192-9d6c-4c12-8d75-08d632a87ba1 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:VI1PR05MB3277; X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 3:jLxHAYSYvpkan6As9ToBswWxCjIkvWwRxS2Q3eT9DpGNiPDathe768+kXgdW0ShvqZ3lyIGkv4KGBfSdy3dgV4wOKlpzKsZkVXlZ3imzTpLR2H7Pa3HJn7DpydUIkP1Z6q1nuVkmE8R/DUNdw8SHhhxK9cJT9CRAjFTAa1mUMYjy9A+PUkcNgTZWIGnyvP1+oSmvGlnt21YtekqnHvyFuKi2uLgRKe5U0ZNyMyW7vAQVWhcuWgWPsgnELIwLWfv3; 25:25YruTMJrVGzTwRukjOFiN0zS3IJkAVK2FoAlMcjMVxurG7Hf4gM+Y5KlPxutlKsuS12thX4d3Zul1Jqk7ehidQFyY/bG9xZc535Dhta3IVKzo2Vznmi/DUEB+0wmFIg73lEnh2a8qubaIjH6YUa/j/Iu4SNR3HsrlzJxVz/E+baGhuriOjf4Z+U1pdnxxwPTw2egDMYlbNMV4JFEm8tjh59DJ/zFfCqfDH9hKjj7cZb2ypKoutA+cHHOZMtMJBH/8we8uPIjZWfaa6P+zr9LkizDRV4oCpP1Rnc8BAUXAkAAhpqeahFCcHc8eOD3hDSrYsKBN/5A2PqTa75acJpAw==; 31:7hEZ9ipYKdA3CGj/ncHWlJF6jNJJIsQUC6y3gVCMr4R/V1MfxZkzid4VrPpT6D1Utv6NFy3R05MEHy/GfrA8fXpTKsAdMkceu7bR1+A477xodJ6qZTfxnYC2LGNwIo4vbyeA4XMYNE63GEExpoaGEbs0qyMqJXU+Jr3K6MW/wbUmHa9mq88ODDj4m0u2+sXw11ST+U6JWF7dtZBp6yu/E4JhgwD/4+EkfyEmG6lb8D4= X-MS-TrafficTypeDiagnostic: VI1PR05MB3277: X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 20:2XFmlMWJsydxDQR5v0qptBR3EtspmcYJkPtRP+r5JXWCWssOxDsZTPc3FluSHBnKTbFo1tzpBFkG/9FPw8PUI0Ihrghz6ZYLDhp4Wyf03wYvNNOtQfAohPmxV6xawIXywzxXBvzbleRVce/lIlE9KzvT1P/reMdu9l57P436ALULLV6Pdy4mrn0lfPlD8nCmT/hbgMP/Okg1S7dOyFWb4s+gspPBObw/BanqPeStOlRSvsM+uCq14L+eJL9KnPjE+wxYswh6ettzDmOnbdNynO85un8IwnEB9TZrNt9+hedVvavAXbaJEwCAx1wMQEOxlFLqgMVwnuq8DomvuZOiPaFfGZalQIPLh8T8gF4G+jbsQ08AamW5xDFIl3h3t+qPpp3k62oM2Ul2Yne+DR2xjC4xvYLk0Z9xfF/1rkvz2CO+z1B8KaKkxAidUhHtdfrWARlGtXKfY7W11IDmB7WiH6DzocVYu6qSLSKDeTQMoGVpN1o7HZounxkx3pU7AulE; 4:6Zorl+t9a9wayhpU0Up5XACvT60LoTpps3z4Od+0JLXTkAfKzqPTu4YP8VjnjnX4QSTqDsqLmGBgWqK0CGM3vOsGGHlaTWb0V09ZxrnL6aDeURMLLlHsnezL4J06kMk3Jv2DJWRm+D1YuPt5J31k+4IcCb2v4LtUcuRkR2U/BwAjA4K0OIQb1xVwAJcac3yEkc3sI/nOobLktuJyhiUIoTTBPN4bYUtudqSa+j3iPUQ9KDFM8c5SAtbNoCYsDUULExHB9D2oyX4BDgQPnD4POA== 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)(3002001)(3231355)(944501410)(52105095)(10201501046)(93006095)(93001095)(6055026)(149066)(150057)(6041310)(20161123560045)(20161123558120)(20161123562045)(20161123564045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(201708071742011)(7699051); SRVR:VI1PR05MB3277; BCL:0; PCL:0; RULEID:; SRVR:VI1PR05MB3277; X-Forefront-PRVS: 0826B2F01B X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(136003)(39860400002)(376002)(346002)(366004)(396003)(199004)(189003)(107886003)(16526019)(66066001)(7736002)(8676002)(47776003)(106356001)(51416003)(7696005)(52116002)(15650500001)(25786009)(68736007)(105586002)(186003)(16586007)(305945005)(8936002)(3846002)(81166006)(81156014)(6116002)(386003)(50226002)(6666004)(50466002)(11346002)(86362001)(14444005)(446003)(76176011)(97736004)(6636002)(21086003)(36756003)(2906002)(33026002)(4720700003)(69596002)(53936002)(55016002)(48376002)(85306007)(478600001)(476003)(8886007)(316002)(26005)(4326008)(486006)(2616005)(5660300001)(956004); DIR:OUT; SFP:1101; SCL:1; SRVR:VI1PR05MB3277; H:mellanox.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-Exchange-Diagnostics: =?us-ascii?Q?1; VI1PR05MB3277; 23:rNggLhYyO2yDNvyb8x9t98MS2AsLZnWz16Lz20Mi3?= GoJfE+7SqFqeBsmsv0QoFX9qj/IgZMgBwQ8+q0lSCmW3iCbqYGftRNQ181SIUE0UrD55U2pITIbMVuKSkHvZSDLPPmc6hoxbVeRRx4epAS3pP94Va+QNmhHjEFOxQrV9YF3hj2l1Lj3c/jCb5CLIQH9SGfnKtIqE+pYXjkiZbINvrkJF+9dElN7V+EjkVTXn++cC6Zs7GUhzdffgqVFbuz707gFuDUxTvf6ornEr+LixXCkc2o9ieItamboU+zy8LotjRg/DOTI1226GCumx147uiPuiGpPAN+nK2UvBAvLseP4p31B8O/NW0bjKwf1F/BxTcFrcGaRr+Jn4Ro1xwwCju2qTZvJDvBr8wVBOMcIeQnKkOafuZF0Bk2UwX9hNemgRkbfTtBfFpPm7XWv1Q+JalTzVHFtqkWeA9e000YCNYCX/wgHfaQ3n+k/gw6zsqrdbKbqIhKaem+XH/aLSNngGfoKJvGZZbSvJnpKEMeU38b+CCpLOXybFlOqBjMC8ED5L/4k80HqsXi+7jkRbXZDN6aABw1lDA6s9PbwrNTBOVnaBbCqGzOALZ+On0Nt77aS1UETfTHYTRHd9ZwZQQRexQdrS7/BaY6fM1ojJrnMgVuGSuVvqV5gP76/pRK7sL/yNB6OjSyZ5EfSMI1MiFFdSHCQuiBRJr/UqkFLJW4Knw/uQcErvf7iNvzQ9TwPOBa0l8IdKz9FJ+uNBPDQpmG9/talsTunkOVuDecopFn96+TNygSADfS9mNA65ckmw8tsr92G9ZafASe2FmKi+bxU/r++6XEauDAPnNnh+5gkueeWgWMk15S4YWeFNJvM2dYNHKcstXZ1AN+tjZmd7zeEwigQt/jvIxoJ7LrodCvMcq3vaBqLyvCSfQL8494Mw9Z4m57D3PZUBc+hw37cw9eAJA6yrtTIcMVp2nyg3cqzO2bsoxiNU5xVt4mhcaLiOegA6rOYk4Iw+hGOxSLMGRfUsT3jE2HHQvLDiE/KGRvuaJUAblVx9dr2OO1VT8TU1ILTczcU5tZ1CjSoLRllC16N17KpL6AVofsaXIdxGJJkDpDq0xMeW+9whMUrfEnzVgAoZyQEUESh6HRKa0yBc9eQDOWja52O9gbOb34jMPJKQ78/fLS56/MZUnvWGUI+boRK+ZJZ4uWWZw9+/BGbrHw6krPjICoRvrkonp3GodwvqwIhhCzH84KAb5FIU4ehWAi4IdqeO6p1fH+p9tto2EJMhSNq6VYJ/RqeKOIHdjUmguS0CPjiUVObtCCWsHU6wvslX2uO5e4rGPO8S7pFY/HYEOAn71kd0iJFv9PmykbJfw== X-Microsoft-Antispam-Message-Info: QwfVDkw4cs0J5wJNG6QnaefsJwWatTJJchiQGAdPjl0y4XMsI6U3Wt7CGeRhu8iDonWsPm45NvuRWhriijmbwAk+nj75+VeOIgpCTcia9apkgzo1IQ1MiyyvMtR0AugbabeSsBcH/Am72fTK41k8l9Y8H695jUalmNgSi0ObtCyc25Zv4Quf6BCsYO0S1mBMPI5pxL19OraspXx9nq3//ueSkRz/4vFKW1ORU+54CKFHuO8bdgfbKCKfUduCKbUhIblkuqd44jLcR0Yvu+QtO9BJsp3ngIadbeEClqfxjJvbCnX6ND9Tvhr9jrIhfstnzCMzDVNwdcbEwK7eJsKxkXp6niB5EKzD5cb3PjuSusQ= X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 6:ZfjRyT+zTNDYDTfFk4fgFatnPpRBiUZJEY7P6rfj4IIrakL6oaurdtlTjSQynv2PBGSWs3/2CNpR6i0C2HX+o31SNGVlHlJLL7qZx1kPAwuRteKPR1eCXbpnAukQS7UHWubuOS8rpbngeIgvHc/Ytf7HXMv8XUZyqoxDTV7SsUAjCezOEBtGFRt/8og4BnkvKOKcPcbPhR/FO2y7f/LqAGTTvgM2Ixyco9LAYsHyKaL0qdto8IFWcFyYa5lPNvv8uDgXHLPmnCgxpTnI6Z12mRifx5qEDsUKF1EYklr7i5dQ8Xe/kku0JAbDSRx1cQTubTWK0NCiDcEh3saktTIusrCQecqJkhUJvVZMPJ+QjTX/IgTXBabxslWConPeDfkG//tri2loZjxiPyJrZfUnv1vvemsWpYsLaT1wmwoMRtNNu9htgDLgC+TimUBK+5MRcuNYmhcWrclhqmeI3tGGng==; 5:TuFJYC/cjtWK08HsvzGv0ErAk8MuUy7kW/H+rVHbjPdVXHF0NeuOb6AZ3HSSJqJNwwBnp6tfqMdlfQUSYgimhjBVDmZtEzLPQfQc2lItMFQ/UMgaF3mbzWTLEulxw9JAC8XBRDywE60pek8lGu53BPrYLqJ6jOHZdjNULt1wh9s=; 7:1T8fbsxfZ23KKe1o5V/12wrZgpjGIVk/kQnhSuqQCDMi9gVAR3pixuGJYy0CWdEZkMZdddf1xFZBNkc6/km5CqFmuNAqeXetcSmZvfATHPUyWVzrFVcM6kZFYU7LWxESEibNfFdb/RM9sfT4PAT1PFMf3HywLTPDFHy9+hbKr+h/P0iPJWEfVap9wgVPp3MI2gAIM9QukuueOIy1Xvl/zkZOsC5mKTTD1xv+UiJk7BRrob0I+KPL0e6Y+rtme8Jw SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Oct 2018 14:14:12.3802 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 55839192-9d6c-4c12-8d75-08d632a87ba1 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR05MB3277 Subject: [dpdk-dev] [PATCH v2 4/7] net/mlx5: e-switch VXLAN netlink routines update 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" This part of patchset updates Netlink exchange routine. Message sequence numbers became not random ones, the multipart reply messages are supported, not propagating errors to the following socket calls, Netlink replies buffer size is increased to MNL_SOCKET_BUFFER_SIZE and now is preallocated at context creation time instead of stack usage. This update is needed to support Netlink query operations. Suggested-by: Adrien Mazarguil Signed-off-by: Viacheslav Ovsiienko Acked-by: Yongseok Koh --- drivers/net/mlx5/mlx5_flow_tcf.c | 82 +++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 22 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_tcf.c b/drivers/net/mlx5/mlx5_flow_tcf.c index 660d45e..d6840d5 100644 --- a/drivers/net/mlx5/mlx5_flow_tcf.c +++ b/drivers/net/mlx5/mlx5_flow_tcf.c @@ -3372,37 +3372,75 @@ struct pedit_parser { /** * Send Netlink message with acknowledgment. * - * @param ctx + * @param tcf * Flow context to use. * @param nlh * Message to send. This function always raises the NLM_F_ACK flag before * sending. + * @param[in] msglen + * Message length. Message buffer may contain multiple commands and + * nlmsg_len field not always corresponds to actual message length. + * If 0 specified the nlmsg_len field in header is used as message length. + * @param[in] cb + * Callback handler for received message. + * @param[in] arg + * Context pointer for callback handler. * * @return * 0 on success, a negative errno value otherwise and rte_errno is set. */ static int -flow_tcf_nl_ack(struct mlx5_flow_tcf_context *ctx, struct nlmsghdr *nlh) +flow_tcf_nl_ack(struct mlx5_flow_tcf_context *tcf, + struct nlmsghdr *nlh, + uint32_t msglen, + mnl_cb_t cb, void *arg) { - alignas(struct nlmsghdr) - uint8_t ans[mnl_nlmsg_size(sizeof(struct nlmsgerr)) + - nlh->nlmsg_len - sizeof(*nlh)]; - uint32_t seq = ctx->seq++; - struct mnl_socket *nl = ctx->nl; - int ret; - - nlh->nlmsg_flags |= NLM_F_ACK; + unsigned int portid = mnl_socket_get_portid(tcf->nl); + uint32_t seq = tcf->seq++; + int err, ret; + + assert(tcf->nl); + assert(tcf->buf); + if (!seq) + seq = tcf->seq++; nlh->nlmsg_seq = seq; - ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len); - if (ret != -1) - ret = mnl_socket_recvfrom(nl, ans, sizeof(ans)); - if (ret != -1) - ret = mnl_cb_run - (ans, ret, seq, mnl_socket_get_portid(nl), NULL, NULL); + if (!msglen) { + msglen = nlh->nlmsg_len; + nlh->nlmsg_flags |= NLM_F_ACK; + } + ret = mnl_socket_sendto(tcf->nl, nlh, msglen); + err = (ret <= 0) ? errno : 0; + nlh = (struct nlmsghdr *)(tcf->buf); + /* + * The following loop postpones non-fatal errors until multipart + * messages are complete. + */ if (ret > 0) + while (true) { + ret = mnl_socket_recvfrom(tcf->nl, tcf->buf, + tcf->buf_size); + if (ret < 0) { + err = errno; + if (err != ENOSPC) + break; + } + if (!err) { + ret = mnl_cb_run(nlh, ret, seq, portid, + cb, arg); + if (ret < 0) { + err = errno; + break; + } + } + /* Will receive till end of multipart message */ + if (!(nlh->nlmsg_flags & NLM_F_MULTI) || + nlh->nlmsg_type == NLMSG_DONE) + break; + } + if (!err) return 0; - rte_errno = errno; - return -rte_errno; + rte_errno = err; + return -err; } /** @@ -3433,7 +3471,7 @@ struct pedit_parser { nlh = dev_flow->tcf.nlh; nlh->nlmsg_type = RTM_NEWTFILTER; nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; - if (!flow_tcf_nl_ack(nl, nlh)) + if (!flow_tcf_nl_ack(nl, nlh, 0, NULL, NULL)) return 0; return rte_flow_error_set(error, rte_errno, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, @@ -3466,7 +3504,7 @@ struct pedit_parser { nlh = dev_flow->tcf.nlh; nlh->nlmsg_type = RTM_DELTFILTER; nlh->nlmsg_flags = NLM_F_REQUEST; - flow_tcf_nl_ack(nl, nlh); + flow_tcf_nl_ack(nl, nlh, 0, NULL, NULL); } /** @@ -3842,7 +3880,7 @@ struct pedit_parser { tcm->tcm_handle = TC_H_MAKE(TC_H_INGRESS, 0); tcm->tcm_parent = TC_H_INGRESS; /* Ignore errors when qdisc is already absent. */ - if (flow_tcf_nl_ack(nl, nlh) && + if (flow_tcf_nl_ack(nl, nlh, 0, NULL, NULL) && rte_errno != EINVAL && rte_errno != ENOENT) return rte_flow_error_set(error, rte_errno, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, @@ -3858,7 +3896,7 @@ struct pedit_parser { tcm->tcm_handle = TC_H_MAKE(TC_H_INGRESS, 0); tcm->tcm_parent = TC_H_INGRESS; mnl_attr_put_strz_check(nlh, sizeof(buf), TCA_KIND, "ingress"); - if (flow_tcf_nl_ack(nl, nlh)) + if (flow_tcf_nl_ack(nl, nlh, 0, NULL, NULL)) return rte_flow_error_set(error, rte_errno, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "netlink: failed to create ingress" From patchwork Mon Oct 15 14:13:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slava Ovsiienko X-Patchwork-Id: 46852 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 174FC4CBD; Mon, 15 Oct 2018 16:14:28 +0200 (CEST) Received: from EUR03-AM5-obe.outbound.protection.outlook.com (mail-eopbgr30080.outbound.protection.outlook.com [40.107.3.80]) by dpdk.org (Postfix) with ESMTP id 3041E2C28 for ; Mon, 15 Oct 2018 16:14:16 +0200 (CEST) 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=lktZpFu5XVc8qAN2V7BARFQZk+JQOvObqq38/iEGvgs=; b=k5XeXHQ7cVeWisSlB4W0qmjr9UcER2FD2woJ7h/pnmruXRiFzoVihNEuv0bPJddXSiuwX0n867eiTMUWLKa3NUm8TXZPg5i3kS7ugl/p8QI9IbkLJIU50ontAgzexhjkZ/+NUaicndeVediIBWnl0g07hbER4HbOV1WUWfK8kLM= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=viacheslavo@mellanox.com; Received: from mellanox.com (37.142.13.130) by VI1PR05MB3277.eurprd05.prod.outlook.com (2603:10a6:802:1c::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1228.24; Mon, 15 Oct 2018 14:14:13 +0000 From: Viacheslav Ovsiienko To: shahafs@mellanox.com, yskoh@mellanox.com Cc: dev@dpdk.org, Viacheslav Ovsiienko Date: Mon, 15 Oct 2018 14:13:33 +0000 Message-Id: <1539612815-47199-6-git-send-email-viacheslavo@mellanox.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1539612815-47199-1-git-send-email-viacheslavo@mellanox.com> References: <1538461807-37507-1-git-send-email-viacheslavo@mellanox.com> <1539612815-47199-1-git-send-email-viacheslavo@mellanox.com> MIME-Version: 1.0 X-Originating-IP: [37.142.13.130] X-ClientProxiedBy: CWLP265CA0084.GBRP265.PROD.OUTLOOK.COM (2603:10a6:401:50::24) To VI1PR05MB3277.eurprd05.prod.outlook.com (2603:10a6:802:1c::22) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 4062ece7-070c-4c9f-d3db-08d632a87c69 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:VI1PR05MB3277; X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 3:8FsaZiPuj4wxPm4MoG1/2ksaBgEIJgXfwsG6TGRzTG+grSQVZM6BxFN8RROtyV+jLodLWaXHKRFbi0dP67hJ+E+tlQiWn8hnpFTModKN0NrUg1Y/I0xRvlC8ssWqSR/GVDFnzejuOYH+RteKqUjV4yLGwDwq5vr9eYbtGSF1xRAMv+bXzC1YJaqTU5nvne0m20YpwGPMDVgZ+f3kZg7jfpxUg9zb0C1JbJ/jQ1KbDJqyvUYyyiXRdBkGxF09H/2/; 25:iszPlTZfqEgw32Er5YlPCOSF8ZkuD2i5S3vOTTj4ZMdrVE9uEzB0zHJE/kNjsuRJqHB3NoR345A+NFKaeV1iU5dtrDtok23DPn0tRObC0vvb+VhEE5RUo9/2lIf75LOEysumi626KbxjCyPas25WrgOoT8aEX5PNkn66fk+6Y+MJRUca7lZGeEM8/H/C5ZYoR9jsNzRLfR0d4brTglZHe2r17WvgM32o0UBndenFX1ZYLEd26KjQh9vdP8nrTmQxH28IrWyTaSb8Jh7rVqbP21n3JmoXPn0TmKFDppOYGXuTviIw3YOWCijChigrJQ16Jc+Shzz+Ion26ajMRT4VKg==; 31:gAuhF0vH8VSUx4MKUX74rG2RWy0cP5P9hTlXx4fmZ4GC6joZkdEoRaI+VTwxFxskdNv9OBaUPDjr0FeKdqB3Z6qM9J2Jtmv9JXhp8//GhtLL3RyvZC5xH/l3IFKevyM/jfWIirW5NKNoDJ+Ci2sATxbuNUPvuG7PC4yQ1W+hGpL8dAxgeIrRFENRxICvc5519yTZxckmxg+5NkEGFVht9Y+q4J6ktQQtiLJG2WVV2Z0= X-MS-TrafficTypeDiagnostic: VI1PR05MB3277: X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 20:cNEhSDm7BllswQWVxueSRrEs2gZJuPWa9+N+2KcJjVHdK9Ka1FIV07KZqdCWFKosqQxxUyx/pkpFgraTzRlMQ+ZNDc4gq+Jm4Qs3+bKy/i4axVKo14W4dDTbPZf/1Bd4jEUYSsAwlUcGz+0A8xXn3+FIIRD0PgJUWUzU+a/0ddH4PRMGZz0dfpxg2Xb2yTss/NfXFd+086r5qzBs9HBo5oInYUFiILKtjHB19oLg+VNHPcMgjDe4KBxbg4z9fHJ+onw8cnq+cGp0910qfwopCyOJuhrXOhrmXPMScvLL6kolqfkTZMjsOB22I0I8WVE/m7cVfoKR3ZLsOoYEvYzxB08rjpIWLvYGEXKdbHH7zqiaOyR+vLtjGhcCbzjjh5W5AX7L6wvSe/e55D29Oy+7B4rVSCwc1zIQ6byP8jQvup37JOneRSrWysRm3BiRdum0kBr3zfJhfJy8t24MnEv66l9zZwkbkzbb00ON86k+xKZ/hH13rAN5Pncq+xwk835E; 4:hTklqH5q5xJ5Uyk6fhXGJ0AOB+AXdCxj+I4AjzHppJ5+Wzp9G99QZTPinJYpNqnldDYIPtXWRX9ppjqn+WW8ax8+VNupXznwbe+TR2laCL7jKWN55FL02Yt0kti5XGN0hilnRzmq62URZ78FgHqYypFjca48HM7w3/0seczrmeOrfc1HXAaO+A6y83C1ebilyTJwitfbjqAD+7mpdjoIbNL3EO75nbjKPNTSP+zhLEuc5gA7dkEO3o4mr0tgYjWcCCJQmvbKSBicGR57ILXAbA3iWmCPWOwxialKLRWdYHkux3Iyskk6SrcGh5ULo2M+l7TcDDoFfDiYMY9WOWmz93+gMtcHo7bmOrClhhZc2Kg= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(211171220733660)(788757137089); X-MS-Exchange-SenderADCheck: 1 X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(3002001)(3231355)(944501410)(52105095)(10201501046)(93006095)(93001095)(6055026)(149066)(150057)(6041310)(20161123560045)(20161123558120)(20161123562045)(20161123564045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(201708071742011)(7699051); SRVR:VI1PR05MB3277; BCL:0; PCL:0; RULEID:; SRVR:VI1PR05MB3277; X-Forefront-PRVS: 0826B2F01B X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(136003)(39860400002)(376002)(346002)(366004)(396003)(199004)(189003)(107886003)(16526019)(66066001)(7736002)(8676002)(47776003)(106356001)(51416003)(7696005)(52116002)(25786009)(68736007)(105586002)(186003)(16586007)(305945005)(8936002)(3846002)(81166006)(81156014)(6116002)(386003)(50226002)(6666004)(50466002)(11346002)(5024004)(86362001)(14444005)(446003)(76176011)(97736004)(6636002)(21086003)(36756003)(2906002)(33026002)(4720700003)(69596002)(53936002)(55016002)(48376002)(85306007)(478600001)(476003)(8886007)(316002)(26005)(4326008)(4744004)(486006)(2616005)(5660300001)(956004); DIR:OUT; SFP:1101; SCL:1; SRVR:VI1PR05MB3277; H:mellanox.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-Exchange-Diagnostics: =?us-ascii?Q?1; VI1PR05MB3277; 23:obZIgengMeNLbidwukCU+6nojrJ1bTgpZ0C/NSiKD?= VTyzRKV2SP1oEfZyGuXpEfOL6077ooieTjsncBVc6OfQtIHzU0la5S0DlYTTbZ5orClUTJ/J0Mtn1/rtSRT0iTOYQ+ub88/CBD3hSHiQ6Sodw54tT4Q5uNm2cn9H2Va0P055SLtc0LKtSFqyrLqwv8UMQLW02nqVVDpePp58WDXIcpN4yYWVjyQ60Qwy0j9r8C6tVpzszESjbrfBiog7dbvks9VwNCfrGEf3mCAih3fYHIrxboAsEUMvwbbaqzUjwwCKxaWQDHfLh/adoGZj2CV9yI1rQFa+zqRKopN+cDOObeDS9XA8ZUfFLPdJLiqFe4DVnV1t4GiDPdenTIuP9AyiAqBR7tPQcEowoLcsmST92ogXhkeKoAdcL/N4wFR8MpkzZyap8c4CM/FHzNhKwPqojnr5L8Wjk4Lyj7x49toRfZcP3m5lmj7FUbfIGKKTkB95g4qA+C8vViVj/LaBWR40JkfgmPIRtP9RGpmZ1bJz43wZ/ol2J16yw5tn3nr+8uEYogXq6Wvz+D2f1pLv1uBCPkG2Y62riNGL+IV8/2gE/hoM0tnRIuIidRxYUdkuotmlSrLzmxTe4EkAFX5W3XiEplbPh7x/Gp8JfgxdMvrklrUWlRmPd+mw9cQPp+lixkFzNhXDubUag31hDVx3u4NrQLEo+NZL6+jxPkMAoOVHTF8ZZ6yzZoeSrxRnEE2nu+ChZ4xyhjpBdtcs6mZVXGQHCN8neT5GyCArHiYNPH5cWkPhtxHn+DqfRwxMZeQLyUNv5IloG3+5ZcUGRxBvz9H+ZkacA90tuTtERq9jzLR5zfFyiiTBgtV/vTjOWq/3g+DBmqabp7toNceBSVpmMtGlSV3DBipovZm84JnjON+mNFPtehw5FS6Fio4UH3mYl7CFEmhCVF7QX4bUcUxIA1AaX0OKpNPAffcF9XJNoZkXntF4fNOxbZ6XmTue4b4KpNrQamwpXcerDd85dBkABf7qIkEhkSRVZZcNrVYpo12mFhtHNtSgnyckf6tOVA8YUvMtyMYQyo8ftTnThXn7JKKR2jYzm4WfaGlfow7Z01YXHvO7GriTmoez55YxwV8uZtOC/FXeLQci2w5PlDCJiX4/csA0H2YfUb8hQds6puq20Jv6YiHpt0xo7bjqG1hjs871b0lN0FUcqAJZ37kIhz23duWWCWGcRvz2ZumSe+JBs7JyYkLi9Y6D/Fi1O1b/9ML2QhypMW7MTWQUpYbG3jN2qoydExeg0mfFLA2e3NE7TH7NStcfvmNVT34iQr/TsMhQcF1vbvLn/xSpqG0GJCt0ug2A7wuIsusEPzIpJSqHg== X-Microsoft-Antispam-Message-Info: QDyx/off+8tQKm49N/EJ6X2aGKASDvDLHJCJiJXUaSzq/Snzl/wa0kBtwWguW3TwmrtinjPPh8rx+LjLdUrTjVHlvI/LCB2NPRAoMBqshoUoiiINt1m8W02OfbY+8GeIa4Gw3tLqEKPMAJEFjnJ4bTgBctG9GdaCxDGdirHhgb0fYkY0Z7Zd3yCcGHBpgmqOJtXgKYP+HA+HRmDeqonUAsF5QzV9lCLSgfLCa8aLRPoTuKESZ12p0CDpznbEZGszPAR3kceTNwj/JILIc7CnoMdxeWgMO4ZCYlz24gZQu4iQFM+5mioAD4/BaDlg6Sdp2p+LY+3E/KFlW+HGAhe2IeDBoNSAyJGCI6R39wfo+X8= X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 6:E//ZVbTtgwSFTrzE+apNBDWrG1+t9LFmx1sZLtEDZ5zcHkcxrdgBnrm+9MNj2+XOI0l8u6YserIYkh1Ew199zd24Y0Wyb4LLVa8ljp1FTUKsFnDm6FMhI3OraLhVQL6qPbva7V8KwlC2ar29/tbP6SDW1ZFeR9lz0PojO7y8QTpYotxc3SMqL3wdXObqltRC7gRcm8zkaZD50NT3HBOCKsDUNtph8Nn2rQKm04xj9cKanp1Gb2vvcI7HCc3L0duFX+0Ui8jh2siO/f529y8qzSJaRvKROP0IrwKikUFWoSR9gPCA0upm0DWd5NGCHSSObuPhcwXUQ1Lafw1zJ835fc36gA1TNkTcyswRXxVzWwby8Z+nf1MGW8m4M8knH+x2CVjOJ7MqXJiI48TQWPSE7aoh6isqGlGO27BDCsmmhWJyfAlJEgKDkdMFyKaLeSSpW0NwDIHO0Q6MN/O/hcMVWg==; 5:pGpiUkpSsnk4LBt2RevDiElHg/mggQc9C4DhBx26NMyOaIgoHaOLVDHmbq9bamSQnd8jrDEzFP5hoM4y9LG9cw2+NDsJ9QLctUVs8z5qdaibEjDDECrp//oHMD/ANt3g3VFZCC7rski8c/URZu51joe70BMcoa0LocTn7BEAMmk=; 7:7JUjbVpi93ebiw+OhU5TZrO5JAL/EohYnqXcYf67E2WWsf6KU9f77JOzy3qEQ5u6jFNBeN9vqrssIwqaeYiXbbARMARZXMX/Qwr3CZOKq6iqI0Ar435DaUuHhHA3TmFu89QT3tsfaaNbzqbAfRBSHht5gtITiLAOHSqoBJWgggWRY2xxdjQr7cdq0KmtvBF2QpZp0PLsNra6N/RpkyYM5eVwhUNM2pueEvYFx6uzv7/tTEoMTGquElebGk8zbsy1 SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Oct 2018 14:14:13.6302 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 4062ece7-070c-4c9f-d3db-08d632a87c69 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR05MB3277 Subject: [dpdk-dev] [PATCH v2 5/7] net/mlx5: e-switch VXLAN tunnel devices management 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" VXLAN interfaces are dynamically created for each local UDP port of outer networks and then used as targets for TC "flower" filters in order to perform encapsulation. These VXLAN interfaces are system-wide, the only one device with given UDP port can exist in the system (the attempt of creating another device with the same UDP local port returns EEXIST), so PMD should support the shared device instances database for PMD instances. These VXLAN implicitly created devices are called VTEPs (Virtual Tunnel End Points). Creation of the VTEP occurs at the moment of rule applying. The link is set up, root ingress qdisc is also initialized. Encapsulation VTEPs are created on per port basis, the single VTEP is attached to the outer interface and is shared for all encapsulation rules on this interface. The source UDP port is automatically selected in range 30000-60000. For decapsulaton one VTEP is created per every unique UDP local port to accept tunnel traffic. The name of created VTEP consists of prefix "vmlx_" and the number of UDP port in decimal digits without leading zeros (vmlx_4789). The VTEP can be preliminary created in the system before the launching application, it allows to share UDP ports between primary and secondary processes. Suggested-by: Adrien Mazarguil Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_flow_tcf.c | 503 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 499 insertions(+), 4 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_tcf.c b/drivers/net/mlx5/mlx5_flow_tcf.c index d6840d5..efa9c3b 100644 --- a/drivers/net/mlx5/mlx5_flow_tcf.c +++ b/drivers/net/mlx5/mlx5_flow_tcf.c @@ -3443,6 +3443,432 @@ struct pedit_parser { return -err; } +/* VTEP device list is shared between PMD port instances. */ +static LIST_HEAD(, mlx5_flow_tcf_vtep) + vtep_list_vxlan = LIST_HEAD_INITIALIZER(); +static pthread_mutex_t vtep_list_mutex = PTHREAD_MUTEX_INITIALIZER; + +/** + * Deletes VTEP network device. + * + * @param[in] tcf + * Context object initialized by mlx5_flow_tcf_context_create(). + * @param[in] vtep + * Object represinting the network device to delete. Memory + * allocated for this object is freed by routine. + */ +static void +flow_tcf_delete_iface(struct mlx5_flow_tcf_context *tcf, + struct mlx5_flow_tcf_vtep *vtep) +{ + struct nlmsghdr *nlh; + struct ifinfomsg *ifm; + alignas(struct nlmsghdr) + uint8_t buf[mnl_nlmsg_size(MNL_ALIGN(sizeof(*ifm))) + 8]; + int ret; + + assert(!vtep->refcnt); + if (vtep->created && vtep->ifindex) { + DRV_LOG(INFO, "VTEP delete (%d)", vtep->ifindex); + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = RTM_DELLINK; + nlh->nlmsg_flags = NLM_F_REQUEST; + ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm)); + ifm->ifi_family = AF_UNSPEC; + ifm->ifi_index = vtep->ifindex; + ret = flow_tcf_nl_ack(tcf, nlh, 0, NULL, NULL); + if (ret) + DRV_LOG(WARNING, "netlink: error deleting VXLAN " + "encap/decap ifindex %u", + ifm->ifi_index); + } + rte_free(vtep); +} + +/** + * Creates VTEP network device. + * + * @param[in] tcf + * Context object initialized by mlx5_flow_tcf_context_create(). + * @param[in] ifouter + * Outer interface to attach new-created VXLAN device + * If zero the VXLAN device will not be attached to any device. + * @param[in] port + * UDP port of created VTEP device. + * @param[out] error + * Perform verbose error reporting if not NULL. + * + * @return + * Pointer to created device structure on success, NULL otherwise + * and rte_errno is set. + */ +#ifndef HAVE_IFLA_VXLAN_COLLECT_METADATA +static struct mlx5_flow_tcf_vtep* +flow_tcf_create_iface(struct mlx5_flow_tcf_context *tcf __rte_unused, + unsigned int ifouter __rte_unused, + uint16_t port __rte_unused, + struct rte_flow_error *error) +{ + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "netlink: failed to create VTEP, " + "VXLAN metadat is not supported by kernel"); + return NULL; +} +#else +static struct mlx5_flow_tcf_vtep* +flow_tcf_create_iface(struct mlx5_flow_tcf_context *tcf, + unsigned int ifouter, + uint16_t port, struct rte_flow_error *error) +{ + struct mlx5_flow_tcf_vtep *vtep; + struct nlmsghdr *nlh; + struct ifinfomsg *ifm; + char name[sizeof(MLX5_VXLAN_DEVICE_PFX) + 24]; + alignas(struct nlmsghdr) + uint8_t buf[mnl_nlmsg_size(sizeof(*ifm)) + 128 + + SZ_NLATTR_DATA_OF(sizeof(name)) + + SZ_NLATTR_NEST * 2 + + SZ_NLATTR_STRZ_OF("vxlan") + + SZ_NLATTR_DATA_OF(sizeof(uint32_t)) + + SZ_NLATTR_DATA_OF(sizeof(uint32_t)) + + SZ_NLATTR_DATA_OF(sizeof(uint16_t)) + + SZ_NLATTR_DATA_OF(sizeof(uint8_t))]; + struct nlattr *na_info; + struct nlattr *na_vxlan; + rte_be16_t vxlan_port = RTE_BE16(port); + int ret; + + vtep = rte_zmalloc(__func__, sizeof(*vtep), + alignof(struct mlx5_flow_tcf_vtep)); + if (!vtep) { + rte_flow_error_set + (error, ENOMEM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "unadble to allocate memory for VTEP desc"); + return NULL; + } + *vtep = (struct mlx5_flow_tcf_vtep){ + .refcnt = 0, + .port = port, + .created = 0, + .ifouter = 0, + .ifindex = 0, + .local = LIST_HEAD_INITIALIZER(), + .neigh = LIST_HEAD_INITIALIZER(), + }; + memset(buf, 0, sizeof(buf)); + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = RTM_NEWLINK; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; + ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm)); + ifm->ifi_family = AF_UNSPEC; + ifm->ifi_type = 0; + ifm->ifi_index = 0; + ifm->ifi_flags = IFF_UP; + ifm->ifi_change = 0xffffffff; + snprintf(name, sizeof(name), "%s%u", MLX5_VXLAN_DEVICE_PFX, port); + mnl_attr_put_strz(nlh, IFLA_IFNAME, name); + na_info = mnl_attr_nest_start(nlh, IFLA_LINKINFO); + assert(na_info); + mnl_attr_put_strz(nlh, IFLA_INFO_KIND, "vxlan"); + na_vxlan = mnl_attr_nest_start(nlh, IFLA_INFO_DATA); + if (ifouter) + mnl_attr_put_u32(nlh, IFLA_VXLAN_LINK, ifouter); + assert(na_vxlan); + mnl_attr_put_u8(nlh, IFLA_VXLAN_COLLECT_METADATA, 1); + mnl_attr_put_u8(nlh, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, 1); + mnl_attr_put_u8(nlh, IFLA_VXLAN_LEARNING, 0); + mnl_attr_put_u16(nlh, IFLA_VXLAN_PORT, vxlan_port); + mnl_attr_nest_end(nlh, na_vxlan); + mnl_attr_nest_end(nlh, na_info); + assert(sizeof(buf) >= nlh->nlmsg_len); + ret = flow_tcf_nl_ack(tcf, nlh, 0, NULL, NULL); + if (ret) + DRV_LOG(WARNING, + "netlink: VTEP %s create failure (%d)", + name, rte_errno); + else + vtep->created = 1; + if (ret && ifouter) + ret = 0; + else + ret = if_nametoindex(name); + if (ret) { + vtep->ifindex = ret; + vtep->ifouter = ifouter; + memset(buf, 0, sizeof(buf)); + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = RTM_NEWLINK; + nlh->nlmsg_flags = NLM_F_REQUEST; + ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm)); + ifm->ifi_family = AF_UNSPEC; + ifm->ifi_type = 0; + ifm->ifi_index = vtep->ifindex; + ifm->ifi_flags = IFF_UP; + ifm->ifi_change = IFF_UP; + ret = flow_tcf_nl_ack(tcf, nlh, 0, NULL, NULL); + if (ret) { + DRV_LOG(WARNING, + "netlink: VTEP %s set link up failure (%d)", + name, rte_errno); + rte_free(vtep); + rte_flow_error_set + (error, -errno, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "netlink: failed to set VTEP link up"); + vtep = NULL; + } else { + ret = mlx5_flow_tcf_init(tcf, vtep->ifindex, error); + if (ret) + DRV_LOG(WARNING, + "VTEP %s init failure (%d)", name, rte_errno); + } + } else { + DRV_LOG(WARNING, + "VTEP %s failed to get index (%d)", name, errno); + rte_flow_error_set + (error, -errno, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + !vtep->created ? "netlink: failed to create VTEP" : + "netlink: failed to retrieve VTEP ifindex"); + ret = 1; + } + if (ret) { + flow_tcf_delete_iface(tcf, vtep); + vtep = NULL; + } + DRV_LOG(INFO, "VTEP create (%d, %s)", vtep->port, vtep ? "OK" : "error"); + return vtep; +} +#endif /* HAVE_IFLA_VXLAN_COLLECT_METADATA */ + +/** + * Create target interface index for VXLAN tunneling decapsulation. + * In order to share the UDP port within the other interfaces the + * VXLAN device created as not attached to any interface (if created). + * + * @param[in] tcf + * Context object initialized by mlx5_flow_tcf_context_create(). + * @param[in] dev_flow + * Flow tcf object with tunnel structure pointer set. + * @param[out] error + * Perform verbose error reporting if not NULL. + * @return + * Interface index on success, zero otherwise and rte_errno is set. + */ +static unsigned int +flow_tcf_decap_vtep_create(struct mlx5_flow_tcf_context *tcf, + struct mlx5_flow *dev_flow, + struct rte_flow_error *error) +{ + struct mlx5_flow_tcf_vtep *vtep, *vlst; + uint16_t port = dev_flow->tcf.vxlan_decap->udp_port; + + vtep = NULL; + LIST_FOREACH(vlst, &vtep_list_vxlan, next) { + if (vlst->port == port) { + vtep = vlst; + break; + } + } + if (!vtep) { + vtep = flow_tcf_create_iface(tcf, 0, port, error); + if (vtep) + LIST_INSERT_HEAD(&vtep_list_vxlan, vtep, next); + } else { + if (vtep->ifouter) { + rte_flow_error_set(error, -errno, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Failed to create decap VTEP, attached " + "device with the same UDP port exists"); + vtep = NULL; + } + } + if (vtep) { + vtep->refcnt++; + assert(vtep->ifindex); + return vtep->ifindex; + } else { + return 0; + } +} + +/** + * Creates target interface index for VXLAN tunneling encapsulation. + * + * @param[in] tcf + * Context object initialized by mlx5_flow_tcf_context_create(). + * @param[in] ifouter + * Network interface index to attach VXLAN encap device to. + * @param[in] dev_flow + * Flow tcf object with tunnel structure pointer set. + * @param[out] error + * Perform verbose error reporting if not NULL. + * @return + * Interface index on success, zero otherwise and rte_errno is set. + */ +static unsigned int +flow_tcf_encap_vtep_create(struct mlx5_flow_tcf_context *tcf, + unsigned int ifouter, + struct mlx5_flow *dev_flow __rte_unused, + struct rte_flow_error *error) +{ + static uint16_t encap_port = MLX5_VXLAN_PORT_RANGE_MIN - 1; + struct mlx5_flow_tcf_vtep *vtep, *vlst; + + assert(ifouter); + /* Look whether the attached VTEP for encap is created. */ + vtep = NULL; + LIST_FOREACH(vlst, &vtep_list_vxlan, next) { + if (vlst->ifouter == ifouter) { + vtep = vlst; + break; + } + } + if (!vtep) { + uint16_t pcnt; + + /* Not found, we should create the new attached VTEP. */ +/* + * TODO: not implemented yet + * flow_tcf_encap_iface_cleanup(tcf, ifouter); + * flow_tcf_encap_local_cleanup(tcf, ifouter); + * flow_tcf_encap_neigh_cleanup(tcf, ifouter); + */ + for (pcnt = 0; pcnt <= (MLX5_VXLAN_PORT_RANGE_MAX + - MLX5_VXLAN_PORT_RANGE_MIN); pcnt++) { + encap_port++; + /* Wraparound the UDP port index. */ + if (encap_port < MLX5_VXLAN_PORT_RANGE_MIN || + encap_port > MLX5_VXLAN_PORT_RANGE_MAX) + encap_port = MLX5_VXLAN_PORT_RANGE_MIN; + /* Check whether UDP port is in already in use. */ + vtep = NULL; + LIST_FOREACH(vlst, &vtep_list_vxlan, next) { + if (vlst->port == encap_port) { + vtep = vlst; + break; + } + } + if (vtep) { + vtep = NULL; + continue; + } + vtep = flow_tcf_create_iface(tcf, ifouter, + encap_port, error); + if (vtep) { + LIST_INSERT_HEAD(&vtep_list_vxlan, vtep, next); + break; + } + if (rte_errno != EEXIST) + break; + } + } + if (!vtep) + return 0; + vtep->refcnt++; + assert(vtep->ifindex); + return vtep->ifindex; +} + +/** + * Creates target interface index for tunneling of any type. + * + * @param[in] tcf + * Context object initialized by mlx5_flow_tcf_context_create(). + * @param[in] ifouter + * Network interface index to attach VXLAN encap device to. + * @param[in] dev_flow + * Flow tcf object with tunnel structure pointer set. + * @param[out] error + * Perform verbose error reporting if not NULL. + * @return + * Interface index on success, zero otherwise and rte_errno is set. + */ +static unsigned int +flow_tcf_tunnel_vtep_create(struct mlx5_flow_tcf_context *tcf, + unsigned int ifouter, + struct mlx5_flow *dev_flow, + struct rte_flow_error *error) +{ + unsigned int ret; + + assert(dev_flow->tcf.tunnel); + pthread_mutex_lock(&vtep_list_mutex); + switch (dev_flow->tcf.tunnel->type) { + case MLX5_FLOW_TCF_TUNACT_VXLAN_ENCAP: + ret = flow_tcf_encap_vtep_create(tcf, ifouter, + dev_flow, error); + break; + case MLX5_FLOW_TCF_TUNACT_VXLAN_DECAP: + ret = flow_tcf_decap_vtep_create(tcf, dev_flow, error); + break; + default: + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "unsupported tunnel type"); + ret = 0; + break; + } + pthread_mutex_unlock(&vtep_list_mutex); + return ret; +} + +/** + * Deletes tunneling interface by UDP port. + * + * @param[in] tcf + * Context object initialized by mlx5_flow_tcf_context_create(). + * @param[in] ifindex + * Network interface index of VXLAN device. + * @param[in] dev_flow + * Flow tcf object with tunnel structure pointer set. + */ +static void +flow_tcf_tunnel_vtep_delete(struct mlx5_flow_tcf_context *tcf, + unsigned int ifindex, + struct mlx5_flow *dev_flow) +{ + struct mlx5_flow_tcf_vtep *vtep, *vlst; + + assert(dev_flow->tcf.tunnel); + pthread_mutex_lock(&vtep_list_mutex); + vtep = NULL; + LIST_FOREACH(vlst, &vtep_list_vxlan, next) { + if (vlst->ifindex == ifindex) { + vtep = vlst; + break; + } + } + if (!vtep) { + DRV_LOG(WARNING, "No VTEP device found in the list"); + goto exit; + } + switch (dev_flow->tcf.tunnel->type) { + case MLX5_FLOW_TCF_TUNACT_VXLAN_DECAP: + break; + case MLX5_FLOW_TCF_TUNACT_VXLAN_ENCAP: +/* + * TODO: Remove the encap ancillary rules first. + * flow_tcf_encap_neigh(tcf, vtep, dev_flow, false, NULL); + * flow_tcf_encap_local(tcf, vtep, dev_flow, false, NULL); + */ + break; + default: + assert(false); + DRV_LOG(WARNING, "Unsupported tunnel type"); + break; + } + assert(dev_flow->tcf.tunnel->ifindex_tun == vtep->ifindex); + assert(vtep->refcnt); + if (!vtep->refcnt || !--vtep->refcnt) { + LIST_REMOVE(vtep, next); + flow_tcf_delete_iface(tcf, vtep); + } +exit: + pthread_mutex_unlock(&vtep_list_mutex); +} + /** * Apply flow to E-Switch by sending Netlink message. * @@ -3461,18 +3887,61 @@ struct pedit_parser { struct rte_flow_error *error) { struct priv *priv = dev->data->dev_private; - struct mlx5_flow_tcf_context *nl = priv->tcf_context; + struct mlx5_flow_tcf_context *tcf = priv->tcf_context; struct mlx5_flow *dev_flow; struct nlmsghdr *nlh; + int ret; dev_flow = LIST_FIRST(&flow->dev_flows); /* E-Switch flow can't be expanded. */ assert(!LIST_NEXT(dev_flow, next)); + if (dev_flow->tcf.applied) + return 0; nlh = dev_flow->tcf.nlh; nlh->nlmsg_type = RTM_NEWTFILTER; nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; - if (!flow_tcf_nl_ack(nl, nlh, 0, NULL, NULL)) + if (dev_flow->tcf.tunnel) { + /* + * Replace the interface index, target for + * encapsulation, source for decapsulation. + */ + assert(!dev_flow->tcf.tunnel->ifindex_tun); + assert(dev_flow->tcf.tunnel->ifindex_ptr); + /* Create actual VTEP device when rule is being applied. */ + dev_flow->tcf.tunnel->ifindex_tun + = flow_tcf_tunnel_vtep_create(tcf, + *dev_flow->tcf.tunnel->ifindex_ptr, + dev_flow, error); + DRV_LOG(INFO, "Replace ifindex: %d->%d", + dev_flow->tcf.tunnel->ifindex_tun, + *dev_flow->tcf.tunnel->ifindex_ptr); + if (!dev_flow->tcf.tunnel->ifindex_tun) + return -rte_errno; + dev_flow->tcf.tunnel->ifindex_org + = *dev_flow->tcf.tunnel->ifindex_ptr; + *dev_flow->tcf.tunnel->ifindex_ptr + = dev_flow->tcf.tunnel->ifindex_tun; + } + ret = flow_tcf_nl_ack(tcf, nlh, 0, NULL, NULL); + if (dev_flow->tcf.tunnel) { + DRV_LOG(INFO, "Restore ifindex: %d->%d", + dev_flow->tcf.tunnel->ifindex_org, + *dev_flow->tcf.tunnel->ifindex_ptr); + *dev_flow->tcf.tunnel->ifindex_ptr + = dev_flow->tcf.tunnel->ifindex_org; + dev_flow->tcf.tunnel->ifindex_org = 0; + } + if (!ret) { + dev_flow->tcf.applied = 1; return 0; + } + DRV_LOG(WARNING, "netlink: failed to create TC rule (%d)", rte_errno); + if (dev_flow->tcf.tunnel->ifindex_tun) { + flow_tcf_tunnel_vtep_delete(tcf, + dev_flow->tcf.tunnel->ifindex_tun, + dev_flow); + dev_flow->tcf.tunnel->ifindex_tun = 0; + } return rte_flow_error_set(error, rte_errno, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "netlink: failed to create TC flow rule"); @@ -3490,7 +3959,7 @@ struct pedit_parser { flow_tcf_remove(struct rte_eth_dev *dev, struct rte_flow *flow) { struct priv *priv = dev->data->dev_private; - struct mlx5_flow_tcf_context *nl = priv->tcf_context; + struct mlx5_flow_tcf_context *tcf = priv->tcf_context; struct mlx5_flow *dev_flow; struct nlmsghdr *nlh; @@ -3501,10 +3970,36 @@ struct pedit_parser { return; /* E-Switch flow can't be expanded. */ assert(!LIST_NEXT(dev_flow, next)); + if (!dev_flow->tcf.applied) + return; + if (dev_flow->tcf.tunnel) { + /* + * Replace the interface index, target for + * encapsulation, source for decapsulation. + */ + assert(dev_flow->tcf.tunnel->ifindex_tun); + assert(dev_flow->tcf.tunnel->ifindex_ptr); + dev_flow->tcf.tunnel->ifindex_org + = *dev_flow->tcf.tunnel->ifindex_ptr; + *dev_flow->tcf.tunnel->ifindex_ptr + = dev_flow->tcf.tunnel->ifindex_tun; + } nlh = dev_flow->tcf.nlh; nlh->nlmsg_type = RTM_DELTFILTER; nlh->nlmsg_flags = NLM_F_REQUEST; - flow_tcf_nl_ack(nl, nlh, 0, NULL, NULL); + flow_tcf_nl_ack(tcf, nlh, 0, NULL, NULL); + if (dev_flow->tcf.tunnel) { + *dev_flow->tcf.tunnel->ifindex_ptr + = dev_flow->tcf.tunnel->ifindex_org; + dev_flow->tcf.tunnel->ifindex_org = 0; + if (dev_flow->tcf.tunnel->ifindex_tun) { + flow_tcf_tunnel_vtep_delete(tcf, + dev_flow->tcf.tunnel->ifindex_tun, + dev_flow); + dev_flow->tcf.tunnel->ifindex_tun = 0; + } + } + dev_flow->tcf.applied = 0; } /** From patchwork Mon Oct 15 14:13:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slava Ovsiienko X-Patchwork-Id: 46853 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 394194D27; Mon, 15 Oct 2018 16:14:30 +0200 (CEST) Received: from EUR03-AM5-obe.outbound.protection.outlook.com (mail-eopbgr30058.outbound.protection.outlook.com [40.107.3.58]) by dpdk.org (Postfix) with ESMTP id 61E8A23D for ; Mon, 15 Oct 2018 16:14:17 +0200 (CEST) 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=SuIaxMgZcdDZv3giGp2i81AW1llkZ2p6Jinh3UVAQcM=; b=H+RHxzmVlbu/+wW8Fh/dFVDIR1TBo/d04gf1s0fO3taVjIXd+hJG31IGnmk4XjlQKU4fjH6yLg7ONB3XRTQOFQEzL+P5ZGIZVG/AnAz0q1CAIppry5DlnQRWrMWKArPj9mrHQ6Ox7gGGjim+dn1HWnXoYlHlszkrkNScJ1iku9U= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=viacheslavo@mellanox.com; Received: from mellanox.com (37.142.13.130) by VI1PR05MB3277.eurprd05.prod.outlook.com (2603:10a6:802:1c::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1228.24; Mon, 15 Oct 2018 14:14:15 +0000 From: Viacheslav Ovsiienko To: shahafs@mellanox.com, yskoh@mellanox.com Cc: dev@dpdk.org, Viacheslav Ovsiienko Date: Mon, 15 Oct 2018 14:13:34 +0000 Message-Id: <1539612815-47199-7-git-send-email-viacheslavo@mellanox.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1539612815-47199-1-git-send-email-viacheslavo@mellanox.com> References: <1538461807-37507-1-git-send-email-viacheslavo@mellanox.com> <1539612815-47199-1-git-send-email-viacheslavo@mellanox.com> MIME-Version: 1.0 X-Originating-IP: [37.142.13.130] X-ClientProxiedBy: CWLP265CA0084.GBRP265.PROD.OUTLOOK.COM (2603:10a6:401:50::24) To VI1PR05MB3277.eurprd05.prod.outlook.com (2603:10a6:802:1c::22) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 0e3ed0c3-d0a8-4b24-b6e3-08d632a87d4e 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:VI1PR05MB3277; X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 3:CZGSnntHvCoghI3O8NAibVvu6g8ucuxIlry9vJcTLhEM1o1oOqdQurLPttMQ8PjKEqPWLHSfLEfEeHG1fryl417lCS+ZOjM7TOSOWPgK+VJ+mRENXZUFMGCpkOz0JpgneJFNHhx7gjieats1AJrOEx8kc6YUm6ohCa8T9PmWBAjxtyaV4UK2KzRexoAsJsbfr5f0QmPXLjIfP556hmvCmCu6k2hsQaAbif0MzEIC+dSTwgXezGWCJH+FfjW6LXQ6; 25:AtcFwn+OyBb8L026rCZeKt1f7CWanWkqI0dB/cSFxivqMADgjXsMWMBP0UwbKLtsLeb/vfRysaFiALC0tesweqg/QSWaDWy8kehAqT+0GausI9b3mN8VFEg46FHak+W3EJu43TrVwiyEaz/JTGwLC4XFD7/LJEPwzIIdY0g+nUrnEoGTsyL0re+nHV7fwYUYla1tFhj2/e5f6qecblmR0nPkk0hNyPrMLK5Gqe/uBWiZrcSs2rQ0XorMJbtsLxWWgGrqk7kuoHqEvXz/WBgQwpRIL8ZnA0y08NKww4eLXcbLdsiYOKo7xxeVbT9IGJpNgjaoMlNYriWejSG7HoPOmQ==; 31:1l0lsbTDAXc93W4CCmRecau3NPD9/FkYZgWDwjj2vV1KJqu8aNd7tKfw7p11DYL1hWZrSwIcfpeVcdmiQru5BPQgtqGqEiLwUuKW4WKP3BESGzerbLaRBDng0UFwTMhOjPGRt2evr5jFi442fJBoFOZDIHwePKGEnZ/nYzE76ZNEWjPR+xTHmMol/FFv6tzxe4g6mud12FnJ41VUmUo5l1eb/Sn8rIhi0Sduhyub//A= X-MS-TrafficTypeDiagnostic: VI1PR05MB3277: X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 20:Z5ubXnVXT6HBTkUqQaLeqHRLY0qWYNcafVpRb8t6Fe1HJG/WqKtsWvZ+8qgOSxxOVZ6LTpd7lUQT4QXqsncmIKG1CzpCL5IeJMzlCXH2xjxoBVQfXwGb8gkpvgoFagrPgD9WsJ2+0KM6vMaCUyJ4nL7x/JiTqVOZtjVgh/x0Gui6I2PW+HoAHkEml+fQR68QT5NjSjgy21pa2Pw7DC63BkXE77+oJCDcTi5tH5quiySuMplrS/I/x2g5P5Gk08H2l4ktau9na/burxuIl4dFV4pwFe8jLSc/oC5GyFXs1qKcPEebOtOAfRFLJA0w7+eaC3LC1pnAC3joaq6UdvEaX9xOQMN64C5Amxs08kxWlDZZa0TZ2Ocvs8/uverra85p9rJ1bmbvoOtF+QiryXtndM6QVYDpOm9wLElIg3mOZuRQQueophiniOamnl89DWGLpijJfEG0Bc/wu43btkAQwAXx8XHb4CVf0s4df5dH9iK0GrXGiZryHJxcjcbDb+tH; 4:XIgmX/QxAjPFgX1V2etPOliTiwObJkqMpyC3AORBqB5xoXLcx/s+yGeoK/bJ6avTXWwsXbSJNPwsiWbou64mvH5GEwy9AsOYcaXBPQ5DVa73HrokZkM9I49igZ0jrihN1BDLTnLctz1Q5lGf/U6vUAh38F41l/h/6m5fFIc/Ui3rrvr9vBk6T5rB62dE9fPOJCSrBuQSzkhIKu8S6dPBCUPrxWfHjuz3GIoYckFA+V03b+8fYK4eDzbzyqcI/PBgpAWyac++iKptunbDC/jvBAervncKu7+gDvNeXZgiER5QVexRdBPKj8ouPardtanu X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(211171220733660); X-MS-Exchange-SenderADCheck: 1 X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(3002001)(3231355)(944501410)(52105095)(10201501046)(93006095)(93001095)(6055026)(149066)(150057)(6041310)(20161123560045)(20161123558120)(20161123562045)(20161123564045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(201708071742011)(7699051); SRVR:VI1PR05MB3277; BCL:0; PCL:0; RULEID:; SRVR:VI1PR05MB3277; X-Forefront-PRVS: 0826B2F01B X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(136003)(39860400002)(376002)(346002)(366004)(396003)(199004)(189003)(107886003)(16526019)(66066001)(7736002)(8676002)(47776003)(106356001)(51416003)(7696005)(52116002)(25786009)(68736007)(105586002)(186003)(16586007)(305945005)(8936002)(3846002)(81166006)(81156014)(6116002)(386003)(50226002)(6666004)(50466002)(11346002)(5024004)(86362001)(14444005)(446003)(76176011)(97736004)(6636002)(21086003)(36756003)(2906002)(33026002)(4720700003)(69596002)(53936002)(55016002)(48376002)(85306007)(478600001)(476003)(8886007)(316002)(26005)(4326008)(4744004)(486006)(2616005)(5660300001)(956004); DIR:OUT; SFP:1101; SCL:1; SRVR:VI1PR05MB3277; H:mellanox.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-Exchange-Diagnostics: =?us-ascii?Q?1; VI1PR05MB3277; 23:36TxnZo1ipgM8F2xtNAPP9dTt7G1WyjCryuP3YId4?= OchAm2xJwgbLNC1iN2WZvU7dtFicLptydTj6Tm3DPxv2zz77yDaP1lVO5O/V5E5Yr3ma2iibJVf4NiHs9T46ZWZ2WcyZC8xvuchAGlD0XJQctLfcDCexfxCpfyun+1oT/9wEk2+Z3OdqtM0y3n0peHE+9wVNJ/YpVdkBtzv6PPaFL3zE/Nlsa9yJ/2ZVTev+rq4sTWRDXYiaH+IhnbSNtdO+hDb+SsTb3BqSAJyJLW2R75HpMl9q+Lk4L2/bkE2j1pTsrqowJPGYgfizw/76c5sVOxqrXyChjlZ0mEVy2JNyv1/hxGGFWAIHv8pqRNHJMPtIHeVE+cPIK8k8aGTU2A5KJ6R/VlAMdgqEUIvY45UO5xbbariRTy1tb+ObTDcBqHT8+4q//DMMqwqcX6p9XfvHZ8tJ7QamJg4LD9lp3omk3GnMfLbDWZlcakCfd5i/+BLi3hnDpnKjh2XJnywRI36Mt2vpGv/rTeG/WvsYdpgfq/mt20Ms76PNgGdftn/cTrFUVo/BEAPRbgQ09mrSFG0Hk4ankAI3/I/nNB9+/waLCT4M3+GPgo+N2XsWF96sPVfTAfwg06dTcYLR6R3nHmXTkKlHkBfO9nC9gWqrxSWximiaoYSn3438IxvPTAJBzTICxkXPwkgq9d4445EzgNng31UFo4S/QdC/oxc33Kx0nZNQ1F+aDfQJyZajrLpm9REr/cUqBzZk0qIfDDakc/LAfTujxP7TrYwkPikYz1r9Yqw+3vtitoMAljeIyY6on6HjfLhdJSaLmYRuNNlvyO9Vvz+hOxLLxUjYkrsgZcC+cGv7oqQxVtsCswkO10ZAPPT4HsafPoXkBDmTBh6YXWhPc3K6djdYHN+EGqDk1V+kx+4tCHpbBBppQxKCHedoc98IZtkpMTpPjhSs1G7yyItJTKKHHVrFs7Hde3iaBE2hvw96HsfaB1X+zjcXI4Fw+b5l7Moz8ruqWM43msXKVFdGRqOjykO920bCrulGZIjlIuAlv9HtA3pBJEvvICmtlFlHgi5roLs9U5UDdvk3y3XZWkd0EiH0GYVY2I7t8u0Pd2HQjo8PMAgtRIhr1mEkGLbwNPhlPS4W0ymEpWA6tvD1SmYUuw/vQhVKfqzoExDll/7KqkEhF07CXuim+YCOC9Ae7tKi8DHez0UX95afkFW1FVTxS7/3XeVEAXEPYiJkZ7XQaq5VgHMejTrmeUa4emzQlVM5KGuyrfBg0TtBVEESIjlXoT+vJtGuVsN9/xj6KyMn3HELsY0OsW4TXZ1jpI69eKf+AHirApVCwlEpEQoGG5e4VEsItIb0EjmpANxug== X-Microsoft-Antispam-Message-Info: Rd47uO7+KpgvzgzTy32+0qWldAvtYRvrGmSy843AYC6WUKmhbsuqzgnajIJdcpURSKqGVEtpCoL2S3gvXySodkGj9B0S7yE/6vYQBP+VsrLlbwu2YkKJXtwQpgXEYDhfIEekEHz0zJTGMgpgkvOkz4q3I6SJsePn1N1rDLca5KUqswnkL8Maa0TLeRJLaYjfoowy/A2SlRWxb2l0jiDny4eJI7l0r8zni+o2S9FkkKqsMZN+9U0FbuqfbvEWUTfPev/IGXU1kWPWKZmk6osEDAhxW1PXQY90nTgmwd2rr4HSE0bxn7EegdouaLzepvVaCtUT3W2qSwf+ZrpSoPvyemjf3Ur4uepu/oTh+4KFK5Q= X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 6:1uVh04fmTl1/YaKbKdyBhbSl+xVu7fzpjgKu+klD/jfHuxJloUvSW/VnLwSyB9NgqtSqTQhTpl8d8iI1RJ9a8StSq9Jf/dnXiBROVyfHb5no7oDRryhmAXjDwaFW5V0h+/0fHkOp7pKyCMkgFQE1zdr17Ej8FodXP083Rv7FEc+as3qQgl9PAfOYIiYY9Rds04iF6y6qzGHUvU+0Au/TF3YlFB5xWRWEK9flyX0RPbPsi+mU+9fF+UFMou22d7AsswWxnIbUFmbQGv1M1Qv5jfDThuvoPd4Ht0VqiRoF9q/0kGZXHH1gyEvuxdTkg/BHQYZebU8R7FTV3nCzeIwrVAf1MkA8Tt95ZDtXEwkDlFsxed1cc8zNWdmpU2yzTZfg557yhRMYTmlEhxCzYatHJXGVC4yz5emgn0xTHcu7gydCNrTjaNZRoXwOQblyv1N51OmcbF1nI9Bj4LuIrruwfw==; 5:IuZY/d3X8nkiG/2RzgTFJC5LF0ytg5UzwD7brMG+rx29/FRVnsYWwmaVy06mH85ojy5eFePHBG3U3i8hh63cTqSlacxbvBFNFXVeYI9A3IftEoddzKfSj2FRmii7PEC/v/5Us9Ek/4LnoaHw9+ziU0jHtOs3yFKJLfeyWKCjhLI=; 7:rpF6GnaTDBLb8KgWSdF7US5BATfUmAznYfxA+IfoPt6dDKjDJBsWQxkGFR6g5SiaZjM+PN6snuiNm+EzvtqKFvpP/ElLUVwJXq2w7AXetQ7q6kLScXkGbkYENoWKe8opDbW+Y4AfuSHMsT2uPhNz57Hz8eFDyjTJ6YlCD5v5Gp4SwfJCN04vHbpD/O5CwwiBPzpmN3UgiK6uk6lW4+PWZoJo6gMfhsXM0zModkJH7/oyO1OV5cuOX64RAPmrTSmi SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Oct 2018 14:14:15.1146 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 0e3ed0c3-d0a8-4b24-b6e3-08d632a87d4e X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR05MB3277 Subject: [dpdk-dev] [PATCH v2 6/7] net/mlx5: e-switch VXLAN encapsulation rules management 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" VXLAN encap rules are applied to the VF ingress traffic and have the VTEP as actual redirection destinations instead of outer PF. The encapsulation rule should provide: - redirection action VF->PF - VF port ID - some inner network parameters (MACs/IP) - the tunnel outer source IP (v4/v6) - the tunnel outer destination IP (v4/v6). Current - VNI - Virtual Network Identifier There is no direct way found to provide kernel with all required encapsulatioh header parameters. The encapsulation VTEP is created attached to the outer interface and assumed as default path for egress encapsulated traffic. The outer tunnel IP address are assigned to interface using Netlink, the implicit route is created like this: ip addr add peer dev scope link Peer address provides implicit route, and scode link reduces the risk of conflicts. At initialization time all local scope link addresses are flushed from device (see next part of patchset). The destination MAC address is provided via permenent neigh rule: ip neigh add dev lladdr to nud permanent At initialization time all neigh rules of this type are flushed from device (see the next part of patchset). Suggested-by: Adrien Mazarguil Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_flow_tcf.c | 394 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 389 insertions(+), 5 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_tcf.c b/drivers/net/mlx5/mlx5_flow_tcf.c index efa9c3b..a1d7733 100644 --- a/drivers/net/mlx5/mlx5_flow_tcf.c +++ b/drivers/net/mlx5/mlx5_flow_tcf.c @@ -3443,6 +3443,376 @@ struct pedit_parser { return -err; } +/** + * Emit Netlink message to add/remove local address to the outer device. + * The address being added is visible within the link only (scope link). + * + * Note that an implicit route is maintained by the kernel due to the + * presence of a peer address (IFA_ADDRESS). + * + * These rules are used for encapsultion only and allow to assign + * the outer tunnel source IP address. + * + * @param[in] tcf + * Libmnl socket context object. + * @param[in] encap + * Encapsulation properties (source address and its peer). + * @param[in] ifindex + * Network interface to apply rule. + * @param[in] enable + * Toggle between add and remove. + * @param[out] error + * Perform verbose error reporting if not NULL. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +static int +flow_tcf_rule_local(struct mlx5_flow_tcf_context *tcf, + const struct mlx5_flow_tcf_vxlan_encap *encap, + unsigned int ifindex, + bool enable, + struct rte_flow_error *error) +{ + struct nlmsghdr *nlh; + struct ifaddrmsg *ifa; + alignas(struct nlmsghdr) + uint8_t buf[mnl_nlmsg_size(sizeof(*ifa) + 128)]; + + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = enable ? RTM_NEWADDR : RTM_DELADDR; + nlh->nlmsg_flags = + NLM_F_REQUEST | (enable ? NLM_F_CREATE | NLM_F_REPLACE : 0); + nlh->nlmsg_seq = 0; + ifa = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifa)); + ifa->ifa_flags = IFA_F_PERMANENT; + ifa->ifa_scope = RT_SCOPE_LINK; + ifa->ifa_index = ifindex; + if (encap->mask & MLX5_FLOW_TCF_ENCAP_IPV4_SRC) { + ifa->ifa_family = AF_INET; + ifa->ifa_prefixlen = 32; + mnl_attr_put_u32(nlh, IFA_LOCAL, encap->ipv4.src); + if (encap->mask & MLX5_FLOW_TCF_ENCAP_IPV4_DST) + mnl_attr_put_u32(nlh, IFA_ADDRESS, + encap->ipv4.dst); + } else { + assert(encap->mask & MLX5_FLOW_TCF_ENCAP_IPV6_SRC); + ifa->ifa_family = AF_INET6; + ifa->ifa_prefixlen = 128; + mnl_attr_put(nlh, IFA_LOCAL, + sizeof(encap->ipv6.src), + &encap->ipv6.src); + if (encap->mask & MLX5_FLOW_TCF_ENCAP_IPV6_DST) + mnl_attr_put(nlh, IFA_ADDRESS, + sizeof(encap->ipv6.dst), + &encap->ipv6.dst); + } + if (!flow_tcf_nl_ack(tcf, nlh, 0, NULL, NULL)) + return 0; + return rte_flow_error_set + (error, rte_errno, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "netlink: cannot complete IFA request (ip addr add)"); +} + +/** + * Emit Netlink message to add/remove neighbor. + * + * @param[in] tcf + * Libmnl socket context object. + * @param[in] encap + * Encapsulation properties (destination address). + * @param[in] ifindex + * Network interface. + * @param[in] enable + * Toggle between add and remove. + * @param[out] error + * Perform verbose error reporting if not NULL. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +static int +flow_tcf_rule_neigh(struct mlx5_flow_tcf_context *tcf, + const struct mlx5_flow_tcf_vxlan_encap *encap, + unsigned int ifindex, + bool enable, + struct rte_flow_error *error) +{ + struct nlmsghdr *nlh; + struct ndmsg *ndm; + alignas(struct nlmsghdr) + uint8_t buf[mnl_nlmsg_size(sizeof(*ndm) + 128)]; + + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = enable ? RTM_NEWNEIGH : RTM_DELNEIGH; + nlh->nlmsg_flags = + NLM_F_REQUEST | (enable ? NLM_F_CREATE | NLM_F_REPLACE : 0); + nlh->nlmsg_seq = 0; + ndm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ndm)); + ndm->ndm_ifindex = ifindex; + ndm->ndm_state = NUD_PERMANENT; + ndm->ndm_flags = 0; + ndm->ndm_type = 0; + if (encap->mask & MLX5_FLOW_TCF_ENCAP_IPV4_DST) { + ndm->ndm_family = AF_INET; + mnl_attr_put_u32(nlh, NDA_DST, encap->ipv4.dst); + } else { + assert(encap->mask & MLX5_FLOW_TCF_ENCAP_IPV6_DST); + ndm->ndm_family = AF_INET6; + mnl_attr_put(nlh, NDA_DST, sizeof(encap->ipv6.dst), + &encap->ipv6.dst); + } + if (encap->mask & MLX5_FLOW_TCF_ENCAP_ETH_SRC && enable) + DRV_LOG(WARNING, + "Outer ethernet source address cannot be " + "forced for VXLAN encapsulation"); + if (encap->mask & MLX5_FLOW_TCF_ENCAP_ETH_DST) + mnl_attr_put(nlh, NDA_LLADDR, sizeof(encap->eth.dst), + &encap->eth.dst); + if (!flow_tcf_nl_ack(tcf, nlh, 0, NULL, NULL)) + return 0; + return rte_flow_error_set + (error, rte_errno, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "netlink: cannot complete ND request (ip neigh)"); +} + +/** + * Manage the local IP addresses and their peers IP addresses on the + * outer interface for encapsulation purposes. The kernel searches the + * appropriate device for tunnel egress traffic using the outer source + * IP, this IP should be assigned to the outer network device, otherwise + * kernel rejects the rule. + * + * Adds or removes the addresses using the Netlink command like this: + * ip addr add peer scope link dev + * + * The addresses are local to the netdev ("scope link"), this reduces + * the risk of conflicts. Note that an implicit route is maintained by + * the kernel due to the presence of a peer address (IFA_ADDRESS). + * + * @param[in] tcf + * Libmnl socket context object. + * @param[in] vtep + * VTEP object, contains rule database and ifouter index. + * @param[in] dev_flow + * Flow object, contains the tunnel parameters (for encap only). + * @param[in] enable + * Toggle between add and remove. + * @param[out] error + * Perform verbose error reporting if not NULL. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +static int +flow_tcf_encap_local(struct mlx5_flow_tcf_context *tcf, + struct mlx5_flow_tcf_vtep *vtep, + struct mlx5_flow *dev_flow, + bool enable, + struct rte_flow_error *error) +{ + const struct mlx5_flow_tcf_vxlan_encap *encap = + dev_flow->tcf.vxlan_encap; + struct tcf_local_rule *rule; + bool found = false; + int ret; + + assert(encap); + assert(encap->hdr.type == MLX5_FLOW_TCF_TUNACT_VXLAN_ENCAP); + if (encap->mask & MLX5_FLOW_TCF_ENCAP_IPV4_SRC) { + assert(encap->mask & MLX5_FLOW_TCF_ENCAP_IPV4_DST); + LIST_FOREACH(rule, &vtep->local, next) { + if (rule->mask & MLX5_FLOW_TCF_ENCAP_IPV4_SRC && + encap->ipv4.src == rule->ipv4.src && + encap->ipv4.dst == rule->ipv4.dst) { + found = true; + break; + } + } + } else { + assert(encap->mask & MLX5_FLOW_TCF_ENCAP_IPV6_SRC); + assert(encap->mask & MLX5_FLOW_TCF_ENCAP_IPV6_DST); + LIST_FOREACH(rule, &vtep->local, next) { + if (rule->mask & MLX5_FLOW_TCF_ENCAP_IPV6_SRC && + !memcmp(&encap->ipv6.src, &rule->ipv6.src, + sizeof(encap->ipv6.src)) && + !memcmp(&encap->ipv6.dst, &rule->ipv6.dst, + sizeof(encap->ipv6.dst))) { + found = true; + break; + } + } + } + if (found) { + if (enable) { + rule->refcnt++; + return 0; + } + if (!rule->refcnt || !--rule->refcnt) { + LIST_REMOVE(rule, next); + return flow_tcf_rule_local(tcf, encap, + vtep->ifouter, false, error); + } + return 0; + } + if (!enable) { + DRV_LOG(WARNING, "Disabling not existing local rule"); + rte_flow_error_set + (error, ENOENT, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "Disabling not existing local rule"); + return -ENOENT; + } + rule = rte_zmalloc(__func__, sizeof(struct tcf_local_rule), + alignof(struct tcf_local_rule)); + if (!rule) { + rte_flow_error_set + (error, ENOMEM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "unable to allocate memory for local rule"); + return -rte_errno; + } + *rule = (struct tcf_local_rule){.refcnt = 0, + .mask = 0, + }; + if (encap->mask & MLX5_FLOW_TCF_ENCAP_IPV4_SRC) { + rule->mask = MLX5_FLOW_TCF_ENCAP_IPV4_SRC + | MLX5_FLOW_TCF_ENCAP_IPV4_DST; + rule->ipv4.src = encap->ipv4.src; + rule->ipv4.dst = encap->ipv4.dst; + } else { + rule->mask = MLX5_FLOW_TCF_ENCAP_IPV6_SRC + | MLX5_FLOW_TCF_ENCAP_IPV6_DST; + memcpy(&rule->ipv6.src, &encap->ipv6.src, + sizeof(rule->ipv6.src)); + memcpy(&rule->ipv6.dst, &encap->ipv6.dst, + sizeof(rule->ipv6.dst)); + } + ret = flow_tcf_rule_local(tcf, encap, vtep->ifouter, true, error); + if (ret) { + rte_free(rule); + return ret; + } + rule->refcnt++; + LIST_INSERT_HEAD(&vtep->local, rule, next); + return 0; +} + +/** + * Manage the destination MAC/IP addresses neigh database, kernel uses + * this one to determine the destination MAC address within encapsulation + * header. Adds or removes the entries using the Netlink command like this: + * ip neigh add dev lladdr to nud permanent + * + * @param[in] tcf + * Libmnl socket context object. + * @param[in] vtep + * VTEP object, contains rule database and ifouter index. + * @param[in] dev_flow + * Flow object, contains the tunnel parameters (for encap only). + * @param[in] enable + * Toggle between add and remove. + * @param[out] error + * Perform verbose error reporting if not NULL. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +static int +flow_tcf_encap_neigh(struct mlx5_flow_tcf_context *tcf, + struct mlx5_flow_tcf_vtep *vtep, + struct mlx5_flow *dev_flow, + bool enable, + struct rte_flow_error *error) +{ + const struct mlx5_flow_tcf_vxlan_encap *encap = + dev_flow->tcf.vxlan_encap; + struct tcf_neigh_rule *rule; + bool found = false; + int ret; + + assert(encap); + assert(encap->hdr.type == MLX5_FLOW_TCF_TUNACT_VXLAN_ENCAP); + if (encap->mask & MLX5_FLOW_TCF_ENCAP_IPV4_DST) { + assert(encap->mask & MLX5_FLOW_TCF_ENCAP_IPV4_SRC); + LIST_FOREACH(rule, &vtep->neigh, next) { + if (rule->mask & MLX5_FLOW_TCF_ENCAP_IPV4_DST && + encap->ipv4.dst == rule->ipv4.dst) { + found = true; + break; + } + } + } else { + assert(encap->mask & MLX5_FLOW_TCF_ENCAP_IPV6_SRC); + assert(encap->mask & MLX5_FLOW_TCF_ENCAP_IPV6_DST); + LIST_FOREACH(rule, &vtep->neigh, next) { + if (rule->mask & MLX5_FLOW_TCF_ENCAP_IPV6_DST && + !memcmp(&encap->ipv6.dst, &rule->ipv6.dst, + sizeof(encap->ipv6.dst))) { + found = true; + break; + } + } + } + if (found) { + if (memcmp(&encap->eth.dst, &rule->eth, + sizeof(encap->eth.dst))) { + DRV_LOG(WARNING, "Destination MAC differs" + " in neigh rule"); + rte_flow_error_set(error, EEXIST, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "Different MAC address" + " neigh rule for the same" + " destination IP"); + return -EEXIST; + } + if (enable) { + rule->refcnt++; + return 0; + } + if (!rule->refcnt || !--rule->refcnt) { + LIST_REMOVE(rule, next); + return flow_tcf_rule_neigh(tcf, encap, + vtep->ifouter, + false, error); + } + return 0; + } + if (!enable) { + DRV_LOG(WARNING, "Disabling not existing neigh rule"); + rte_flow_error_set + (error, ENOENT, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "unable to allocate memory for neigh rule"); + return -ENOENT; + } + rule = rte_zmalloc(__func__, sizeof(struct tcf_neigh_rule), + alignof(struct tcf_neigh_rule)); + if (!rule) { + rte_flow_error_set + (error, ENOMEM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "unadble to allocate memory for neigh rule"); + return -rte_errno; + } + *rule = (struct tcf_neigh_rule){.refcnt = 0, + .mask = 0, + }; + if (encap->mask & MLX5_FLOW_TCF_ENCAP_IPV4_DST) { + rule->mask = MLX5_FLOW_TCF_ENCAP_IPV4_DST; + rule->ipv4.dst = encap->ipv4.dst; + } else { + rule->mask = MLX5_FLOW_TCF_ENCAP_IPV6_DST; + memcpy(&rule->ipv6.dst, &encap->ipv6.dst, + sizeof(rule->ipv6.dst)); + } + memcpy(&rule->eth, &encap->eth.dst, sizeof(rule->eth)); + ret = flow_tcf_rule_neigh(tcf, encap, vtep->ifouter, true, error); + if (ret) { + rte_free(rule); + return ret; + } + rule->refcnt++; + LIST_INSERT_HEAD(&vtep->neigh, rule, next); + return 0; +} + /* VTEP device list is shared between PMD port instances. */ static LIST_HEAD(, mlx5_flow_tcf_vtep) vtep_list_vxlan = LIST_HEAD_INITIALIZER(); @@ -3715,6 +4085,7 @@ static LIST_HEAD(, mlx5_flow_tcf_vtep) { static uint16_t encap_port = MLX5_VXLAN_PORT_RANGE_MIN - 1; struct mlx5_flow_tcf_vtep *vtep, *vlst; + int ret; assert(ifouter); /* Look whether the attached VTEP for encap is created. */ @@ -3766,6 +4137,21 @@ static LIST_HEAD(, mlx5_flow_tcf_vtep) } if (!vtep) return 0; + /* Create local ipaddr with peer to specify the outer IPs. */ + ret = flow_tcf_encap_local(tcf, vtep, dev_flow, true, error); + if (ret) { + if (!vtep->refcnt) + flow_tcf_delete_iface(tcf, vtep); + return 0; + } + /* Create neigh rule to specify outer destination MAC. */ + ret = flow_tcf_encap_neigh(tcf, vtep, dev_flow, true, error); + if (ret) { + flow_tcf_encap_local(tcf, vtep, dev_flow, false, error); + if (!vtep->refcnt) + flow_tcf_delete_iface(tcf, vtep); + return 0; + } vtep->refcnt++; assert(vtep->ifindex); return vtep->ifindex; @@ -3848,11 +4234,9 @@ static LIST_HEAD(, mlx5_flow_tcf_vtep) case MLX5_FLOW_TCF_TUNACT_VXLAN_DECAP: break; case MLX5_FLOW_TCF_TUNACT_VXLAN_ENCAP: -/* - * TODO: Remove the encap ancillary rules first. - * flow_tcf_encap_neigh(tcf, vtep, dev_flow, false, NULL); - * flow_tcf_encap_local(tcf, vtep, dev_flow, false, NULL); - */ + /* Remove the encap ancillary rules first. */ + flow_tcf_encap_neigh(tcf, vtep, dev_flow, false, NULL); + flow_tcf_encap_local(tcf, vtep, dev_flow, false, NULL); break; default: assert(false); From patchwork Mon Oct 15 14:13:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slava Ovsiienko X-Patchwork-Id: 46854 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 F081D2BD3; Mon, 15 Oct 2018 16:14:49 +0200 (CEST) Received: from EUR03-AM5-obe.outbound.protection.outlook.com (mail-eopbgr30055.outbound.protection.outlook.com [40.107.3.55]) by dpdk.org (Postfix) with ESMTP id 890A123D for ; Mon, 15 Oct 2018 16:14:18 +0200 (CEST) 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=FMz9bL9h81oH6gctwHSOJhnSQNcukl+3mVSVnkke5/4=; b=xMHLpY7c0iUuvDM/Cott0vFGCPiyArQJ/RK3Fjfdf/NdK59ygqXCJjcAdGLfk0ZGZAI5m3EB14Mv12no2S1ZluL/U7BFXCuDFMGBwVvDPiu996wvgzvfW1BSGVMbSgH2vtxQj9OK1G6xZSGmCTS4Pr4K8duZsJfo1ElgMqxpxKA= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=viacheslavo@mellanox.com; Received: from mellanox.com (37.142.13.130) by VI1PR05MB3277.eurprd05.prod.outlook.com (2603:10a6:802:1c::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1228.24; Mon, 15 Oct 2018 14:14:16 +0000 From: Viacheslav Ovsiienko To: shahafs@mellanox.com, yskoh@mellanox.com Cc: dev@dpdk.org, Viacheslav Ovsiienko Date: Mon, 15 Oct 2018 14:13:35 +0000 Message-Id: <1539612815-47199-8-git-send-email-viacheslavo@mellanox.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1539612815-47199-1-git-send-email-viacheslavo@mellanox.com> References: <1538461807-37507-1-git-send-email-viacheslavo@mellanox.com> <1539612815-47199-1-git-send-email-viacheslavo@mellanox.com> MIME-Version: 1.0 X-Originating-IP: [37.142.13.130] X-ClientProxiedBy: CWLP265CA0084.GBRP265.PROD.OUTLOOK.COM (2603:10a6:401:50::24) To VI1PR05MB3277.eurprd05.prod.outlook.com (2603:10a6:802:1c::22) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 7a3322da-1adb-4556-e821-08d632a87e41 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:VI1PR05MB3277; X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 3:3ba8nNQO+RPDoRjLgGH/DKYRhbNyI0wpSpsEZvzNVAovegG0RHS0oc9xu1fPyKF/H2+JgOR5FsQLnRoiEUf50g6/WuI9HcVu9G7JhsMWVOlJFsiTjoDZ88WVi2lOy9FnmkjfDhTmlltVLi0EqGSz+Z+Zg2/22Jcrx3xEpCM33Z5XKBF6mgHhYVE/WRhOtRCnrHWZEJtyVxr2hMQvEwTKvwFthcI1WC/69hWopRn8ndj/2isS4qv8Sg8p8YCl78Gr; 25:iK7mprLcxvqeWkNihY/tad4ltNBvC4SV4/Zu0nPpoVDSDTHIxZZZoSx03/YbbcbFzxGw3GZxM1XGpIwV7HjLuHAlKU2NEWQ7RE9puk2Lej/q0orP4OKHhoeG8gLY73ZctuKY91fJCGYsKeZupqyz7l7KdON/ifxcazYSQjtn99M//M6ajNu+Obt2Cd+AN/H2/KYY0+uVdJ3ehiykVwQNPMT2b2mpmyPByN6oNGyRRN2raR7FZfaqdaEzHr/5qVOWGtLtDJ0BWD0CbobQrJ/hHiQTtMAbwlt2CIHVnKETL5l/Vakpf9Mdgs1ROKliJrDToP6c/smpa5qotmmKbn6RMQ==; 31:BUwJ4gr0JVwT2ZlSz9qD6JNABrxaCbB6L+M5pJ3HLcbx5+s4gH6x0PCwt1lqi5SdjhyTkCs7SqxXbF8+/iK5iz3uhIsY8kvXLqMsaujqwFBiXRLNEJtmgjD/oh/H0hCsI4vimvCH+TPvlBEq0KozUfykQsTvuprdSShXHE1dlB5pcIQ9O/lny1SVIFZNqbUExawMHdIwajW1ANn2eKGDBhvSZmIRAr1BifaPShnAx2I= X-MS-TrafficTypeDiagnostic: VI1PR05MB3277: X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 20:wkXmL2Rp8gX0qm+17P+mGhUzgRxuPr0JjaBbh+QBrZxJjZTVP20nXv7oFVc39chpn0JoiMbRMniGFrYlMK78zqtSBDfg9rmhzAjBERAFypozHksk3zaN4sxdYlkKfC++vZwq7AXS+YmosCcQbdg6N5ZvqFIkOulPHCbdck2mz8vBIMC5Cr+EBY6l1VzeW6cYDVrDEOfe8EToXIEXqDnX/XaJkHei6SHqizF5UPWhL1AkbSupxNu8fO/bT3Tl8IvIKKthSNHcDHguHS/Twon52tSZxevIpBEIGsCih1PGLCyWWxbNnb57jYPMXwkbnKVpCL66Kf+LslXfufP9MOKaeg1aZ8NTbCN6oYPK1Yc7Au06IBA02KyDCzjsFcPUL6izbxhuAfSkdhVfhQsMCle8PUyImNjbtB0bn2FM/Mb9zAVRSbuVYQihi4VjzlBZ6Mc+OgMj8Qp+wN5IyHKbdLwKLG/MSCwOsJhh+SSWKiWyDOh5QA4vQHPWqszRPwldhfRx; 4:LGgbC9Uy6idHqIJjRlUrG7utcYqB27vmqEil7GhmEGkT7SmMX2y1ZrzdkgxqCro3M2tXbGPFM697KvxAo98IIANHfPImIbviX6BLBcLr8Kv7hWs7n3ZiFbPW7lpmrIa3/8EH8Qhe8QglqAqxENhiiB09rpjRowUuQjBEZgv5dm3QBnTrXbJDGbSylijvs3E/CZRWzxv6PLrrBlDiCIzCKNaFRs682yMV7RaxWds7PlCGVxL0izOy8Sm+7+5b1diqnmcL20V6AtDtAsJxnbCq7A== 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)(3002001)(3231355)(944501410)(52105095)(10201501046)(93006095)(93001095)(6055026)(149066)(150057)(6041310)(20161123560045)(20161123558120)(20161123562045)(20161123564045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(201708071742011)(7699051); SRVR:VI1PR05MB3277; BCL:0; PCL:0; RULEID:; SRVR:VI1PR05MB3277; X-Forefront-PRVS: 0826B2F01B X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(136003)(39860400002)(376002)(346002)(366004)(396003)(199004)(189003)(107886003)(16526019)(66066001)(7736002)(8676002)(47776003)(106356001)(51416003)(7696005)(52116002)(25786009)(68736007)(105586002)(186003)(16586007)(305945005)(8936002)(3846002)(81166006)(81156014)(6116002)(386003)(50226002)(6666004)(50466002)(11346002)(5024004)(86362001)(14444005)(446003)(76176011)(97736004)(6636002)(21086003)(36756003)(2906002)(33026002)(4720700003)(69596002)(53936002)(55016002)(48376002)(85306007)(478600001)(476003)(8886007)(316002)(26005)(4326008)(4744004)(486006)(2616005)(5660300001)(956004)(21314002); DIR:OUT; SFP:1101; SCL:1; SRVR:VI1PR05MB3277; H:mellanox.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-Exchange-Diagnostics: =?us-ascii?Q?1; VI1PR05MB3277; 23:1GEl2zqjT9j4VXBEDokG3zZJUbjiuIGmHYSubylom?= NLYQBUVvvBVT7Z2QTV5sz9NYCxLY8zDUKuSuykvpuckKayJ7dLGoxCyaFTqu9Z/jcDT4OjfwYacXxAwtMheWdNJlDF7Y7W2tBkimkVCzT5V9PD6XeR6uSPztahwJ94gOi9NFF9UZ65niWXm28ZnY94V0B8Hrb+XqqDGD8IvFb3Wu6TxZ+iBAHGwbkvNcOqDw2Rzh5+aX7kDZ088whtKne9b/2QfLl/J8NYFSzrQJwoYQuiG+WZ/lCHqVX/8ujnX6dwMq6iXeXgchTiYUcoiWnLsta+ba7Ha2fvSSi5q3sG+IdVpj+rse+xHTiCLuzgi0Z1D5s567cGy2UvLjEP6JWqRdUSJlkMKbahq3dA3+X1I3YG//Dy6MxNv9QxPZsTNTR1nhX/O++674Tv8YmzwkOKTSaGdUCiXc03eAIw8pM8MMA8d37MglTSk6PxeI1MlPdN3zoSr5QPNuioZXhA98MfdIfIRkXtgMPqeItpXPZndEbQQqZFi5X/P2X0sbVJamw+HNoD6Auv3q+vlYXmWJfka1xULBZqlGL4Sj6YdDwIqzpj8/3iczH9b0Z0juWpGouDh9lv32SNNTchm/jZfpb0IKDbWEHD2S4mj5zSHqC0Foj9hYtGMEF7NfApnyWoZ1iF7k4anMLg3CqAJmNCvllPWURdT6TLp7EFOQd6jsMOk87JjyI2Wuvex5zQofZsOYKagyeGuYGDdAaDrzLwksTlZi6RBHwVqQRYlVS/cqEGI5EMk8ZplL9P6RKOkLHPU0kVaGX3wv3JzrMc6bgIgajnFmghoSeSmOaLTX+qP2Ic0S1mlI5h9UIA3Ri7r2n7XbvtGABjRhx1fUM1wY9Q2wk46yEdZIGLNtStNpIgASUFW0pAwns+wZ2GIUq4w/2Zg7b6VXYmifVsrUAPsy6Yz+xITln8Oajg50C7nph5cF2Ox/d2xOiCfOiE120ie3JufWGNGCQD20UJdX0rXKmMAty5XXhdCl1WTPeaufxN4gACz7KOHlJsFLssG3uStJnoYTlqoEMNBGtpaSnotjXmf/YHRvgc7XgGwQDXko0SESZeSM0/h6NQsls9ZaE4hceVIQMCe3z2E4pXXJ+zMaZ4klkJSzS8AIe3TK5KQqBEKEGgWbQ+UBWOzsVROAZwAF/KY3TU5/pCDi6+jJtg9vjJmkDol78hBwTLCJaNAd1zKzdhQGVkyYqDG1tDJU+zBkbPNt3lVKaxrIcLfEwc4McwZngbJIxKFBUClM1K4p4Ohl2W2NKmB63C7yOsrsUhCLuksHPIodZsi8ptaaf7Nnvgfyo3n+UG/uMJdskP9cHDJeeBXxZ1bjKf98WURq1KZ6K3FWBc= X-Microsoft-Antispam-Message-Info: hVTKD8eBQJqndvZNLZp7fhxYjH3mB36tSXtMBRberpHx6fEqT1lX2CwdgCHURAGNF6GbhUVv8GYFvVgEQlofXx4khOR5KNkJnuYgHv7tNhOhQe5nS2HB5aj5KJ64Bc6wRecY+eAoqSf10648lm9ysRJFUdqxsbe2AjfjKT6a7SoHYqPJgCGyI/roZE51t5pdPy+Xt1E6fb43quCsAlMoEhHgBomf9uDuw28uJcINw09mqmg9WaqEvALr+79dJJEc5r3L+kMEyBYwy/WQioPsGKa7wMb9Yt42LpnS8JnJCXpOrWidg62peC+JBUXNgHehYVo87mT9s2bLTyCxcbJNHjOnlyaKhetVAm3gRsdSK9E= X-Microsoft-Exchange-Diagnostics: 1; VI1PR05MB3277; 6:EMXckWPLjSKu6R3mBYa7ShbI/PzlHkQOLaoRElfc0bcP5/+IG0tWCNNCGmfpSNtjMvsx1LIQrFuacR6TEXY/gKEoFwHIPmxqkwz9M6UpIDpSA4YbuuA7qps10z7Rrr+Pxo2/KeCPfTQqny5dWTgTEv0TkX+nyx+ZD+SwOr3gnQZYYswHDSLx0rwK3uxLNw05gFprv3HMI4HG+JJufyZzxKkW3zsmnOH+db7Qjgheb3LKB1KN0M/vcOgm6Yk7gzomHcKFB6Z83dg9cEhKuiXcirh3Yh1FW1sJ7+lLCkNli6w/AV0+6VJr0vJ2fEYj089tBGfF3qM1kzN0pQuLlVt5thPAb7iL/VowAguDkGdsUmYRZoy2SAj6ZdiaOPWl3YjoBADf0WO6Qgns5moUtIrCKmzq3X4oCEkfwwE2NGmsBtq4rsENRqcnihhOwBcwecsdSR4mQVhGLnFfpt6bjp6YXg==; 5:TovaJZ3b90OXUQcToYDIR/h1dZFHsRmKwAc7Obj3DUlbjT3MVylb9DrgZkA+kqe3FfPqs+bbA1BT0shVy2DYyuRIjAk3KysMv4Qr3eDL6Y32ch9Ng+EYD3TfhU6AiuwKGqajxI68ZcEgBGyHp5F3L3PDNbAR3s6UhO25OeFHY8k=; 7:F1Dt31xWmqOr1yp4liygiVDpV9Aawsa1V4B9O0GR27+4Epu/IeWNkG4L7VQFx4S6RxWxCkg8FtqNmAaw0FUdiTvwYJby0VBju2LqtL1lKnniExk8Kh5STQTrW2KxoLohGVFLswq5H4kfqjvljEJ9Ow/w035BdA7kDIO7wf3+xejyjgQI+eLR/+btbnkSSixs54u1YM0izT6FHI/20aZJCdWXkYr4RLJe9NSa0cxlhxEPenAMxiLy31IxZt4jgviH SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Oct 2018 14:14:16.7084 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 7a3322da-1adb-4556-e821-08d632a87e41 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR05MB3277 Subject: [dpdk-dev] [PATCH v2 7/7] net/mlx5: 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" 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. Suggested-by: Adrien Mazarguil Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_flow_tcf.c | 505 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 499 insertions(+), 6 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_tcf.c b/drivers/net/mlx5/mlx5_flow_tcf.c index a1d7733..a3348ea 100644 --- a/drivers/net/mlx5/mlx5_flow_tcf.c +++ b/drivers/net/mlx5/mlx5_flow_tcf.c @@ -4012,6 +4012,502 @@ static LIST_HEAD(, mlx5_flow_tcf_vtep) } #endif /* HAVE_IFLA_VXLAN_COLLECT_METADATA */ +#define MNL_REQUEST_SIZE_MIN 256 +#define MNL_REQUEST_SIZE_MAX 2048 +#define MNL_REQUEST_SIZE RTE_MIN(RTE_MAX(sysconf(_SC_PAGESIZE), \ + MNL_REQUEST_SIZE_MIN), MNL_REQUEST_SIZE_MAX) + +/* 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 = NLMSG_ALIGN(size); + buf = LIST_FIRST(&ctx->nlbuf); + if (buf && (buf->size + size) <= ctx->bufsize) { + nlh = (struct nlmsghdr *)&buf->msg[buf->size]; + buf->size += size; + return nlh; + } + if (size > ctx->bufsize) { + DRV_LOG(WARNING, "netlink: too long command buffer requested"); + return NULL; + } + buf = 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 = size; + nlh = (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 = 0; + + assert(buf->size); + do { + nlh = (struct nlmsghdr *)&buf->msg[size]; + size += NLMSG_ALIGN(nlh->nlmsg_len); + if (size >= buf->size) { + nlh->nlmsg_flags |= 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 = 0; + + bc = LIST_FIRST(&ctx->nlbuf); + while (bc) { + int rc; + + bn = LIST_NEXT(bc, next); + if (bc->size) { + flow_tcf_setack_nlcmd(bc); + nlh = (struct nlmsghdr *)&bc->msg; + rc = flow_tcf_nl_ack(tcf, nlh, bc->size, NULL, NULL); + if (rc && !ret) + ret = rc; + } + rte_free(bc); + bc = bn; + } + LIST_INIT(&ctx->nlbuf); + return ret; +} + +/** + * Collect local IP address rules with scope link attribute 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 otherwise + * and rte_errno is set. + */ +static int +flow_tcf_collect_local_cb(const struct nlmsghdr *nlh, void *arg) +{ + struct tcf_nlcb_context *ctx = arg; + struct nlmsghdr *cmd; + struct ifaddrmsg *ifa; + struct nlattr *na; + struct nlattr *na_local = NULL; + struct nlattr *na_peer = NULL; + unsigned char family; + + if (nlh->nlmsg_type != RTM_NEWADDR) { + rte_errno = EINVAL; + return -rte_errno; + } + ifa = mnl_nlmsg_get_payload(nlh); + family = ifa->ifa_family; + if (ifa->ifa_index != ctx->ifindex || + ifa->ifa_scope != RT_SCOPE_LINK || + !(ifa->ifa_flags & IFA_F_PERMANENT) || + (family != AF_INET && family != AF_INET6)) + return 1; + mnl_attr_for_each(na, nlh, sizeof(*ifa)) { + switch (mnl_attr_get_type(na)) { + case IFA_LOCAL: + na_local = na; + break; + case IFA_ADDRESS: + na_peer = 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 = flow_tcf_alloc_nlcmd(ctx, MNL_ALIGN(sizeof(struct nlmsghdr)) + + MNL_ALIGN(sizeof(struct ifaddrmsg)) + + (family == AF_INET6 + ? 2 * SZ_NLATTR_DATA_OF(IPV6_ADDR_LEN) + : 2 * SZ_NLATTR_TYPE_OF(uint32_t))); + if (!cmd) { + rte_errno = ENOMEM; + return -rte_errno; + } + cmd = mnl_nlmsg_put_header(cmd); + cmd->nlmsg_type = RTM_DELADDR; + cmd->nlmsg_flags = NLM_F_REQUEST; + ifa = mnl_nlmsg_put_extra_header(cmd, sizeof(*ifa)); + ifa->ifa_flags = IFA_F_PERMANENT; + ifa->ifa_scope = RT_SCOPE_LINK; + ifa->ifa_index = ctx->ifindex; + if (family == AF_INET) { + ifa->ifa_family = AF_INET; + ifa->ifa_prefixlen = 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 = AF_INET6; + ifa->ifa_prefixlen = 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 = { + .ifindex = ifindex, + .bufsize = MNL_REQUEST_SIZE, + .nlbuf = LIST_HEAD_INITIALIZER(), + }; + int ret; + + assert(ifindex); + /* + * Seek and destroy leftovers of local IP addresses with + * matching properties "scope link". + */ + nlh = mnl_nlmsg_put_header(tcf->buf); + nlh->nlmsg_type = RTM_GETADDR; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; + ifa = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifa)); + ifa->ifa_family = AF_UNSPEC; + ifa->ifa_index = ifindex; + ifa->ifa_scope = RT_SCOPE_LINK; + ret = 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 = 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 otherwise + * and rte_errno is set. + */ +static int +flow_tcf_collect_neigh_cb(const struct nlmsghdr *nlh, void *arg) +{ + struct tcf_nlcb_context *ctx = arg; + struct nlmsghdr *cmd; + struct ndmsg *ndm; + struct nlattr *na; + struct nlattr *na_ip = NULL; + struct nlattr *na_mac = NULL; + unsigned char family; + + if (nlh->nlmsg_type != RTM_NEWNEIGH) { + rte_errno = EINVAL; + return -rte_errno; + } + ndm = mnl_nlmsg_get_payload(nlh); + family = ndm->ndm_family; + if (ndm->ndm_ifindex != (int)ctx->ifindex || + !(ndm->ndm_state & NUD_PERMANENT) || + (family != AF_INET && family != AF_INET6)) + return 1; + mnl_attr_for_each(na, nlh, sizeof(*ndm)) { + switch (mnl_attr_get_type(na)) { + case NDA_DST: + na_ip = na; + break; + case NDA_LLADDR: + na_mac = na; + break; + } + if (na_mac && na_ip) + break; + } + if (!na_mac || !na_ip) + return 1; + /* Neigh rule with permenent attribute found. */ + cmd = flow_tcf_alloc_nlcmd(ctx, MNL_ALIGN(sizeof(struct nlmsghdr)) + + MNL_ALIGN(sizeof(struct ndmsg)) + + SZ_NLATTR_DATA_OF(ETHER_ADDR_LEN) + + (family == AF_INET6 + ? SZ_NLATTR_DATA_OF(IPV6_ADDR_LEN) + : SZ_NLATTR_TYPE_OF(uint32_t))); + if (!cmd) { + rte_errno = ENOMEM; + return -rte_errno; + } + cmd = mnl_nlmsg_put_header(cmd); + cmd->nlmsg_type = RTM_DELNEIGH; + cmd->nlmsg_flags = NLM_F_REQUEST; + ndm = mnl_nlmsg_put_extra_header(cmd, sizeof(*ndm)); + ndm->ndm_ifindex = ctx->ifindex; + ndm->ndm_state = NUD_PERMANENT; + ndm->ndm_flags = 0; + ndm->ndm_type = 0; + if (family == AF_INET) { + ndm->ndm_family = AF_INET; + mnl_attr_put_u32(cmd, NDA_DST, mnl_attr_get_u32(na_ip)); + } else { + ndm->ndm_family = 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 = { + .ifindex = ifindex, + .bufsize = MNL_REQUEST_SIZE, + .nlbuf = LIST_HEAD_INITIALIZER(), + }; + int ret; + + assert(ifindex); + /* Seek and destroy leftovers of neigh rules. */ + nlh = mnl_nlmsg_put_header(tcf->buf); + nlh->nlmsg_type = RTM_GETNEIGH; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; + ndm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ndm)); + ndm->ndm_family = AF_UNSPEC; + ndm->ndm_ifindex = ifindex; + ndm->ndm_state = NUD_PERMANENT; + ret = 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 = 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 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 otherwise + * and rte_errno is set. + */ +static int +flow_tcf_collect_vxlan_cb(const struct nlmsghdr *nlh, void *arg) +{ + struct tcf_nlcb_context *ctx = arg; + struct nlmsghdr *cmd; + struct ifinfomsg *ifm; + struct nlattr *na; + struct nlattr *na_info = NULL; + struct nlattr *na_vxlan = NULL; + bool found = false; + unsigned int vxindex; + + if (nlh->nlmsg_type != RTM_NEWLINK) { + rte_errno = EINVAL; + return -rte_errno; + } + ifm = mnl_nlmsg_get_payload(nlh); + if (!ifm->ifi_index) { + rte_errno = EINVAL; + return -rte_errno; + } + mnl_attr_for_each(na, nlh, sizeof(*ifm)) + if (mnl_attr_get_type(na) == IFLA_LINKINFO) { + na_info = 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 = true; + break; + case IFLA_INFO_DATA: + na_vxlan = na; + break; + } + if (found && na_vxlan) + break; + } + if (!found || !na_vxlan) + return 1; + found = false; + mnl_attr_for_each_nested(na, na_vxlan) { + if (mnl_attr_get_type(na) == IFLA_VXLAN_LINK && + mnl_attr_get_u32(na) == ctx->ifindex) { + found = true; + break; + } + } + if (!found) + return 1; + /* Attached VXLAN device found, store the command to delete. */ + vxindex = ifm->ifi_index; + cmd = flow_tcf_alloc_nlcmd(ctx, MNL_ALIGN(sizeof(struct nlmsghdr)) + + MNL_ALIGN(sizeof(struct ifinfomsg))); + if (!nlh) { + rte_errno = ENOMEM; + return -rte_errno; + } + cmd = mnl_nlmsg_put_header(cmd); + cmd->nlmsg_type = RTM_DELLINK; + cmd->nlmsg_flags = NLM_F_REQUEST; + ifm = mnl_nlmsg_put_extra_header(cmd, sizeof(*ifm)); + ifm->ifi_family = AF_UNSPEC; + ifm->ifi_index = 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 = { + .ifindex = ifindex, + .bufsize = MNL_REQUEST_SIZE, + .nlbuf = LIST_HEAD_INITIALIZER(), + }; + int ret; + + assert(ifindex); + /* + * Seek and destroy leftover VXLAN encap/decap interfaces with + * matching properties. + */ + nlh = mnl_nlmsg_put_header(tcf->buf); + nlh->nlmsg_type = RTM_GETLINK; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; + ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm)); + ifm->ifi_family = AF_UNSPEC; + ret = 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 = flow_tcf_send_nlcmd(tcf, &ctx); + if (ret) + DRV_LOG(WARNING, "netlink: device delete error %d", ret); +} + + /** * Create target interface index for VXLAN tunneling decapsulation. * In order to share the UDP port within the other interfaces the @@ -4100,12 +4596,9 @@ static LIST_HEAD(, mlx5_flow_tcf_vtep) uint16_t pcnt; /* Not found, we should create the new attached VTEP. */ -/* - * TODO: not implemented yet - * flow_tcf_encap_iface_cleanup(tcf, ifouter); - * flow_tcf_encap_local_cleanup(tcf, ifouter); - * flow_tcf_encap_neigh_cleanup(tcf, ifouter); - */ + flow_tcf_encap_iface_cleanup(tcf, ifouter); + flow_tcf_encap_local_cleanup(tcf, ifouter); + flow_tcf_encap_neigh_cleanup(tcf, ifouter); for (pcnt = 0; pcnt <= (MLX5_VXLAN_PORT_RANGE_MAX - MLX5_VXLAN_PORT_RANGE_MIN); pcnt++) { encap_port++;