From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM03-BY2-obe.outbound.protection.outlook.com (mail-by2nam03on0054.outbound.protection.outlook.com [104.47.42.54]) by dpdk.org (Postfix) with ESMTP id 988075A4E for ; Fri, 26 Aug 2016 17:55:02 +0200 (CEST) Received: from DM5PR03CA0003.namprd03.prod.outlook.com (10.175.104.13) by DM2PR0301MB0719.namprd03.prod.outlook.com (10.160.97.14) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id 15.1.557.21; Fri, 26 Aug 2016 15:55:00 +0000 Received: from BY2FFO11FD033.protection.gbl (2a01:111:f400:7c0c::180) by DM5PR03CA0003.outlook.office365.com (2603:10b6:3:118::13) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id 15.1.599.9 via Frontend Transport; Fri, 26 Aug 2016 15:54:59 +0000 Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=nxp.com; nxp.com; dkim=none (message not signed) header.d=none;nxp.com; dmarc=fail action=none header.from=nxp.com;nxp.com; dkim=none (message not signed) header.d=none; Received-SPF: Fail (protection.outlook.com: domain of nxp.com does not designate 192.88.168.50 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.168.50; helo=tx30smr01.am.freescale.net; Received: from tx30smr01.am.freescale.net (192.88.168.50) by BY2FFO11FD033.mail.protection.outlook.com (10.1.14.218) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.587.6 via Frontend Transport; Fri, 26 Aug 2016 15:55:00 +0000 Received: from BuildMachinepc.ap.freescale.net (BuildMachinepc.ap.freescale.net [10.232.133.79]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id u7QFsrmP028095; Fri, 26 Aug 2016 08:54:57 -0700 From: Pankaj Chauhan To: CC: , , , , , Pankaj Chauhan Date: Sat, 27 Aug 2016 21:56:24 +0530 Message-ID: <1472315186-28090-2-git-send-email-pankaj.chauhan@nxp.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1472315186-28090-1-git-send-email-pankaj.chauhan@nxp.com> References: <1472315186-28090-1-git-send-email-pankaj.chauhan@nxp.com> X-EOPAttributedMessage: 0 X-Matching-Connectors: 131167005005845178; (91ab9b29-cfa4-454e-5278-08d120cd25b8); () X-Forefront-Antispam-Report: CIP:192.88.168.50; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(7916002)(2980300002)(1110001)(1109001)(339900001)(199003)(189002)(106466001)(105606002)(50226002)(2950100001)(92566002)(7846002)(104016004)(47776003)(2351001)(81156014)(81166006)(229853001)(8676002)(8936002)(4326007)(305945005)(2906002)(8666005)(33646002)(68736007)(86362001)(356003)(5003940100001)(626004)(36756003)(575784001)(77096005)(19580395003)(586003)(19580405001)(85426001)(189998001)(76176999)(110136002)(5660300001)(50986999)(97736004)(50466002)(48376002)(87936001)(7059030)(41533002)(21314002); DIR:OUT; SFP:1101; SCL:1; SRVR:DM2PR0301MB0719; H:tx30smr01.am.freescale.net; FPR:; SPF:Fail; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11FD033; 1:wblbdRMICxEbBAIpQ9HCfTE8kZ/5GoC15ikES3RSmMqTpSklIdaM82kqW5zeE3N6AOPRZasog2krwInOLrraWuOPahc4xciPYdnWYVOsw+BjCpGSgrLlEUt5T6ZB97dP11Ur/0pSUz4beJAwz2bAwxVtYXOuRzo1XbxNiIjOaTXxc0qhb9WIiMvBy4+uiUjN0MfxBMwbSDaS8rEN3p1aSmRjZD0NI9xKwajHgTo6K42TiuvkOOej7mQlIFiCHMcf67cD5DI/7alWtVvyYY85BTCDbhjACTeWEn63M1fNvqKmOaVAtrQD712k4NmI8T63kxwY56x/TfMbEX2geDC/3z/CpU4aATIWAQUfiCfDZN9fybEjd8wvl80hNsccrvnMB43EL4+1Smd7JMJRjwSbX6U3WCicY9dkQQIgyrQGdU7CThvv/HndIAVnc152PyC+xhutxUoJI0pCyopCRcSzMyfsWViIVV7WTuQFMlzEOntNwLbwdv51UObG8n6gMMMtWK20rKO7tStB+f63Q1H+8rpma0ZCxBYJSBnv3tIwp0f1ueHmF/mycUURjy7sUnI37ZD61PdBnEuqfn759IP4ao7LI0XM/YUPsMlYwKcnxOYJrZz+4NObjxGKYUu1LvunkhEZWwTqd2cBzf9zJjz5YfUkcFvp+wpYT+fNvDQ4DOlNpylNlaM1MuqXA3NIx1XNXrL02Ym1XcVe9Ivhlsj401/SO1LehPOgyxeebCSOaOxGOtMGH+4EQRoEchnrxb5EkWwzeZf5BMfma42e9U3hmw== MIME-Version: 1.0 Content-Type: text/plain X-MS-Office365-Filtering-Correlation-Id: c707e9b2-82d3-4160-07b2-08d3cdc95604 X-Microsoft-Exchange-Diagnostics: 1; DM2PR0301MB0719; 2:V5R9Egmw4cjsjrx88R/AlykNNR/oD7Go/cBBXlcayS9iEs2ljUTxYwLcFJndLala+u9PKXWcLOdmjhc1HNWGEdlzW2/YrYNUMxekm2dIvCtwEc2FsARWwEc+S/NqHJ+xHa9Ydn+PJQZf6/M2WtlNsYPW2H0KOcLJ7lvWAn296FXadshDsHC91JncY0FhO1Ja; 3:6rIl9nU+OqkR2ROWMU3OZnUenByTD+GULG4i0nNJeksk+R9/qCGfdbfsxhWfFUkAkH7wB/xAIRUmJTbOr/0dmHR3XZtWPiTsuHJi9ZPIxvEMxx8BlWLB1c6OeCwZMdPoGhsrZfhqmtj7qAk0xeGcW+XyClnGZ4KTDpUS+2x0uJwKS6Yba+BOPR2O3dBzpXYBVhZv/cI8V6NYlgvMS7m4W7oW6AQQnWuKX+CJpPm2P0M= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:DM2PR0301MB0719; X-Microsoft-Exchange-Diagnostics: 1; DM2PR0301MB0719; 25:xKviAFYxsE/7fUwZPvTPVoY89xTovtPh4uSIC/1fYDcS8W9mDvCVld7VNTm9W6VMqePPXJkaSoGUFdZF/xDQBYKS4KZbPaZskfXfIH9s4pO/fDJLrCOH5gDoT4Ib9Uq4jsGouvGFc7dfmx9+tw2F8SPpH73I+mYdQbIOEHW4onG838REjgFDlHu0PcCYB9DisW6URJ9++rT8VS368NfYfRE9VmZWdP1RVLuWDJQwJwr0SNMAX45dtae3Yn8uNB2jWzvSQEbM8DSDw8aJZTq/CPLwatUfB1VxZZ2UxsmwYyODgHKr5f/n4CDudU7JGeQ2Rbd2VKyuPkmUMvB6R1q60R6jy7tUYFZ4ecgpUbOMct9pcmGEKa2XhO0eEK32sdlsSkBDnBWKrRScrpcKas+6wByK7AzU0gSAFSiq7SNasDjSi1qUz7p7NpSagTa7lu5e9rTbleGGtrZ6zvKPuzMjbe59SNExYPKnUBoM/7y5tBavQ6xPjH3hMQlqxtCE8S2KwgHIRv7WzyW7d5IqZtBMeQrrgQbWRiJkh7SgRoj5zBVbv4lp7XOXLbPf3TW6dCgKlmA92A792LX+sdz67qJcQ3cC69ch5s6pNeNg70ORnfK2HnPdkVTUyBLRvmyUJgJMrtOmYwRFtHylZBmz2thLoAyPYt8PNi7oEKNLNL8KEBLTxpWzZgC96CdnvSc38vljHwIVPDYo96aqBe/00V4VqRRlWTbbtxEgj64oLFN1/x6OykLsZ+mB+9aPdzkcgANVSC/XS5l+F2171LbuEp4Psg== X-Microsoft-Exchange-Diagnostics: 1; DM2PR0301MB0719; 31:pTDBV3fkZn7Sx0vA1YkryXIPbyGuC4SP+Wu43JMSRNFTdinjvQQPIpoqP4RGQuCWDZMSUlHqViLR6Ze0sNThowLvMB0uw8yRkZwMvJ33rLJt8d4HF+PcCGEpS5bZZ4N9ozlOjsa1TzNmXHR5aC10odxRyVHVUQFJmF7DIlD2Y2GJB7Hbd/qEqvgIupqZ4rAaoCtfV6DZaLwPQxeTG1DQp/EdXqfytYLgHj46A5P11JA=; 4:nhI0kZcnQZCdC5uKCrjnK87SyFmCam+tMotrBcpmTeJU9yAoWa3oTNJFFDPmy4Tanm3UmtJ1q0fa43X3FfRJRUVnj0VtubP4E9QwrzZwKtWbKmdOYwyK5HCR/63cqbm+gZ/B1m8fAEfGOtUf/OOVKpyPBgIKMIdUgezaRawo4n0opzqk8N1NJqVaT06Ipq0SvTliPlzcS3aR0+p/wgz3Jg6/KeGb4zh2TCWEgZHFV0R7IddHrZu+kpSQ6wWXbPFMrRQpH5pWXlAKfg28MX7La8MtwAvISr6TGnqW6NXmgXs5095aD+CK6XhMClabraFlpGNifQpoivdV8KNvdB3l0oYwryQKrFTtTCInsY53F4QcJ2RIyLRklrIRFJs8LDsTTomWxfPZL2PiZXgI86rIT9ayQZBMho8O6Dlx+3NpLhAl/K2oqWjlGB8iAz5DCDdPwXGaz/OOxhI8kysRJEebJo5Etf63enr5k1F/PS3JkAOf711j5oRS6lcArIysuBMRgCBke5pMfsg7X/xlO9QRMo+fq6txiyV7BOLKMrW8ndg= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(185117386973197); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040176)(601004)(2401047)(13015025)(13023025)(13024025)(13018025)(13017025)(8121501046)(5005006)(10201501046)(3002001)(6055026); SRVR:DM2PR0301MB0719; BCL:0; PCL:0; RULEID:(400006); SRVR:DM2PR0301MB0719; X-Forefront-PRVS: 00462943DE X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; DM2PR0301MB0719; 23:u8XFrUD7qbs2AcixRH54cJuylOrefC88Hqofj8l?= =?us-ascii?Q?+D7jrq+w9wMdVXy2qAkCQ/iZdZz8KK6hhz5FmCoRhV+YjweamRnqsc1gnloK?= =?us-ascii?Q?EMuxYpesdx5SVmWGoaEpiM2IPB0ASbGwOP8LZAv5ZlTlHpZQYCrERDVMJKeQ?= =?us-ascii?Q?EH9kcNuhaHKT8VFgxl7TkgKbO6iry/KP2v7UfT1MXxf3BXEudFTXM/cykXcN?= =?us-ascii?Q?3l36EzrNyiocAyBW5Tw8gVWGnyXDiQfBos2yDO6arSXJAoAL4tY7uNbZuseu?= =?us-ascii?Q?lIDA5O4tcfFHC1eihT9U299HfltVzk+oTo5K5DINejjAhteO0bMpQqZs0A0U?= =?us-ascii?Q?2m6QTZNHlIJ1q2TgI8/p3NEZCcSD5b/wtqLxDJXL/xcZFX5cqnTyv2mPTg1A?= =?us-ascii?Q?SnsM/gOSeWchSyzPcY2NCn8jDnwiur3IESbAFejcGPDR3l+En84sw3lkIg2/?= =?us-ascii?Q?nqhFRsxBuSlC9eOtR0ie4XJpJKjrxTdQ0IHjgx/fmDxYMNYeRV3bKpeZaCCd?= =?us-ascii?Q?Fn0HLURtpdS65qBPBg/HOC8Jbh0EhYtoj12P1OucCfy6zutZ/yDS9CpyTivr?= =?us-ascii?Q?FZeE1kQooaxUTJlaH2421swC/VTyIp3AJkB1Yd3VjX1zUrP2TDTaZEelFNgI?= =?us-ascii?Q?lqDvFbVC9YP42NSo8zu54cTxFmdv78977gkqj1F5dZL/YFVZ5/9FkXWE1VkF?= =?us-ascii?Q?c5hu7CNkv4Uf78JhX99CLHuVW+63o5KXUPivBv/2YTh8HaKh28nznFi5n5NB?= =?us-ascii?Q?15O+sjixo0+V2hw4tAYfHpSdxOjmIUv94CSNdhOFmoKNXuC9luLwLGdJjWBq?= =?us-ascii?Q?jeQ/Y4kiykpCft1Ke0PvUNVs813371JpI2gwjLuKkKEQw+SmBztvYrjBUeUR?= =?us-ascii?Q?+0uznzKvgc6/7xK8JE6a8AhP2yABgnafql2lk9GxjTW9kk2Eb9DnCPejfkV5?= =?us-ascii?Q?PIa1AIdLL1kSX55HFSyQ7P9Td5wQy0wegEzuCs2MmgR1yGj7kAbvPfc3qE0M?= =?us-ascii?Q?DJSZmA++r19QaNezOyw79GjX+5ydnImDfSvBU47akmiVd9bPSuVRboxx93SR?= =?us-ascii?Q?GZRy/kV+PzSgGcpQZ4oV6Zfxc6NKkx6atbAG1J0KFPJp1HPtEbG+IO7It9o8?= =?us-ascii?Q?aOLwrcQgEQ4zxw+iVAUMNAwrkIYzalzvoqyClo6wyn89WRpbZOKuSzBkbxC/?= =?us-ascii?Q?+w+zTdnny9SziWUM+AD83G/jLsoL1jYdj4saw?= X-Microsoft-Exchange-Diagnostics: 1; DM2PR0301MB0719; 6:aJdFkx9qX1xzpdHI7e7uJLap7ZXwgvD09HrnhCVmROv20eaf8gYZLtRn0Bj7JLnZxsAY47r92DhIdElwVMjiFbQaS9bAMpKrLXPiGZWYrBatUzZr3mfPPdcpNXrSkiyvMprZ7AcqzmO1NaBknSIzzs3pfmDQwsGrJrXucl3jsP52UNsVBJU43jmiYBNB69e/v8O1mbwA3EZXL7g892KjDQ4I+3qR/+ztB7rAoRLyEm226JHBCMPeHorPhrK2KgDyzZLAg2OxRAJX/gEVGBPHKF2gBEQks4ARxHBH5hbZ+qc=; 5:yjzffCgBpqzgDA1ZiuKxuDt2ZkhLSvmelKASNhctwHiya8D7pixGxduLjekNeyPmKBy9nMtNW5xIqQj1+AwpsOXRLz2CLBMlPCYdfaxOJzF9+zZrpD1HuNq51Bd7CeLYfSgst7ALDy77HxFqFCP++Dn2nadU53IBd0n4zf0X6K0=; 24:LixT6j0ipjirZU54Tas7YaFDkiU6G+DCpKapmtU80PZuQkpKEdEnKnscDPgcYJupvaZHqekeyTRdk2PHjtTNYLUBlW1J4cyzOTbKKRYUhMs=; 7:bn/Cz01VV6vxtKLg5H72sQdQUi+TqDLVD59Odab3scIbenJAZOKdLsCbqRXI1M3ImCKDr6UeKLV/z5uDZQahdtym6J8SYvukb/+4CjhzNz3XFEKqYyKyG7Ci8+58bnCVyakPcKbMLTlKwxx8VyrDqgsrIUhd/b/r6ckNG1iiN1TAG3oaGDg5oJeIUAIGzzFAwh+5MIheVTUnk5gxIRhZNlEA6atkkkwEikwi/2fXC/mBUGUCiVPiayijxTxGRw0g SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Aug 2016 15:55:00.2569 (UTC) X-MS-Exchange-CrossTenant-Id: 5afe0b00-7697-4969-b663-5eab37d5f47e X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=5afe0b00-7697-4969-b663-5eab37d5f47e; Ip=[192.88.168.50]; Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM2PR0301MB0719 Subject: [dpdk-dev] [RFC][PATCH 1/3] examples/vhost: Add vswitch (generic switch) framework X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 26 Aug 2016 15:55:03 -0000 Indroduce support for a generic framework for handling of switching between physical and virtio devices. The vswitch framework introduces the following concept: 1. vswitch_dev: Vswitch device is a logical switch which can have Phsyical and virtio devices. The devices are operated/used using standard DPDK API for devices. 2. vswitch_port: Any physical or virtio device that is added to vswitch. The port can have it's own tx/rx functions for doing data transfer, which are exposed to the framework using generic function pointers (vs_port->do_tx/do_rx). This way the generic code can do tx/rx without understanding the type of device (Physical or virtio). 3. vswitch_ops: The ops is set of function pointers which are used to do operations like learning, unlearning, add/delete port, lookup_and_forward. The user of vswitch framework (vhost/main.[c,h])uses these function pointers to perform above mentioned operations, thus it remains agnostic of the underlying implmentation. Different switching logics can implement their vswitch_device and vswitch_ops, and register with the framework. This framework makes vhost-switch application scalable in terms of: 1. Different switching logics (one of them is vmdq, vhost/vmdq.[c,h] 2. Number of ports. 3. Policies of selecting ports for rx and tx. Signed-off-by: Pankaj Chauhan --- examples/vhost/Makefile | 2 +- examples/vhost/vswitch_common.c | 467 ++++++++++++++++++++++++++++++++++++++++ examples/vhost/vswitch_common.h | 175 +++++++++++++++ 3 files changed, 643 insertions(+), 1 deletion(-) create mode 100644 examples/vhost/vswitch_common.c create mode 100644 examples/vhost/vswitch_common.h diff --git a/examples/vhost/Makefile b/examples/vhost/Makefile index e95c68a..458d166 100644 --- a/examples/vhost/Makefile +++ b/examples/vhost/Makefile @@ -48,7 +48,7 @@ else APP = vhost-switch # all source are stored in SRCS-y -SRCS-y := main.c +SRCS-y := main.c vswitch_common.c CFLAGS += -O2 -D_FILE_OFFSET_BITS=64 CFLAGS += $(WERROR_FLAGS) diff --git a/examples/vhost/vswitch_common.c b/examples/vhost/vswitch_common.c new file mode 100644 index 0000000..f0e07f2 --- /dev/null +++ b/examples/vhost/vswitch_common.c @@ -0,0 +1,467 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Freescale Semiconductor. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Freescale Semiconductor nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "vswitch_common.h" + +/* Meta data for vswitch. Since this is going to be used in this file only it + * is defined here instead of in a header file. + */ +struct vs_mdata { + rte_spinlock_t lock; + int vswitch_dev_count; + LIST_HEAD(, vswitch_dev) vswitch_head; +}; + +static struct vs_mdata *vs_mdata_g; + +static uint16_t vs_do_tx_phys_port(struct vswitch_port *port, uint16_t tx_q, + __attribute__((unused))struct rte_mempool *mbuf_pool, + struct rte_mbuf **pkts, uint16_t pkt_count) +{ + return rte_eth_tx_burst(port->port_id, tx_q, pkts, pkt_count); +} + + +static uint16_t vs_do_tx_virtio_port(struct vswitch_port *port, uint16_t tx_q, + __attribute__((unused)) struct rte_mempool *mbuf_pool, + struct rte_mbuf **pkts, uint16_t pkt_count) +{ + return rte_vhost_enqueue_burst(port->port_id, tx_q, pkts, pkt_count); +} + + +static uint16_t vs_do_rx_phys_port (struct vswitch_port *port, uint16_t rx_q, + __attribute__((unused))struct rte_mempool *mbuf_pool, + struct rte_mbuf **rx_pkts, uint16_t pkt_count) +{ + return rte_eth_rx_burst(port->port_id, rx_q, rx_pkts, pkt_count); +} + +static uint16_t vs_do_rx_virtio_port (struct vswitch_port *port, uint16_t rx_q, + struct rte_mempool *mbuf_pool, + struct rte_mbuf **rx_pkts, uint16_t pkt_count) +{ + return rte_vhost_dequeue_burst(port->port_id, rx_q, mbuf_pool, + rx_pkts, pkt_count); +} + +struct vswitch_dev *vs_get_vswitch_dev(const char *name) +{ + struct vswitch_dev *temp, *vs_dev = NULL; + + rte_spinlock_lock(&vs_mdata_g->lock); + LIST_FOREACH(temp, &vs_mdata_g->vswitch_head, list) { + if (!strncmp(temp->name, name, VSWITCH_NAME_SIZE)) + vs_dev = temp; + } + rte_spinlock_unlock(&vs_mdata_g->lock); + + return vs_dev; +} + +static struct vswitch_port *vs_get_free_port(struct vswitch_dev *vs_dev) +{ + int i; + struct vswitch_port *vs_port = NULL; + + for (i = 0; i < vs_dev->port_count; i++) { + vs_port = &vs_dev->ports[i]; + if (vs_port->state == VSWITCH_PSTATE_NOT_INUSE) + return vs_port; + } + + return NULL; +} + +static void vs_free_port(struct vswitch_port *vs_port) +{ + + vs_port->state = VSWITCH_PSTATE_NOT_INUSE; +} + +static __attribute__((unused))struct vswitch_port *vs_get_port( + struct vswitch_dev *vs_dev, unsigned int port_id, + enum vswitch_port_type type) +{ + int i; + struct vswitch_port *vs_port = NULL; + + for (i = 0; i < vs_dev->port_count; i++) { + vs_port = &vs_dev->ports[i]; + if ((vs_port->port_id == port_id) && (vs_port->type == type)) + return vs_port; + } + + return NULL; +} + +int vs_port_start(struct vswitch_port *vs_port) +{ + struct vswitch_ops *vs_ops = vs_port->vs_dev->ops; + int rc = 0; + + if (vs_ops->port_start) + rc = vs_ops->port_start(vs_port); + + if (!rc) + vs_port->state = VSWITCH_PSTATE_LEARNING; + + return rc; +} + +int vs_port_stop(struct vswitch_port *vs_port) +{ + struct vswitch_ops *vs_ops = vs_port->vs_dev->ops; + int rc = 0; + + if (vs_ops->port_stop) + rc = vs_ops->port_stop(vs_port); + + if (!rc) + vs_port->state = VSWITCH_PSTATE_ADDED; + + return rc; +} + +struct vswitch_port *vs_add_port(struct vswitch_dev *vs_dev, int port_id, + enum vswitch_port_type type, void *priv) +{ + int rc = 0; + struct vswitch_port *vs_port = NULL; + struct vswitch_ops *vs_ops = vs_dev->ops; + + vs_port = vs_get_free_port(vs_dev); + if (!vs_port) { + RTE_LOG(DEBUG, VHOST_CONFIG, "Failed get free port in \ + vswitch %s\n", vs_dev->name); + rc = -EBUSY; + goto out; + } + + vs_port->port_id = port_id; + vs_port->type = type; + vs_port->priv = priv; + + switch (type) { + case VSWITCH_PTYPE_PHYS: + vs_port->do_tx = vs_do_tx_phys_port; + vs_port->do_rx = vs_do_rx_phys_port; + case VSWITCH_PTYPE_VIRTIO: + vs_port->do_tx = vs_do_tx_virtio_port; + vs_port->do_rx = vs_do_rx_virtio_port; + default: + RTE_LOG(DEBUG, VHOST_CONFIG, "Invalid port [id %d, type %d]", + port_id, type); + rc = -EINVAL; + goto out; + } + + if (vs_ops->add_port) + rc = vs_ops->add_port(vs_port); + + if (rc) + goto out; + + vs_port->state = VSWITCH_PSTATE_ADDED; + + rte_eth_macaddr_get(vs_port->port_id, &vs_port->mac_addr); + RTE_LOG(INFO, VHOST_PORT, "Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 + " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", + (unsigned)port_id, + vs_port->mac_addr.addr_bytes[0], + vs_port->mac_addr.addr_bytes[1], + vs_port->mac_addr.addr_bytes[2], + vs_port->mac_addr.addr_bytes[3], + vs_port->mac_addr.addr_bytes[4], + vs_port->mac_addr.addr_bytes[5]); + + RTE_LOG(DEBUG, VHOST_CONFIG, "Added port [%d, type %d] to \ + vswitch %s\n", vs_port->port_id, type, vs_dev->name); +out: + if (rc){ + RTE_LOG(INFO, VHOST_CONFIG, "Failed to Add port [%d, type %d] to \ + vswitch %s\n", port_id, type, vs_dev->name); + if (vs_port) + vs_free_port(vs_port); + vs_port = NULL; + } + + return vs_port; +} + +int vs_del_port(struct vswitch_port *vs_port) +{ + int rc = 0; + struct vswitch_ops *vs_ops = vs_port->vs_dev->ops; + + if (vs_ops->del_port) + rc = vs_ops->del_port(vs_port); + + if (!rc) + vs_port->state = VSWITCH_PSTATE_NOT_INUSE; + + + /*TBD:XXX: may be put a dummy function which frees all packets without + * any tx/rx, NULL looks ugly! + */ + vs_port->do_tx = vs_port->do_rx = NULL; + + RTE_LOG(DEBUG, VHOST_CONFIG, "Removed port [%d, type %d] from \ + vswitch %s\n", vs_port->port_id, vs_port->type, + vs_port->vs_dev->name); + + return rc; +} + +int vs_learn_port(struct vswitch_port *vs_port, struct rte_mbuf + **pkts, uint16_t count) +{ + struct vswitch_ops *vs_ops = vs_port->vs_dev->ops; + int rc; + + rc = vs_ops->learn_port(vs_port, pkts, count); + if (!rc) + vs_port->state = VSWITCH_PSTATE_FORWARDING; + + return rc; +} + +int vs_unlearn_port(struct vswitch_port *vs_port) +{ + struct vswitch_ops *vs_ops = vs_port->vs_dev->ops; + + vs_ops->unlearn_port(vs_port); + vs_port->state = VSWITCH_PSTATE_LEARNING; + + return 0; +} + + +int vs_lookup_n_fwd(struct vswitch_port *vs_port, struct rte_mbuf **pkts, + uint16_t count, uint16_t in_rxq) +{ + int rc, i; + struct vswitch_ops *vs_ops = vs_port->vs_dev->ops; + + rc = vs_ops->lookup_n_fwd(vs_port, pkts, count, in_rxq); + + if (rc) { + for (i = 0; i < count; i++) + rte_pktmbuf_free(pkts[i]); + } + + return rc; +} + +int vs_do_broadcast_fwd(struct vswitch_dev *vs_dev, + struct vswitch_port *in_port, struct rte_mbuf *mbuf) +{ + int i = 0, tx_q; + struct vswitch_port *dest_port; + + for (i = 0; i < vs_dev->port_count; i++) { + dest_port = &vs_dev->ports[i]; + if ((in_port->type != dest_port->type) && + (in_port->port_id != dest_port->port_id)) { + if (dest_port->type == VSWITCH_PTYPE_VIRTIO) + tx_q = VIRTIO_TXQ; + else + tx_q = rte_lcore_id(); + dest_port->do_tx(dest_port, tx_q, NULL, &mbuf, 1); + } + } + + return 0; +} + +struct vswitch_port *vs_sched_rx_port(struct vswitch_dev *vs_dev, enum + vswitch_port_type ptype, uint16_t core_id) +{ + struct vswitch_port *vs_port = NULL; + struct vswitch_ops *vs_ops = vs_dev->ops; + + if (vs_ops->sched_rx_port) + vs_port = vs_ops->sched_rx_port(vs_dev, ptype, core_id); + + return vs_port; +} + +struct vswitch_port *vs_sched_tx_port(struct vswitch_dev *vs_dev, enum + vswitch_port_type ptype, uint16_t core_id) +{ + struct vswitch_port *vs_port = NULL; + struct vswitch_ops *vs_ops = vs_dev->ops; + + if (vs_ops->sched_tx_port) + vs_port = vs_ops->sched_tx_port(vs_dev, ptype, core_id); + + return vs_port; +} + + +struct vswitch_dev *vs_register_switch(const char *name, int priv_size, + int max_ports, struct vswitch_ops *ops) +{ + struct vswitch_dev *vs_dev; + struct vswitch_port *vs_port; + int size, i; + + size = priv_size + sizeof(struct vswitch_dev); + vs_dev = rte_malloc(NULL, size, 64); + if (!vs_dev) { + RTE_LOG(DEBUG, VHOST_CONFIG, "Failed to vswitch device\n"); + goto out; + } + + strncpy(vs_dev->name, name, VSWITCH_NAME_SIZE); + vs_dev->priv = (void *) (vs_dev + 1); + + size = max_ports * sizeof(struct vswitch_port); + vs_dev->ports = rte_malloc(NULL, size, 64); + if (!vs_dev->ports) { + RTE_LOG(DEBUG, VHOST_CONFIG, + "Failed allocate %d ports for vswitch %s\n", + max_ports, vs_dev->name); + goto out; + } + + memset(vs_dev->ports, 0, size); + for (i = 0; i < max_ports; i++) + { + vs_port = &vs_dev->ports[i]; + vs_port->state = VSWITCH_PSTATE_NOT_INUSE; + } + + vs_dev->port_count = max_ports; + vs_dev->ops = ops; + + rte_spinlock_lock(&vs_mdata_g->lock); + LIST_INSERT_HEAD(&vs_mdata_g->vswitch_head, vs_dev, list); + vs_mdata_g->vswitch_dev_count++; + rte_spinlock_unlock(&vs_mdata_g->lock); + + RTE_LOG(DEBUG, VHOST_CONFIG, "Added vswitch %s, max_ports %d\n", + vs_dev->name, vs_dev->port_count); + + return vs_dev; + +out: + if (vs_dev && vs_dev->ports) + rte_free(vs_dev->ports); + if (vs_dev) + rte_free(vs_dev); + + return NULL; +} + +int vs_unregister_switch(struct vswitch_dev *vs_dev) +{ + struct vswitch_dev *temp; + int removed = 0, rc; + + rte_spinlock_lock(&vs_mdata_g->lock); + LIST_FOREACH(temp, &vs_mdata_g->vswitch_head, list) { + if (!strncmp(temp->name, vs_dev->name, VSWITCH_NAME_SIZE)){ + LIST_REMOVE(temp, list); + removed = 1; + } + } + rte_spinlock_unlock(&vs_mdata_g->lock); + + if (!removed) { + RTE_LOG(DEBUG, VHOST_CONFIG, "vswitch [%s] not found\n", + vs_dev->name); + rc = -ENODEV; + } + + RTE_LOG(DEBUG, VHOST_CONFIG, "Unregistering and freeing vswitch [%s]\n", + vs_dev->name); + + if (vs_dev->ports) + rte_free(vs_dev->ports); + + rte_free(vs_dev); + + return rc; +} + +int vs_switch_dev_init(struct vswitch_dev *vs_dev, uint16_t conf_flags) +{ + struct vswitch_ops *ops = vs_dev->ops; + int rc = 0; + + if (ops->switch_init) + rc = ops->switch_init(vs_dev, conf_flags); + + if (!rc) + vs_dev->conf_flags = conf_flags; + + return rc; +} + +int vs_vswitch_init(void) +{ + int rc = 0; + + vs_mdata_g = rte_malloc(NULL, sizeof(struct vs_mdata), 64); + if (!vs_mdata_g) + { + RTE_LOG(DEBUG, VHOST_CONFIG, + "Failed to allocate mem for vhost siwtch metadata\n"); + rc = -ENOMEM; + goto out; + } + + memset(vs_mdata_g, 0, sizeof(struct vs_mdata)); + LIST_INIT(&vs_mdata_g->vswitch_head); + rte_spinlock_init(&vs_mdata_g->lock); + +out: + return rc; +} + diff --git a/examples/vhost/vswitch_common.h b/examples/vhost/vswitch_common.h new file mode 100644 index 0000000..0496152 --- /dev/null +++ b/examples/vhost/vswitch_common.h @@ -0,0 +1,175 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Freescale Semiconductor. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Freescale Semiconductor nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __VHOST_SWITCH_COMMON_H__ +#define __VHOST_SWITCH_COMMON_H__ + +#include +#include "main.h" + +#define VSWITCH_NAME_SIZE 32 + +enum vswitch_port_type { + VSWITCH_PTYPE_PHYS = 1, + VSWITCH_PTYPE_VIRTIO, + VSWITCH_PTYPE_END, +}; +enum vswitch_port_state { + VSWITCH_PSTATE_ADDED = 1, + VSWITCH_PSTATE_LEARNING, + VSWITCH_PSTATE_FORWARDING, + VSWITCH_PSTATE_NOT_INUSE, + VSWITCH_PSTATE_END, +}; + +struct vswitch_port { + enum vswitch_port_type type; + enum vswitch_port_state state; + unsigned int port_id; + struct rte_eth_conf port_conf; + struct vswitch_dev *vs_dev; /*switch to which this port belongs */ + void *priv; /*Private for port specefic data*/ + struct ether_addr mac_addr; + int phys_port_rxq; + uint16_t (*do_tx) (struct vswitch_port *port, uint16_t tx_q, + __attribute__((unused))struct rte_mempool *mbuf_pool, + struct rte_mbuf **tx_pkts, uint16_t pkt_count); + uint16_t (*do_rx) (struct vswitch_port *port, uint16_t rx_q, + __attribute__((unused))struct rte_mempool *mbuf_pool, + struct rte_mbuf **rx_pkts, uint16_t pkt_count); +}; + +struct vswitch_dev { + char name[VSWITCH_NAME_SIZE]; + void *priv; /* Private for switch specefic + * data */ + uint64_t conf_flags; + LIST_ENTRY (vswitch_dev) list; + struct vswitch_port *ports; + int port_count; + struct vswitch_ops *ops; +}; + +/* Function typedefs */ +typedef int (*vs_switch_init_t) (struct vswitch_dev *, uint64_t conf_flags); +typedef int (*vs_add_port_t) (struct vswitch_port *vs_port); +typedef int (*vs_del_port_t) (struct vswitch_port *port); +typedef int (*vs_learn_port_t) (struct vswitch_port *port, struct rte_mbuf + **pkts, uint16_t count); +typedef int (*vs_unlearn_port_t) (struct vswitch_port *port); +typedef int (*vs_lookup_n_fwd_t)(struct vswitch_port *in_port, struct rte_mbuf + **pkts, uint16_t pkt_count, uint16_t rxq); +#if 0 +typedef uint16_t (*vs_do_tx_t) (struct vswitch_port *port, uint16_t tx_q, struct + rte_mbuf **tx_pkts, uint16_t pkt_count); + +typedef uint16_t (*vs_do_rx_t) (struct vswitch_port *port, uint16_t rx_q, struct + rte_mbuf **rx_pkts, uint16_t pkt_count); +#endif +typedef struct vswitch_port* (*vs_sched_tx_port_t)(struct vswitch_dev *vs_dev, + enum vswitch_port_type ptype, uint16_t core_id); + +typedef struct vswitch_port* (*vs_sched_rx_port_t)(struct vswitch_dev *vs_dev, + enum vswitch_port_type ptype, uint16_t core_id); + +typedef int (*vs_port_start_t) (struct vswitch_port *port); + +struct vswitch_ops { + vs_add_port_t add_port; + vs_del_port_t del_port; + vs_lookup_n_fwd_t lookup_n_fwd; + vs_learn_port_t learn_port; + vs_unlearn_port_t unlearn_port; + vs_port_start_t port_start; + vs_port_start_t port_stop; + vs_switch_init_t switch_init; + vs_sched_tx_port_t sched_tx_port; + vs_sched_rx_port_t sched_rx_port; + +}; + +/*VSWITCH conf flags */ +#define VS_CNF_FLG_VM2VM_HARDWARE (1 << 0) +#define VS_CNF_FLG_VM2VM_SOFTWARE (1 << 1) +#define VS_CNF_FLG_PROMISCOUS_EN (1 << 2) +#define VS_CNF_FLG_JUMBO_EN (1 << 3) +#define VS_CNF_FLG_VLAN_STRIP_EN (1 << 4) +#define VS_CNF_FLG_STATS_EN (1 << 5) + +/*API for vswitch implementations*/ +struct vswitch_dev *vs_register_switch(const char *name, int priv_size, + int max_ports, struct vswitch_ops *ops); +int vs_unregister_switch(struct vswitch_dev *dev); + +int vs_vswitch_init(void); + + +/*API for user of vswitch like vhost-switch application */ + +struct vswitch_dev *vs_get_vswitch_dev(const char *name); +struct vswitch_port *vs_add_port(struct vswitch_dev *vs_dev, int port_id, + enum vswitch_port_type type, void *priv); + +int vs_del_port(struct vswitch_port *port); + +int vs_switch_dev_init(struct vswitch_dev *vs_dev, uint16_t conf_flags); + +int vs_port_start(struct vswitch_port *vs_port); +int vs_port_stop(struct vswitch_port *vs_port); +int vs_learn_port(struct vswitch_port *port, struct rte_mbuf + **pkts, uint16_t count); +int vs_unlearn_port(struct vswitch_port *port); +int vs_lookup_n_fwd(struct vswitch_port *in_port, struct rte_mbuf + **pkts, uint16_t count, uint16_t in_rxq); + +int vs_do_broadcast_fwd(struct vswitch_dev *vs_dev, + struct vswitch_port *in_port, struct rte_mbuf *mbuf); + +struct vswitch_port *vs_sched_tx_port(struct vswitch_dev *vs_dev, enum + vswitch_port_type ptype, uint16_t core_id); + +struct vswitch_port *vs_sched_rx_port(struct vswitch_dev *vs_dev, enum + vswitch_port_type ptype, uint16_t core_id); +/*Extern APIs from vhost/main.c */ + +extern struct mbuf_table *vhost_switch_get_txq(uint16_t core_id); +extern int virtio_tx_local(struct vhost_dev *vdev, struct rte_mbuf *m); +extern struct vhost_dev *find_vhost_dev(struct ether_addr *mac); +void do_drain_mbuf_table(struct mbuf_table *tx_q); + +/* TBD:XXX: This needs to be removed here, when constructor mechanism + * for registering swittches is in place + */ +extern void vmdq_switch_impl_init(void); +#endif + -- 1.9.1