From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM01-BY2-obe.outbound.protection.outlook.com (mail-by2nam01on0068.outbound.protection.outlook.com [104.47.34.68]) by dpdk.org (Postfix) with ESMTP id 9C5F4568C for ; Sun, 4 Sep 2016 12:23:23 +0200 (CEST) Received: from BLUPR0301CA0031.namprd03.prod.outlook.com (10.162.113.169) by MWHPR03MB2448.namprd03.prod.outlook.com (10.169.200.142) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id 15.1.609.9; Sun, 4 Sep 2016 10:23:21 +0000 Received: from BL2FFO11FD024.protection.gbl (2a01:111:f400:7c09::131) by BLUPR0301CA0031.outlook.office365.com (2a01:111:e400:5259::41) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id 15.1.609.9 via Frontend Transport; Sun, 4 Sep 2016 10:23:20 +0000 Authentication-Results: spf=fail (sender IP is 192.88.158.2) 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.158.2 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.158.2; helo=az84smr01.freescale.net; Received: from az84smr01.freescale.net (192.88.158.2) by BL2FFO11FD024.mail.protection.outlook.com (10.173.161.103) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.587.6 via Frontend Transport; Sun, 4 Sep 2016 10:23:19 +0000 Received: from BuildMachinepc.ap.freescale.net (BuildMachinepc.ap.freescale.net [10.232.133.79]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id u84ANCDQ024782; Sun, 4 Sep 2016 03:23:16 -0700 From: Pankaj Chauhan To: CC: , , , , Pankaj Chauhan Date: Mon, 5 Sep 2016 16:24:29 +0530 Message-ID: <1473072871-16108-2-git-send-email-pankaj.chauhan@nxp.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1473072871-16108-1-git-send-email-pankaj.chauhan@nxp.com> References: <1473072871-16108-1-git-send-email-pankaj.chauhan@nxp.com> X-EOPAttributedMessage: 0 X-Matching-Connectors: 131174582000644947; (91ab9b29-cfa4-454e-5278-08d120cd25b8); () X-Forefront-Antispam-Report: CIP:192.88.158.2; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(7916002)(2980300002)(1110001)(1109001)(339900001)(199003)(189002)(626004)(104016004)(68736007)(5003940100001)(92566002)(189998001)(305945005)(110136002)(97736004)(7846002)(47776003)(356003)(8666005)(86362001)(76176999)(50986999)(50466002)(5660300001)(8676002)(81166006)(81156014)(48376002)(50226002)(2950100001)(586003)(2351001)(229853001)(77096005)(105606002)(106466001)(8936002)(33646002)(36756003)(4326007)(2906002)(85426001)(19580395003)(19580405001)(87936001)(69596002)(41533002)(7059030)(21314002); DIR:OUT; SFP:1101; SCL:1; SRVR:MWHPR03MB2448; H:az84smr01.freescale.net; FPR:; SPF:Fail; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BL2FFO11FD024; 1:sqJ9oZJ13c2AgwojGeiRjS5xZXAPbwCTE8kTmXlPoJQBb7AjFbTIFlqSwbfpKppPF1+PogmjPm0LdESHgNV3El/PmRjyKTTwzvhX8Ybz05oZqjd1I5NCdQZrzQaIScg9Pyk6ZIAHXE/rdEytmlvduNtMuR93+JnFtJFYY8pjnCEFulhveneFA1jpMi5U8wzaKjJgxGEFwmpDhLUGi+RkPLNaxNALGhfFMOUXIvssKF/iJ+XN7EjswQYGqmCcXvnn5nNZc/ZNrKgUqISeNAiZOb/VJIyFbIa0U4HnHQEvSeSjoHJRf6gjh8GyaZ0bGQA2lBksO22CA3ntrFEIEO8T/D8TjHb8q+J8jWhi2RWJ2RzrjhSuMYIUvjElS6ZW2icQIhQahltoEBwAkWMqwmkwQWf5pwyJXHPqkUEtX84Qd6hNjzS3lMR5OIRMIKXUSeFeKABAt3S95Gg1b4LnAb2T4MomBm1iJQixZF5ZDbobk9nB3wAT1VHUy+EH+tH0z2w3EO4UxFvzF18UC07LPJGhymr2f7pKt0p3R8/zrQ3FJVF0WYybuk0CnT8xTiAz/NbS6kTsDtDOs7ihX8R67BQdNuXDKQZoCwB4NkJi9NS1g7mE+k01DSgCYZL9VeYoZkVa3fcOZ7TNRqCinzt+kxdtpWj6JmMkn+ACbfOQnsfTy5OI4ITtD1PAN9Jfv955+Fu1lzD4kg/e5cA64eUCTAXnfZDV0/rXo3NBQng+q6qpYS+9l09tcnUp1HDea7OuM5KoGUsK+PQgf7MWFRfECe27Sw== MIME-Version: 1.0 Content-Type: text/plain X-MS-Office365-Filtering-Correlation-Id: cfe63868-d360-4628-11f2-08d3d4ad7e2a X-Microsoft-Exchange-Diagnostics: 1; MWHPR03MB2448; 2:/qLxYwwABohnNxws12aCE8jxuuFdxi66ZLY33c9Wuatl5NJZwcT7RhKYMDZeOx3PIJ3sYrazaoeBfqk9tONuUzEf0foS7GX6iJJPi456gHytd+cV/NnqGBMRTczbfPvm2H/h0rG5nT29dZ4wFuRjtDKFB/qgwpBpoMIkonT1lGziPCo5w/V+5w2Ybana3eJc; 3:j4DT44AJ4HtMpztXny4SdwgIgRRJMB1boK9W6Z3MutUBUQN2jvxkmdQn6Jr6nBDq+fDLpnfupVLZkC7nV1GoQPz3isyxspNgc5QwH1VpxbDt+cYmDr5Dn5z/FMAwbbDieuicwW5co0iApzhsFAeL6VznogWSPV3kTckt+WTPNX0sjahdCV9KriPm8Zt9e2bGO6xhd/Hk0nj0LAwkHOrsvsnzEHOcIbosAoExho11JPQ= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:MWHPR03MB2448; X-Microsoft-Exchange-Diagnostics: 1; MWHPR03MB2448; 25:JZsEdpg2Vs8sWsN2xIUs2JqW9DXPDtPn0n2+173GBUtVenDItCiLH9BR598HBZAwlU65wMcNKXi+G7J7wIMBiUp3T6ats0jccA96V80OZdeFzcDLUzYxgtUlVv7yz3u41QBxYG27OIMl1vHYuMfzX7ch/bCka5zrCVYv6ZKmJ2pQcjhLyEo8NKiNnpoAZIFaRxozWgoEpXX0J+R06rqUyWg/0InA9zi6FWXSCod1llRUbEJJpym0LIp5Z4sRKkpe70ht2Gj1V4Q9pUu057ljkgzEJ/66xRf7ELI2e7uYDZfG1edeN0bzXwp3r8f0i5VGTzfl/A0Byj7DMtuok5HbPHEPPU59lt0oBMIW/4/xA0AbfYgdlnmqYlrUD5DrAPtb0khlizTnjY+HbDH1ExAnzcJXShHnAG5+eB/CNcUmDAYmcp2CcbHRzFg44Mt2GzwxaqoZRlQTwUvF4wUVWvzynY6RcOo6LSgNviyS8QKZNSCAQKpIbQ4b5uFs7cbUOb2MLmeeWhfA+TIlUnIB5jbmO8a1zGKqa65Oe1SYE81P0wOYGY7W+BcIRstki7El0bUDVzVBweyPUU/OdKlcCOmpoRAwFAPD+kG/PoacVsFf5JcINvRM/BIhiFpwD7H63Jj4SyeFqesDF7yXSJqQRJhBgeEPiTUyBz7Z+ToGkNTqsaXI6lbhjTCf6icSKpxNAddvAJXAalBV0YKDFZ9vCSYPbUrI7KyxgU89nbjkLSg91YtAYb1qJnUwm0jKRSfuGAIW X-Microsoft-Exchange-Diagnostics: 1; MWHPR03MB2448; 31:BMLKgMEuEGE08OxXH9ClzxLj6oixzDHawYcIrClPnVmyyemPZekgLV38E5N3ex1ngRf0Cg3RWuak2U/lUtCLceXrUB9adAhyydU4aTvZm01SH7DWk1XTy+YktoPofHsKmH6697rR1AzlwxPQC2g5N7PsREpbOfaFgFDS2MDxpClQUI1aggFIJiYOZ4FMadVB+FZtans7buff5DibDFhWyI3I4JZ+wSemktWHAotGm0A=; 4:FWKpm0VdMdReTYu4laqdy+HotkYRbkarqv06c8u1J3R4Hp1vuRMrWWM2UJk1T7x5enhw/U2PD+mha4sNKCJ19VvI3FI47526f+fKY7k5SkFSXwur4k0PTp6QEQVh/dGeLUC/gNOxPCXfSlMxBk9lGkoWQB2M3pTbzuFx3m6XmH2C8HgK1UJh4dC4Wwz30koKGDGAmhE5e9Z6w1h/NkqG8acMXP6XcULjKe6be+s5OYJlV3LUWFvvOdR602NIMPiXlDelAqtNnNIzIeYR0pYlTNFgDt3HXpZdhj7NE8oEL+tJd8fKcnNZjdl30Yh2jQUbuhdtyJ3r9yayrrBHb3kXXJwv4Su3x5qUA3IK+XWNUwbDmPbT9cQulFQgiL4W8Pac6iaSnZbuxxfrglQZLxh1p1KcqeTx56FWVJr9B10pWGw9DFunY4vohPR8xbjwNutke8jrIBoq2kPpXOD7UtkvacRcsVRjuhpb5Fb2JxebpksfinzO3yLUjdUznNzHeStMH15G66BfIBqlLx0W00IowFZ80ZoYZhKtQaV6i9uiQlfLyB2EU/0N4k5ZrcbbFe4s X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(185117386973197)(788757137089); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040176)(601004)(2401047)(13015025)(13017025)(13023025)(13024025)(13018025)(5005006)(8121501046)(3002001)(10201501046)(6055026); SRVR:MWHPR03MB2448; BCL:0; PCL:0; RULEID:(400006); SRVR:MWHPR03MB2448; X-Forefront-PRVS: 00550ABE1F X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; MWHPR03MB2448; 23:XoJ+aSScaYHiH824Orjqx/FT5DRdf8re9l0PR7NGs?= =?us-ascii?Q?tqT2hybKyaMGtyZvoB6LYD8KxBYLkrrhyaHPhr93NRTD63XqUGpzvx93Tbkw?= =?us-ascii?Q?49lbfxARZn1NjaHXeh4NSM8mdlzRhKgOjqyoJOnktWs9c3MsTVmKltXkGw8M?= =?us-ascii?Q?56q/ZuhqMfim34bfnT7aPvsdlWdnueZcMw8ZNF86e2SgIAVG0Xwnj9YFOEOJ?= =?us-ascii?Q?QxvVBog5kGbyFJGvmOKyd1h0YP1J0/NevGVZswtJR1kX0FyK7V5n3JlLOQjo?= =?us-ascii?Q?S41NjLE4RXfR3UZDRCGn2gJ2YCDu3N+herQ6FXsfnhQ+iG9OTqQI8oWAT8oV?= =?us-ascii?Q?ycKmd2HvOp1hpRsJVnox6UDnCIRdxgYiuKoo62Y9h+BAdwg2XmeBe8YWLVdN?= =?us-ascii?Q?V0UjFADLjNwvMRd3sbAqpL/BxR5VPh0p4qw0WY2hOMCR7HwDVVsLOI4HXzs4?= =?us-ascii?Q?MwKqhXM7bpCAa2C6cQyFcql2dOJsXBEpSaP2+zPmS7oLdS8oLD+AYR2vXO33?= =?us-ascii?Q?EaLqbAJOEjxBL99WzdBDBvaebY3agdi+nBiudHj9k65xFtXFOPiuDPYjiREW?= =?us-ascii?Q?o0nd/U9nthysvdBktMGyuixR4dy+gmv2Ydv6vVcTAHV9bSUUNURW3LMNxXFb?= =?us-ascii?Q?d2KpFDwnqvgoR/9jURoqMC3Yqd9xnIK9uF5X959x+29FOkLmBGc48SGZ4xKm?= =?us-ascii?Q?4zHdWt9ANcc/xAMhLMPqQVNaPQkaQY/883x4l0ZE7Fp5pn2BL3ikzLlusvKS?= =?us-ascii?Q?OVolOBDsBCKOY7pF1O5q7HhF57KQbPSbOLmk5i17mLkMa8yYMgL1YVEoNh0a?= =?us-ascii?Q?TccJQZyj/X1cuLpy67KmoD68lTfTAue2OZD3LeZdtjxCMj7h1nyw5DWlBLPN?= =?us-ascii?Q?EnwT80OlgZ1tJlW7mLs7lFi2LfOA/J5/slvCNrA325UMJ2cDxB50IugTcWfz?= =?us-ascii?Q?7y2PUFjzZ6mW6kszMW5Nl7K6VU6B2/j735PIEeZZMx89GsNSoVedt0K7JJo7?= =?us-ascii?Q?0NXZNhcTwvKDjwFJMNWfJT8fMWVINcQKsAepFAM/eJI93pyPIqYx5PRFyWhk?= =?us-ascii?Q?Dq4NA3hdyjVxnq/LRHd+VSwjuVTIC/w/EaupBC3OnlkKWlRqN7U1lNEjbkzv?= =?us-ascii?Q?q5u/g+jdb9RU+rSG+Q/neJVF+TYZhndeAa3/5E7jQGs3dXEUauKoenzVqFIO?= =?us-ascii?Q?TQ4anYzvpM1m07uDqW6cMYoDjGL/Ofl69AW?= X-Microsoft-Exchange-Diagnostics: 1; MWHPR03MB2448; 6:0jp/5YCRVLMEGkVTF1Ve3c9N3kT9Jq3FxWLe74cbUJkmPda0v17vVzBxflI16Yefs0Q5cUiHJ1rRWndVrKrScRZvkMoV+04SnkEtaAYMm3jeFwyiawl4WgrOTKotOH1nStRqmESap0rEW3agRtWNWodHfTbeQASw7qVkzQVd8Xzt0stFdCO7dCTbN2vz0AV00TcHxoTqJ0wx8ZwtXJDUaNrlpsQgiG+HV74CD78EvmSVr5LxvebMpvjaMEce5P9IyvJgpDTsC91lSHDWL6KI9vzQDojmyMEifNOF8UJyek0=; 5:QNPk7GOcIFzxX9ph53eEn3rPf/2Sp1hHyOwN0ZY8AG+2Gl7jZ+eqsOi5iYsW/7o5UNIYnRss6oV/+9taOW/RYDs/eWVD8zVIsXxQOCN/qnh/aXU58vc1rt6iaLQ+znhZEZNN4nzr5QpV0i05XCa5ujThY5ZIxIgZH8w+R0WIHrg=; 24:51GemSayrHmyIuKe4w9zHtsFUqQss7Y5nNyHMgoZUNAJU9rnWPV2w+WiqDtJMo4q4ZX/4TFWEJd47T25GAsthU0IVV+yGBWJxOD3hM0P61c=; 7:g9AOwUmuz7/oplA76yUq5EDgRgIzeAbZUa4zGYfDHGIsyPf6bQ3k+DIzLLCYxZUIJef9awrCrM/de/e6tW8o6KXXUxIH5FwUyA2zWnOWXBwza1KoPtsu/f8f1fgizm2GZOiVbxZ2J7kMgiX+2ditj2SF7zvqlXQxECE2irDf349i0UJe7sLhKdxREC6jvVg5z0JytdS3hIg+CfDUPDCYPHIJpWvE+FRlZ1Iat3vOEeiz9/cZ0DDp1oojiWJig2Ft SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 04 Sep 2016 10:23:19.8148 (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.158.2]; Helo=[az84smr01.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR03MB2448 Subject: [dpdk-dev] [RFC][PATCH V2 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: Sun, 04 Sep 2016 10:23:24 -0000 Introduce support for a generic framework for handling of switching between physical and vhost devices. The vswitch framework introduces the following concept: 1. vswitch_dev: Vswitch device is a logical switch which can have physical and virtio devices. The devices are operated/used using standard rte_eth API for physical devices and lib_vhost API for vhost devices, PMD API is not used for vhost devices. 2. vswitch_port: Any physical or virtio device that is added to vswitch. The port can have its 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). Similarly each port has its own functions to select tx/rx queues. The framework provides default tx/rx queue selection functions to the port when port is added (for both physical and vhost devices). But the framework allows the switch implementation to override the queue selection functions (vs_port->get_txq/rxq) if required. 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 implementation. 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/main.c | 128 +++++++++-- examples/vhost/vswitch_common.c | 499 ++++++++++++++++++++++++++++++++++++++++ examples/vhost/vswitch_common.h | 186 +++++++++++++++ examples/vhost/vswitch_txrx.c | 97 ++++++++ examples/vhost/vswitch_txrx.h | 71 ++++++ 6 files changed, 966 insertions(+), 17 deletions(-) create mode 100644 examples/vhost/vswitch_common.c create mode 100644 examples/vhost/vswitch_common.h create mode 100644 examples/vhost/vswitch_txrx.c create mode 100644 examples/vhost/vswitch_txrx.h diff --git a/examples/vhost/Makefile b/examples/vhost/Makefile index e95c68a..1b58308 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 vswitch_txrx.c vmdq.c CFLAGS += -O2 -D_FILE_OFFSET_BITS=64 CFLAGS += $(WERROR_FLAGS) diff --git a/examples/vhost/main.c b/examples/vhost/main.c index 92a9823..c949df4 100644 --- a/examples/vhost/main.c +++ b/examples/vhost/main.c @@ -811,9 +811,16 @@ static inline void __attribute__((always_inline)) virtio_xmit(struct vhost_dev *dst_vdev, struct vhost_dev *src_vdev, struct rte_mbuf *m) { - uint16_t ret; + uint16_t ret, txq; + struct vswitch_port *vs_port = dst_vdev->vs_port; - ret = rte_vhost_enqueue_burst(dst_vdev->vid, VIRTIO_RXQ, &m, 1); + /* The switch implmentation decides the txq for each port itself. + * this gives switch implmentations to choose thier own queue management + * for each port + */ + + txq = vs_port->get_txq(vs_port, rte_lcore_id()); + ret = rte_vhost_enqueue_burst(dst_vdev->vid, txq, &m, 1); if (enable_stats) { rte_atomic64_inc(&dst_vdev->stats.rx_total_atomic); rte_atomic64_add(&dst_vdev->stats.rx_atomic, ret); @@ -832,7 +839,7 @@ virtio_tx_local(struct vhost_dev *vdev, struct rte_mbuf *m) struct ether_hdr *pkt_hdr; struct vhost_dev *dst_vdev; - pkt_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); + pkt_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); dst_vdev = find_vhost_dev(&pkt_hdr->d_addr); if (!dst_vdev) @@ -934,11 +941,26 @@ static inline void __attribute__((always_inline)) do_drain_mbuf_table(struct mbuf_table *tx_q) { uint16_t count; + struct vswitch_port *tx_port; + + /* Let switch implmentation decide which physical port to do tx to. + * Every switch implmentation may have it's own strategy, for example + * VMDQ does tx to only one Physical port. Having a scheduler function + * which is switch specefic give flexibility to have another strategy + * for a switch + */ + tx_port = vs_sched_tx_port(vswitch_dev_g, VSWITCH_PTYPE_PHYS, + rte_lcore_id()); + if (unlikely(!tx_port)) + goto out; - count = rte_eth_tx_burst(ports[0], tx_q->txq_id, - tx_q->m_table, tx_q->len); - if (unlikely(count < tx_q->len)) - free_pkts(&tx_q->m_table[count], tx_q->len - count); + if (tx_q->len) { + count = tx_port->do_tx(tx_port, tx_q->txq_id, NULL, tx_q->m_table, + tx_q->len); + + if (unlikely(count < tx_q->len)) + free_pkts(&tx_q->m_table[count], tx_q->len - count); + } tx_q->len = 0; } @@ -1060,6 +1082,28 @@ drain_eth_rx(struct vhost_dev *vdev) { uint16_t rx_count, enqueue_count; struct rte_mbuf *pkts[MAX_PKT_BURST]; + uint16_t rxq, core_id; + struct vswitch_port *rx_port; + + + core_id = rte_lcore_id(); + /* Let switch implmentation decide which physical port to do rx from. + * Every switch implmentation may have it's own strategy, for example + * VMDQ does rx from only one Physical port. Having a scheduler function + * which is switch specefic give flexibility to have another strategy + * for a switch + */ + rx_port = vs_sched_rx_port(vswitch_dev_g, VSWITCH_PTYPE_PHYS, + core_id); + if (unlikely(!rx_port)) + goto out; + + /* The switch implmentation decides the rxq for each port itself. + * this gives switch implmentations to choose thier own queue management + * for each port + */ + rxq = rx_port->get_rxq(rx_port, vdev, core_id); + rx_count = rx_port->do_rx(rx_port, rxq, NULL, pkts, MAX_PKT_BURST); rx_count = rte_eth_rx_burst(ports[0], vdev->vmdq_rx_q, pkts, MAX_PKT_BURST); @@ -1098,20 +1142,31 @@ static inline void __attribute__((always_inline)) drain_virtio_tx(struct vhost_dev *vdev) { struct rte_mbuf *pkts[MAX_PKT_BURST]; - uint16_t count; - uint16_t i; + struct vswitch_port *vs_port = vdev->vs_port; + uint16_t count, rxq, core_id; + + /* The switch implmentation decides the rxq for each port itself. + * this gives switch implmentations to choose thier own queue management + * for each port + */ - count = rte_vhost_dequeue_burst(vdev->vid, VIRTIO_TXQ, mbuf_pool, + core_id = rte_lcore_id(); + rxq = vs_port->get_rxq(vs_port, NULL, core_id); + count = rte_vhost_dequeue_burst(vdev->vid, rxq, mbuf_pool, pkts, MAX_PKT_BURST); - /* setup VMDq for the first packet */ - if (unlikely(vdev->ready == DEVICE_MAC_LEARNING) && count) { - if (vdev->remove || link_vmdq(vdev, pkts[0]) == -1) + if (unlikely(!count)) + goto out; + + if (unlikely(vdev->ready == DEVICE_MAC_LEARNING)) { + if (vdev->remove || vs_learn_port(vs_port, pkts, count)) free_pkts(pkts, count); } - for (i = 0; i < count; ++i) - virtio_tx_route(vdev, pkts[i], vlan_tags[vdev->vid]); + vs_lookup_n_fwd(vs_port, pkts, count, VIRTIO_RXQ); + +out: + return; } /* @@ -1241,7 +1296,7 @@ static int new_device(int vid) { int lcore, core_add = 0; - uint32_t device_num_min = num_devices; + uint32_t device_num_min; struct vhost_dev *vdev; vdev = rte_zmalloc("vhost device", sizeof(*vdev), RTE_CACHE_LINE_SIZE); @@ -1252,6 +1307,16 @@ new_device(int vid) return -1; } vdev->vid = vid; + device_num_min = vs_get_max_vdevs(vswitch_dev_g); + RTE_LOG(INFO, VHOST_PORT, "max virtio devices %d\n", device_num_min); + + vs_port = vs_add_port(vswitch_dev_g, vid, VSWITCH_PTYPE_VIRTIO, vdev); + + if (!vs_port) { + rte_exit(EXIT_FAILURE, "Failed to add port [%d] to vsdev %s\n", + vs_port->port_id, vswitch_dev_g->name); + } + vdev->vs_port = vs_port; TAILQ_INSERT_TAIL(&vhost_dev_list, vdev, global_vdev_entry); vdev->vmdq_rx_q = vid * queues_per_pool + vmdq_queue_base; @@ -1277,6 +1342,10 @@ new_device(int vid) rte_vhost_enable_guest_notification(vid, VIRTIO_RXQ, 0); rte_vhost_enable_guest_notification(vid, VIRTIO_TXQ, 0); + RTE_LOG(INFO, VHOST_PORT, "New virtio port %d\n", vid); + + vs_port_start(vs_port); + RTE_LOG(INFO, VHOST_DATA, "(%d) device has been added to data core %d\n", vid, vdev->coreid); @@ -1402,6 +1471,31 @@ create_mbuf_pool(uint16_t nr_port, uint32_t nr_switch_core, uint32_t mbuf_size, rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); } +static uint64_t get_vswitch_conf_flags(void) +{ + uint64_t vs_conf_flags = 0; + + if (vm2vm_mode == VM2VM_HARDWARE) + vs_conf_flags |= VS_CNF_FLG_VM2VM_HARDWARE; + + if (vm2vm_mode == VM2VM_SOFTWARE) + vs_conf_flags |= VS_CNF_FLG_VM2VM_SOFTWARE; + + if (promiscuous) + vs_conf_flags |= VS_CNF_FLG_PROMISCOUS_EN; + + if (jumbo_frame_en) + vs_conf_flags |= VS_CNF_FLG_JUMBO_EN; + + if (enable_stats) + vs_conf_flags |= VS_CNF_FLG_STATS_EN; + + if (vlan_strip) + vs_conf_flags |= VS_CNF_FLG_VLAN_STRIP_EN; + + return vs_conf_flags; +} + /* * Main function, does initialisation and calls the per-lcore functions. The CUSE * device is also registered here to handle the IOCTLs. @@ -1484,6 +1578,7 @@ main(int argc, char *argv[]) "Cannot initialize network ports\n"); } + RTE_LOG(INFO, VHOST_CONFIG, "PORT init done \n"); /* Enable stats if the user option is set. */ if (enable_stats) { ret = pthread_create(&tid, NULL, (void *)print_stats, NULL); @@ -1499,6 +1594,7 @@ main(int argc, char *argv[]) "Cannot set print-stats name\n"); } + RTE_LOG(INFO, VHOST_CONFIG, "Launching switch_worker threads \n"); /* Launch all data cores. */ RTE_LCORE_FOREACH_SLAVE(lcore_id) rte_eal_remote_launch(switch_worker, NULL, lcore_id); diff --git a/examples/vhost/vswitch_common.c b/examples/vhost/vswitch_common.c new file mode 100644 index 0000000..9f9ab87 --- /dev/null +++ b/examples/vhost/vswitch_common.c @@ -0,0 +1,499 @@ +/*- + * 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" +#include "vswitch_txrx.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 dev_count; + LIST_HEAD(, vswitch_dev) head; +}; + +static struct vs_mdata *vs_mdata_g; + +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->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, found = 0; + struct vswitch_port *vs_port = NULL; + + rte_spinlock_lock(&vs_dev->lock); + + for (i = 0; i < vs_dev->port_count; i++) { + vs_port = &vs_dev->ports[i]; + if (vs_port->state == VSWITCH_PSTATE_NOT_INUSE) { + found = 1; + break; + } + } + + if (found) + vs_port->state = VSWITCH_PSTATE_BEING_ALLOCATED; + else + vs_port = NULL; + + rte_spinlock_unlock(&vs_dev->lock); + return vs_port; +} + +static void vs_free_port(struct vswitch_port *vs_port) +{ + struct vswitch_dev *vs_dev = vs_port->vs_dev; + + rte_spinlock_lock(&vs_dev->lock); + vs_port->state = VSWITCH_PSTATE_NOT_INUSE; + rte_spinlock_unlock(&vs_dev->lock); +} + +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; + + /* Initialize default port operations. It should be noted that + * The switch ops->add_port can replace them with switch specefic + * operations if required. This gives us more flexibility in switch + * implementations. + */ + + switch (type) { + case VSWITCH_PTYPE_PHYS: + vs_port->do_tx = vs_do_tx_phys_port; + vs_port->do_rx = vs_do_rx_phys_port; + vs_port->get_txq = vs_get_txq_phys_port; + vs_port->get_rxq = vs_get_rxq_phys_port; + break; + case VSWITCH_PTYPE_VIRTIO: + vs_port->do_tx = vs_do_tx_virtio_port; + vs_port->do_rx = vs_do_rx_virtio_port; + vs_port->get_txq = vs_get_txq_virtio_port; + vs_port->get_rxq = vs_get_rxq_virtio_port; + break; + 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, uint32_t txport_type_mask, + 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]; + /*Do not broadcast on incomming port */ + if ((in_port->type == dest_port->type) && + (in_port->port_id == dest_port->port_id)) + continue; + if (!(VS_PTYPE_MASK(dest_port->type) & txport_type_mask)) + continue; + + tx_q = dest_port->get_txq(dest_port, 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; +} + +static int vs_check_mandatory_ops(struct vswitch_ops *ops) +{ + int rc = 0; + + if (!ops->lookup_n_fwd){ + RTE_LOG(ERR, VHOST_CONFIG, "lookup_n_fwd is NULL"); + rc = -EINVAL; + } + if (!ops->learn_port){ + RTE_LOG(ERR, VHOST_CONFIG, "learn_port is NULL"); + rc = -EINVAL; + } + + if (!ops->unlearn_port){ + RTE_LOG(ERR, VHOST_CONFIG, "unlearn_port is NULL"); + rc = -EINVAL; + } + + + return rc; +} + +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; + + if (vs_check_mandatory_ops(ops)) { + RTE_LOG(ERR, VHOST_CONFIG, "%s: mandatory ops missing\n", + name); + return NULL; + } + + 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_port->vs_dev = vs_dev; + } + + vs_dev->port_count = max_ports; + vs_dev->ops = ops; + rte_spinlock_init(&vs_dev->lock); + + rte_spinlock_lock(&vs_mdata_g->lock); + LIST_INSERT_HEAD(&vs_mdata_g->head, vs_dev, list); + vs_mdata_g->dev_count++; + rte_spinlock_unlock(&vs_mdata_g->lock); + + RTE_LOG(INFO, VHOST_CONFIG, "Added vswitch %s [0x%p], max_ports %d\n", + vs_dev->name, vs_dev, 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->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_get_max_vdevs(struct vswitch_dev *vs_dev) +{ + struct vswitch_ops *ops = vs_dev->ops; + + return ops->get_max_vdevs(vs_dev); +} + +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(ERR, VHOST_CONFIG, + "vhost vswitch mdata allocation failed\n"); + rc = -ENOMEM; + goto out; + } + + memset(vs_mdata_g, 0, sizeof(struct vs_mdata)); + LIST_INIT(&vs_mdata_g->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..a5800df --- /dev/null +++ b/examples/vhost/vswitch_common.h @@ -0,0 +1,186 @@ +/*- + * 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, +}; + +#define VS_PTYPE_MASK(type) (1 << type) + +enum vswitch_port_state { + VSWITCH_PSTATE_ADDED = 1, + VSWITCH_PSTATE_LEARNING, + VSWITCH_PSTATE_FORWARDING, + VSWITCH_PSTATE_NOT_INUSE, + VSWITCH_PSTATE_BEING_ALLOCATED, + 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); + uint16_t (*get_rxq) (struct vswitch_port *port, struct vhost_dev *vdev, + uint16_t core_id); + uint16_t (*get_txq) (struct vswitch_port *port, uint16_t core_id); +}; + +struct vswitch_dev { + char name[VSWITCH_NAME_SIZE]; + void *priv; /* Private for switch specefic + * data */ + uint64_t conf_flags; + rte_spinlock_t lock; + 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); +typedef int (*vs_get_max_vdevs_t) (struct vswitch_dev *); + +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; + vs_get_max_vdevs_t get_max_vdevs; +}; + +/*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, uint32_t txport_type_mask, + 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); +int vs_get_max_vdevs(struct vswitch_dev *vs_dev); + +/*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 diff --git a/examples/vhost/vswitch_txrx.c b/examples/vhost/vswitch_txrx.c new file mode 100644 index 0000000..23b38b9 --- /dev/null +++ b/examples/vhost/vswitch_txrx.c @@ -0,0 +1,97 @@ +/*- + * 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 "vswitch_common.h" +#include "vswitch_txrx.h" + +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); +} + + +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); +} + +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); +} + +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); +} + +uint16_t vs_get_rxq_phys_port(__attribute__((unused)) struct vswitch_port *port, + struct vhost_dev *vdev, __attribute__((unused))uint16_t core_id) +{ + struct vswitch_port *vdev_vs_port = vdev->vs_port; + + return vdev_vs_port->phys_port_rxq; +} + +uint16_t vs_get_txq_phys_port(__attribute__((unused)) struct vswitch_port *port, + uint16_t core_id) +{ + return core_id; +} + +uint16_t vs_get_rxq_virtio_port(__attribute__((unused)) struct vswitch_port *port, + __attribute__((unused))struct vhost_dev *vdev, + __attribute__((unused)) uint16_t core_id) +{ + return VIRTIO_TXQ; +} + +uint16_t vs_get_txq_virtio_port(__attribute__((unused))struct vswitch_port *port, + __attribute__((unused)) uint16_t core_id) +{ + return VIRTIO_RXQ; +} diff --git a/examples/vhost/vswitch_txrx.h b/examples/vhost/vswitch_txrx.h new file mode 100644 index 0000000..39d2dab --- /dev/null +++ b/examples/vhost/vswitch_txrx.h @@ -0,0 +1,71 @@ + +/*- + * 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 __VSWTICH_TXRX_H__ +#define __VSWTICH_TXRX_H__ + +#include +#include + +#include "vswitch_common.h" +#include "vswitch_txrx.h" + +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); + + +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); + +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); + +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); + +uint16_t vs_get_rxq_phys_port(struct vswitch_port *port, + struct vhost_dev *vdev, uint16_t core_id); + +uint16_t vs_get_txq_phys_port(struct vswitch_port *port, + uint16_t core_id); + +uint16_t vs_get_rxq_virtio_port(struct vswitch_port *port, + struct vhost_dev *vdev, uint16_t core_id); + +uint16_t vs_get_txq_virtio_port(struct vswitch_port *port, + uint16_t core_id); +#endif -- 1.9.1