Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2218457/?format=api
{ "id": 2218457, "url": "http://patchwork.ozlabs.org/api/patches/2218457/?format=api", "web_url": "http://patchwork.ozlabs.org/project/openvswitch/patch/20260401091318.2671624-9-elibr@nvidia.com/", "project": { "id": 47, "url": "http://patchwork.ozlabs.org/api/projects/47/?format=api", "name": "Open vSwitch", "link_name": "openvswitch", "list_id": "ovs-dev.openvswitch.org", "list_email": "ovs-dev@openvswitch.org", "web_url": "http://openvswitch.org/", "scm_url": "git@github.com:openvswitch/ovs.git", "webscm_url": "https://github.com/openvswitch/ovs", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260401091318.2671624-9-elibr@nvidia.com>", "list_archive_url": null, "date": "2026-04-01T09:13:15", "name": "[ovs-dev,v3,08/11] netdev-dpdk: Refactor common functions for reuse by netdev-doca.", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "449e81c66079d83a2791c77ac95c95d4c147a6b7", "submitter": { "id": 79848, "url": "http://patchwork.ozlabs.org/api/people/79848/?format=api", "name": "Eli Britstein", "email": "elibr@nvidia.com" }, "delegate": { "id": 75123, "url": "http://patchwork.ozlabs.org/api/users/75123/?format=api", "username": "echaudron", "first_name": "Eelco", "last_name": "Chaudron", "email": "echaudro@redhat.com" }, "mbox": "http://patchwork.ozlabs.org/project/openvswitch/patch/20260401091318.2671624-9-elibr@nvidia.com/mbox/", "series": [ { "id": 498297, "url": "http://patchwork.ozlabs.org/api/series/498297/?format=api", "web_url": "http://patchwork.ozlabs.org/project/openvswitch/list/?series=498297", "date": "2026-04-01T09:13:07", "name": "netdev-doca", "version": 3, "mbox": "http://patchwork.ozlabs.org/series/498297/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2218457/comments/", "check": "success", "checks": "http://patchwork.ozlabs.org/api/patches/2218457/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<ovs-dev-bounces@openvswitch.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "dev@openvswitch.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "ovs-dev@lists.linuxfoundation.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n unprotected) header.d=Nvidia.com header.i=@Nvidia.com header.a=rsa-sha256\n header.s=selector2 header.b=QNAcx5d5;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=140.211.166.138; helo=smtp1.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)", "smtp1.osuosl.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key,\n unprotected) header.d=Nvidia.com header.i=@Nvidia.com header.a=rsa-sha256\n header.s=selector2 header.b=QNAcx5d5", "smtp2.osuosl.org;\n dmarc=pass (p=reject dis=none) header.from=nvidia.com", "smtp2.osuosl.org; dkim=pass (2048-bit key,\n unprotected) header.d=Nvidia.com header.i=@Nvidia.com header.a=rsa-sha256\n header.s=selector2 header.b=QNAcx5d5" ], "Received": [ "from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4flzrH5WN7z1yGH\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 01 Apr 2026 20:16:31 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby smtp1.osuosl.org (Postfix) with ESMTP id DC31E81FAF;\n\tWed, 1 Apr 2026 09:16:28 +0000 (UTC)", "from smtp1.osuosl.org ([127.0.0.1])\n by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id tdXSPAxPum24; Wed, 1 Apr 2026 09:16:25 +0000 (UTC)", "from lists.linuxfoundation.org (lf-lists.osuosl.org\n [IPv6:2605:bc80:3010:104::8cd3:938])\n\tby smtp1.osuosl.org (Postfix) with ESMTPS id 8AEAD821B7;\n\tWed, 1 Apr 2026 09:16:25 +0000 (UTC)", "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 43741C003D;\n\tWed, 1 Apr 2026 09:16:25 +0000 (UTC)", "from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 036BEC003D\n for <dev@openvswitch.org>; Wed, 1 Apr 2026 09:16:23 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n by smtp2.osuosl.org (Postfix) with ESMTP id 837704088E\n for <dev@openvswitch.org>; Wed, 1 Apr 2026 09:15:26 +0000 (UTC)", "from smtp2.osuosl.org ([127.0.0.1])\n by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id BiPa-qdss1lX for <dev@openvswitch.org>;\n Wed, 1 Apr 2026 09:15:21 +0000 (UTC)", "from PH8PR06CU001.outbound.protection.outlook.com\n (mail-westus3azlp170120001.outbound.protection.outlook.com\n [IPv6:2a01:111:f403:c107::1])\n by smtp2.osuosl.org (Postfix) with ESMTPS id 9A3994090D\n for <dev@openvswitch.org>; Wed, 1 Apr 2026 09:15:20 +0000 (UTC)", "from PH7PR02CA0003.namprd02.prod.outlook.com (2603:10b6:510:33d::31)\n by DM6PR12MB4402.namprd12.prod.outlook.com (2603:10b6:5:2a5::18) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9769.16; Wed, 1 Apr\n 2026 09:15:07 +0000", "from SA2PEPF000015C8.namprd03.prod.outlook.com\n (2603:10b6:510:33d:cafe::e8) by PH7PR02CA0003.outlook.office365.com\n (2603:10b6:510:33d::31) with Microsoft SMTP Server (version=TLS1_3,\n cipher=TLS_AES_256_GCM_SHA384) id 15.20.9745.30 via Frontend Transport; Wed,\n 1 Apr 2026 09:14:52 +0000", "from mail.nvidia.com (216.228.117.161) by\n SA2PEPF000015C8.mail.protection.outlook.com (10.167.241.198) with Microsoft\n SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n 15.20.9769.17 via Frontend Transport; Wed, 1 Apr 2026 09:15:07 +0000", "from rnnvmail201.nvidia.com (10.129.68.8) by mail.nvidia.com\n (10.129.200.67) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.20; Wed, 1 Apr\n 2026 02:14:49 -0700", "from nvidia.com (10.126.231.35) by rnnvmail201.nvidia.com\n (10.129.68.8) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.20; Wed, 1 Apr\n 2026 02:14:46 -0700" ], "X-Virus-Scanned": [ "amavis at osuosl.org", "amavis at osuosl.org" ], "X-Comment": "SPF check N/A for local connections -\n client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN> ", "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 smtp1.osuosl.org 8AEAD821B7", "OpenDKIM Filter v2.11.0 smtp2.osuosl.org 9A3994090D" ], "Received-SPF": [ "Pass (mailfrom) identity=mailfrom;\n client-ip=2a01:111:f403:c107::1;\n helo=ph8pr06cu001.outbound.protection.outlook.com;\n envelope-from=elibr@nvidia.com; receiver=<UNKNOWN>", "Pass (protection.outlook.com: domain of nvidia.com designates\n 216.228.117.161 as permitted sender) receiver=protection.outlook.com;\n client-ip=216.228.117.161; helo=mail.nvidia.com; pr=C" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp2.osuosl.org 9A3994090D", "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n b=dm6gegaf+nwhGozpWgyHbhlOD50z3xJ3bMxjkorGdO26Wytx0WR4uw9VsKvK8pECCBJ+jEuVp6U8sjdGe69lJYAES5xdGTcxZJW6CgofALygMFf/tN4w7bF5beqO6z51vUbH4bZL8Q880JjErMENtD1Q0zE+va+nBLpMcL30XHIHDmBKB8w7VhG1RGmYUgUOpc8S3oaW0l38wC+gZymFfbo+drxVqVbqjs+sJ2QE5Y+KZRSl9XBoVTy8CyLKObwm3VwTTdYs5VH8J7XCWBnztu7YYNj8uFI5ggTyHsuTdXFNzGvDLgCZtAhrcf997MjKzmld7LFtAAsNAQLMozie6Q==", "ARC-Message-Signature": "i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector10001;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;\n bh=PUG5x4PHuGJiplWjsEIfr6jDi5vlD5HRom7yZ6uoFN8=;\n b=dh4AQ6gN6PtMIlPRQPqxpYpI9S5OVYln8T/HpcrSUoSnuJrYO61gPVXD/YgosgDmP65navRXGMrUZdC14/9x/zpBxeojbWvr4pMMsisWLFEIwRS+bvyfdUQFAqPAErcn+wBmb4H2LdQfeWAoiyJd8x07XBTa80losI+vIsdKRA07qqKt/ERXRu53FKbrPgpuNVrs/sCq7Ngl5UT33IVV9pA1OxtAqyurwHpO91zJFXy9Bi+To/9cbeTlGecc1jok8Bai+E7SsIAa2He1vKzZdW8Nf9fHyNPQti1uvyKhhqAvuCRiM6ai+blChidzETG8tIoxI9Grjog4DPk7FNDw3Q==", "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass (sender ip is\n 216.228.117.161) smtp.rcpttodomain=openvswitch.org smtp.mailfrom=nvidia.com;\n dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com;\n dkim=none (message not signed); arc=none (0)", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com;\n s=selector2;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=PUG5x4PHuGJiplWjsEIfr6jDi5vlD5HRom7yZ6uoFN8=;\n b=QNAcx5d5OdMOc5ik0PF/q3BCNMsOx1sdvdp4JUyxqHlG7Q8s7J+YD288bBWILdwWhXjK50ILFc2SSDeAxSWq3sLrraOE103XEc2k1km5OmlONFWzz2omgb9UiI4mELPEr1LA7J4eQFdvstygvxjrT/zVIHGePcgm7wUwqOAUW3o/2vMeWPEBmPvKYIsFzq/n2Db8XUhBt6csX+Ey2TAHIGOoAPsqKHOQn1r4XV5XZZIMfL9bOf7hfvj4EuTSXY1/IzfeH6X6BiCWjWiARGlDldLZz5P232XOefhKcGShWmHBf4k3v8JrvG71EOVzxIHk+jIMZbPtVwpQhjkfXO0S5w==", "X-MS-Exchange-Authentication-Results": "spf=pass (sender IP is 216.228.117.161)\n smtp.mailfrom=nvidia.com;\n dkim=none (message not signed)\n header.d=none;dmarc=pass action=none header.from=nvidia.com;", "From": "Eli Britstein <elibr@nvidia.com>", "To": "<dev@openvswitch.org>", "Date": "Wed, 1 Apr 2026 12:13:15 +0300", "Message-ID": "<20260401091318.2671624-9-elibr@nvidia.com>", "X-Mailer": "git-send-email 2.34.1", "In-Reply-To": "<20260401091318.2671624-1-elibr@nvidia.com>", "References": "<20260401091318.2671624-1-elibr@nvidia.com>", "MIME-Version": "1.0", "X-Originating-IP": "[10.126.231.35]", "X-ClientProxiedBy": "rnnvmail203.nvidia.com (10.129.68.9) To\n rnnvmail201.nvidia.com (10.129.68.8)", "X-EOPAttributedMessage": "0", "X-MS-PublicTrafficType": "Email", "X-MS-TrafficTypeDiagnostic": "SA2PEPF000015C8:EE_|DM6PR12MB4402:EE_", "X-MS-Office365-Filtering-Correlation-Id": "7616278f-2192-4484-27a3-08de8fcf2acc", "X-MS-Exchange-SenderADCheck": "1", "X-MS-Exchange-AntiSpam-Relay": "0", "X-Microsoft-Antispam": "BCL:0;\n ARA:13230040|82310400026|1800799024|376014|36860700016|18002099003|22082099003|56012099003;", "X-Microsoft-Antispam-Message-Info": "\n Q6d80iXL/Iin6YGOR5OU+ma2cbNjlnmuD+SCJ1FYO4kgPND8aBBi0YOnzu2slOiPp7z8oNbZPr7i06AVfqf4qPfHVzx7OtQnT29UcDIE78t17E+GqrtwMPR57BPkMl/gdDq4quGuRle/jJ9AsbTdhWKz7ZpA9ThOG3lAVHcT915JfMuhuAYM0iPfEVoSw1sfCGbr5vD2eZgM9R8kcMmIedTfMe2ECjrzU3+W8PQIKAXXZd8wqco0lPSvj8jnRj+JreoyrlUPyUZkgZSd1i5YrDoYGUoVZ5Hn5ye2y3iE4vPj9cPTYQ0vYJLj+eF87dOcSk8kw9jClrLQ9bbp+C/6ZGzZpuLSsr5z59bb966CGg/GtnwMJp52WEm471qy3OrZWX1D4sD+2CruRzu0uz5QeddGWX8GGVAtMUUqebrwioQi2u6mY/+7qBucpoah9M1DaPUzOSzQONWxeN9WtGXsTirtABzhyHs4hmZHhmZz8MOlizuwYagMkEroa3UpylvZxQd/WAo9t/LANL7RGTuYltZsQBWBE9wecj3Mn1RzdsCnJjQUq18UKwAP4l1IQfxjb4MVzSulWVca4mEYHtqQUqShec/kipK9F8kJxhprAyQ+P/g+C9dX5yNo4QITRzgBjoEQeUtJs0D+bpw5fUPxIgwsk8djjcMIXouw7pRgITCj1mLim5C+nHjUsdlhp7SPLJznukOqO5L+gBFJF9L/iol83PqNM4WSVmrDckbf41yiIcdHwBEMnbWnhGoH0Wjwad6f7kyxLwhbNFbB4OcVCA==", "X-Forefront-Antispam-Report": "CIP:216.228.117.161; CTRY:US; LANG:en; SCL:1;\n SRV:;\n IPV:NLI; SFV:NSPM; H:mail.nvidia.com; PTR:dc6edge2.nvidia.com; CAT:NONE;\n SFS:(13230040)(82310400026)(1800799024)(376014)(36860700016)(18002099003)(22082099003)(56012099003);\n DIR:OUT; SFP:1101;", "X-MS-Exchange-AntiSpam-MessageData-ChunkCount": "1", "X-MS-Exchange-AntiSpam-MessageData-0": "\n v5av7yBdrqelU2+bFTjxGR6eDB6pppcEssb3N3frETLhYAZZLWRtDOxjEvq3Nm5pYUtc9FX0LyU1nt3wCNbMQllDpq8BcHus94JP7NFsI/Q6H6fFgIFaapkPDoPGm17BiYngWfLC4StofPJsMIAMfy2RI2XKUxcmA5SXcikvzzoS4ZWX64A5F7aDvDZlfz2CMjVsAmUDHOgIwAfw0ZfDFFsJnZsjRnC14koWa2oQMTghy0VXrBwSovRB4xrpXBaugBEmWjsqGS2X+yJyKX1meq3KofLJRhUFeWZNlGDgjgLSyly1x9dyGsR9WE8/++MvpjmxXIoixUrjLN82VODxEma06h/m6+hQGEIKekXoGOyv2UGANQJAqV5pTtzg7NnNQVThkfO3s6rNW9BuS5N0kd6kn8Y/GhJqrtcIAnj+q3sZodaVRXLmA8NYIx1y30A0", "X-OriginatorOrg": "Nvidia.com", "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "01 Apr 2026 09:15:07.0726 (UTC)", "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 7616278f-2192-4484-27a3-08de8fcf2acc", "X-MS-Exchange-CrossTenant-Id": "43083d15-7273-40c1-b7db-39efd9ccc17a", "X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp": "\n TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[216.228.117.161];\n Helo=[mail.nvidia.com]", "X-MS-Exchange-CrossTenant-AuthSource": "\n SA2PEPF000015C8.namprd03.prod.outlook.com", "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous", "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem", "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "DM6PR12MB4402", "Subject": "[ovs-dev] [PATCH v3 08/11] netdev-dpdk: Refactor common functions\n for reuse by netdev-doca.", "X-BeenThere": "ovs-dev@openvswitch.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "<ovs-dev.openvswitch.org>", "List-Unsubscribe": "<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>", "List-Archive": "<http://mail.openvswitch.org/pipermail/ovs-dev/>", "List-Post": "<mailto:ovs-dev@openvswitch.org>", "List-Help": "<mailto:ovs-dev-request@openvswitch.org?subject=help>", "List-Subscribe": "<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=subscribe>", "Cc": "Eli Britstein <elibr@nvidia.com>, Ilya Maximets <i.maximets@ovn.org>,\n David Marchand <david.marchand@redhat.com>, Maor Dickman <maord@nvidia.com>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "ovs-dev-bounces@openvswitch.org", "Sender": "\"dev\" <ovs-dev-bounces@openvswitch.org>" }, "content": "Refactor common functions from netdev-dpdk to be declared in\nnetdev-dpdk-private to be reused by netdev-doca.\n\nSigned-off-by: Eli Britstein <elibr@nvidia.com>\n---\n lib/netdev-dpdk-private.h | 108 ++++++\n lib/netdev-dpdk.c | 692 +++++++++++++++++++++-----------------\n 2 files changed, 492 insertions(+), 308 deletions(-)", "diff": "diff --git a/lib/netdev-dpdk-private.h b/lib/netdev-dpdk-private.h\nindex 083ddacb3..1b33c27a4 100644\n--- a/lib/netdev-dpdk-private.h\n+++ b/lib/netdev-dpdk-private.h\n@@ -64,6 +64,16 @@ extern const struct rte_eth_conf port_conf;\n typedef uint16_t dpdk_port_t;\n #define DPDK_PORT_ID_FMT \"%\"PRIu16\n \n+struct dp_packet;\n+struct dp_packet_batch;\n+struct eth_addr;\n+struct netdev;\n+struct netdev_stats;\n+struct rte_eth_xstat;\n+struct rte_eth_xstat_name;\n+struct smap;\n+enum netdev_features;\n+\n /* Enums. */\n \n enum dpdk_hw_ol_features {\n@@ -84,6 +94,11 @@ enum dpdk_hw_ol_features {\n \n /* Structs. */\n \n+struct netdev_dpdk_watchdog_params {\n+ struct ovs_mutex *mutex;\n+ struct ovs_list *list;\n+};\n+\n #ifndef NETDEV_DPDK_TX_Q_TYPE\n #error \"NETDEV_DPDK_TX_Q_TYPE must be defined before\" \\\n \"including netdev-dpdk-private.h\"\n@@ -104,6 +119,12 @@ struct netdev_rxq_dpdk {\n dpdk_port_t port_id;\n };\n \n+static inline struct netdev_rxq_dpdk *\n+netdev_rxq_dpdk_cast(const struct netdev_rxq *rxq)\n+{\n+ return CONTAINER_OF(rxq, struct netdev_rxq_dpdk, up);\n+}\n+\n struct netdev_dpdk_common {\n PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline0,\n uint16_t port_id;\n@@ -179,4 +200,91 @@ dpdk_dev_is_started(struct netdev_dpdk_common *common)\n return started;\n }\n \n+/* Common functions shared between netdev-dpdk and netdev-doca. */\n+\n+/* Type-independent helpers. */\n+struct rte_mempool *netdev_dpdk_mp_create_pool(const char *pool_name,\n+ uint32_t n_mbufs,\n+ uint32_t mbuf_size,\n+ int socket_id);\n+uint32_t netdev_dpdk_buf_size(int mtu);\n+size_t netdev_dpdk_copy_batch_to_mbuf(struct netdev_dpdk_common *common,\n+ struct dp_packet_batch *batch);\n+const char *netdev_dpdk_link_speed_to_str__(uint32_t link_speed);\n+void netdev_dpdk_mbuf_dump(const char *prefix, const char *message,\n+ const struct rte_mbuf *mbuf);\n+\n+/* Functions operating on struct netdev_dpdk_common. */\n+void netdev_dpdk_detect_hw_ol_features(struct netdev_dpdk_common *common,\n+ const struct rte_eth_dev_info *info);\n+void netdev_dpdk_build_port_conf(struct netdev_dpdk_common *common,\n+ const struct rte_eth_dev_info *info,\n+ struct rte_eth_conf *conf);\n+void netdev_dpdk_check_link_status(struct netdev_dpdk_common *common);\n+\n+void *netdev_dpdk_watchdog(void *params);\n+\n+void netdev_dpdk_update_netdev_flags(struct netdev_dpdk_common *common);\n+void netdev_dpdk_clear_xstats(struct netdev_dpdk_common *common);\n+void netdev_dpdk_configure_xstats(struct netdev_dpdk_common *common);\n+void netdev_dpdk_set_rxq_config(struct netdev_dpdk_common *common,\n+ const struct smap *args);\n+int netdev_dpdk_prep_hwol_batch(struct netdev_dpdk_common *common,\n+ struct rte_mbuf **pkts, int pkt_cnt);\n+int netdev_dpdk_filter_packet_len(struct netdev_dpdk_common *common,\n+ struct rte_mbuf **pkts, int pkt_cnt);\n+int netdev_dpdk_eth_tx_burst(struct netdev_dpdk_common *common,\n+ dpdk_port_t port_id, int qid,\n+ struct rte_mbuf **pkts, int cnt);\n+void netdev_dpdk_get_config_common(struct netdev_dpdk_common *common,\n+ struct smap *args);\n+struct netdev_dpdk_common *\n+netdev_dpdk_lookup_by_port_id__(dpdk_port_t port_id,\n+ struct ovs_list *list);\n+dpdk_port_t netdev_dpdk_get_port_by_devargs(const char *devargs);\n+\n+/* Rxq ops shared between dpdk and doca. */\n+struct netdev_rxq *netdev_dpdk_rxq_alloc(void);\n+int netdev_dpdk_rxq_construct(struct netdev_rxq *rxq);\n+void netdev_dpdk_rxq_destruct(struct netdev_rxq *rxq);\n+void netdev_dpdk_rxq_dealloc(struct netdev_rxq *rxq);\n+\n+/* Netdev provider ops usable by both dpdk and doca. */\n+\n+int netdev_dpdk_get_numa_id(const struct netdev *netdev);\n+int netdev_dpdk_set_tx_multiq(struct netdev *netdev, unsigned int n_txq);\n+int netdev_dpdk_set_etheraddr__(struct netdev_dpdk_common *common,\n+ const struct eth_addr mac);\n+int netdev_dpdk_update_flags(struct netdev *netdev,\n+ enum netdev_flags off, enum netdev_flags on,\n+ enum netdev_flags *old_flagsp);\n+int netdev_dpdk_update_flags__(struct netdev_dpdk_common *common,\n+ enum netdev_flags off, enum netdev_flags on,\n+ enum netdev_flags *old_flagsp);\n+int netdev_dpdk_set_etheraddr(struct netdev *netdev,\n+ const struct eth_addr mac);\n+int netdev_dpdk_get_etheraddr(const struct netdev *netdev,\n+ struct eth_addr *mac);\n+int netdev_dpdk_get_mtu(const struct netdev *netdev, int *mtup);\n+int netdev_dpdk_get_ifindex(const struct netdev *netdev);\n+int netdev_dpdk_get_carrier(const struct netdev *netdev, bool *carrier);\n+long long int netdev_dpdk_get_carrier_resets(const struct netdev *netdev);\n+int netdev_dpdk_set_miimon(struct netdev *netdev, long long int interval);\n+int netdev_dpdk_get_speed(const struct netdev *netdev, uint32_t *current,\n+ uint32_t *max);\n+int netdev_dpdk_get_features(const struct netdev *netdev,\n+ enum netdev_features *current,\n+ enum netdev_features *advertised,\n+ enum netdev_features *supported,\n+ enum netdev_features *peer);\n+void netdev_dpdk_convert_xstats(struct netdev_stats *stats,\n+ const struct rte_eth_xstat *xstats,\n+ const struct rte_eth_xstat_name *names,\n+ const unsigned int size);\n+int netdev_dpdk_get_stats(const struct netdev *netdev,\n+ struct netdev_stats *stats);\n+int netdev_dpdk_get_status__(const struct netdev *netdev,\n+ struct ovs_mutex *dev_mutex,\n+ struct smap *args);\n+\n #endif /* NETDEV_DPDK_PRIVATE_H */\ndiff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c\nindex 2562eb4b4..dbf988de4 100644\n--- a/lib/netdev-dpdk.c\n+++ b/lib/netdev-dpdk.c\n@@ -452,17 +452,11 @@ static void netdev_dpdk_vhost_destruct(struct netdev *netdev);\n \n static int netdev_dpdk_get_sw_custom_stats(const struct netdev *,\n struct netdev_custom_stats *);\n-static void netdev_dpdk_configure_xstats(struct netdev_dpdk_common *common);\n-static void netdev_dpdk_clear_xstats(struct netdev_dpdk_common *common);\n-\n int netdev_dpdk_get_vid(const struct netdev_dpdk *dev);\n \n struct ingress_policer *\n netdev_dpdk_get_ingress_policer(const struct netdev_dpdk *dev);\n \n-static void netdev_dpdk_mbuf_dump(const char *prefix, const char *message,\n- const struct rte_mbuf *);\n-\n static bool\n is_dpdk_class(const struct netdev_class *class)\n {\n@@ -479,8 +473,8 @@ is_dpdk_class(const struct netdev_class *class)\n * behaviour, which reduces performance. To prevent this, use a buffer size\n * that is closest to 'mtu', but which satisfies the aforementioned criteria.\n */\n-static uint32_t\n-dpdk_buf_size(int mtu)\n+uint32_t\n+netdev_dpdk_buf_size(int mtu)\n {\n return ROUND_UP(MTU_TO_MAX_FRAME_LEN(mtu), NETDEV_DPDK_MBUF_ALIGN)\n + RTE_PKTMBUF_HEADROOM;\n@@ -630,6 +624,49 @@ dpdk_calculate_mbufs(struct netdev_dpdk *dev, int mtu)\n return n_mbufs;\n }\n \n+struct rte_mempool *\n+netdev_dpdk_mp_create_pool(const char *pool_name, uint32_t n_mbufs,\n+ uint32_t mbuf_size, int socket_id)\n+{\n+ uint32_t mbuf_priv_data_len;\n+ uint32_t aligned_mbuf_size;\n+ struct rte_mempool *mp;\n+ uint32_t pkt_size;\n+\n+ /* The size of the mbuf's private area (i.e. area that holds OvS'\n+ * dp_packet data)*/\n+ mbuf_priv_data_len = sizeof(struct dp_packet) -\n+ sizeof(struct rte_mbuf);\n+ /* The size of the entire dp_packet. */\n+ pkt_size = sizeof(struct dp_packet) + mbuf_size;\n+ /* mbuf size, rounded up to cacheline size. */\n+ aligned_mbuf_size = ROUND_UP(pkt_size, RTE_CACHE_LINE_SIZE);\n+ /* If there is a size discrepancy, add padding to mbuf_priv_data_len.\n+ * This maintains mbuf size cache alignment, while also honoring RX\n+ * buffer alignment in the data portion of the mbuf. If this adjustment\n+ * is not made, there is a possiblity later on that for an element of\n+ * the mempool, buf, buf->data_len < (buf->buf_len - buf->data_off).\n+ * This is problematic in the case of multi-segment mbufs, particularly\n+ * when an mbuf segment needs to be resized (when [push|popp]ing a VLAN\n+ * header, for example.\n+ */\n+ mbuf_priv_data_len += (aligned_mbuf_size - pkt_size);\n+\n+ mp = rte_pktmbuf_pool_create(pool_name, n_mbufs, MP_CACHE_SZ,\n+ mbuf_priv_data_len, mbuf_size,\n+ socket_id);\n+\n+ if (mp) {\n+ /* rte_pktmbuf_pool_create has done some initialization of the\n+ * rte_mbuf part of each dp_packet, while ovs_rte_pktmbuf_init\n+ * initializes some OVS specific fields of dp_packet.\n+ */\n+ rte_mempool_obj_iter(mp, ovs_rte_pktmbuf_init, NULL);\n+ }\n+\n+ return mp;\n+}\n+\n static struct dpdk_mp *\n dpdk_mp_create(struct netdev_dpdk *dev, int mtu)\n {\n@@ -638,9 +675,6 @@ dpdk_mp_create(struct netdev_dpdk *dev, int mtu)\n int socket_id = dev->common.requested_socket_id;\n uint32_t n_mbufs = 0;\n uint32_t mbuf_size = 0;\n- uint32_t aligned_mbuf_size = 0;\n- uint32_t mbuf_priv_data_len = 0;\n- uint32_t pkt_size = 0;\n uint32_t hash = hash_string(netdev_name, 0);\n struct dpdk_mp *dmp = NULL;\n int ret;\n@@ -659,13 +693,6 @@ dpdk_mp_create(struct netdev_dpdk *dev, int mtu)\n n_mbufs = dpdk_calculate_mbufs(dev, mtu);\n \n do {\n- /* Full DPDK memory pool name must be unique and cannot be\n- * longer than RTE_MEMPOOL_NAMESIZE. Note that for the shared\n- * mempool case this can result in one device using a mempool\n- * which references a different device in it's name. However as\n- * mempool names are hashed, the device name will not be readable\n- * so this is not an issue for tasks such as debugging.\n- */\n ret = snprintf(mp_name, RTE_MEMPOOL_NAMESIZE,\n \"ovs%08x%02d%05d%07u\",\n hash, socket_id, mtu, n_mbufs);\n@@ -684,38 +711,12 @@ dpdk_mp_create(struct netdev_dpdk *dev, int mtu)\n dev->common.requested_n_rxq, dev->common.requested_n_txq,\n RTE_CACHE_LINE_SIZE);\n \n- /* The size of the mbuf's private area (i.e. area that holds OvS'\n- * dp_packet data)*/\n- mbuf_priv_data_len = sizeof(struct dp_packet) -\n- sizeof(struct rte_mbuf);\n- /* The size of the entire dp_packet. */\n- pkt_size = sizeof(struct dp_packet) + mbuf_size;\n- /* mbuf size, rounded up to cacheline size. */\n- aligned_mbuf_size = ROUND_UP(pkt_size, RTE_CACHE_LINE_SIZE);\n- /* If there is a size discrepancy, add padding to mbuf_priv_data_len.\n- * This maintains mbuf size cache alignment, while also honoring RX\n- * buffer alignment in the data portion of the mbuf. If this adjustment\n- * is not made, there is a possiblity later on that for an element of\n- * the mempool, buf, buf->data_len < (buf->buf_len - buf->data_off).\n- * This is problematic in the case of multi-segment mbufs, particularly\n- * when an mbuf segment needs to be resized (when [push|popp]ing a VLAN\n- * header, for example.\n- */\n- mbuf_priv_data_len += (aligned_mbuf_size - pkt_size);\n-\n- dmp->mp = rte_pktmbuf_pool_create(mp_name, n_mbufs, MP_CACHE_SZ,\n- mbuf_priv_data_len,\n- mbuf_size,\n- socket_id);\n+ dmp->mp = netdev_dpdk_mp_create_pool(mp_name, n_mbufs, mbuf_size,\n+ socket_id);\n \n if (dmp->mp) {\n VLOG_DBG(\"Allocated \\\"%s\\\" mempool with %u mbufs\",\n mp_name, n_mbufs);\n- /* rte_pktmbuf_pool_create has done some initialization of the\n- * rte_mbuf part of each dp_packet, while ovs_rte_pktmbuf_init\n- * initializes some OVS specific fields of dp_packet.\n- */\n- rte_mempool_obj_iter(dmp->mp, ovs_rte_pktmbuf_init, NULL);\n return dmp;\n } else if (rte_errno == EEXIST) {\n /* A mempool with the same name already exists. We just\n@@ -821,7 +822,7 @@ static int\n netdev_dpdk_mempool_configure(struct netdev_dpdk *dev)\n OVS_REQUIRES(dev->common.mutex)\n {\n- uint32_t buf_size = dpdk_buf_size(dev->common.requested_mtu);\n+ uint32_t buf_size = netdev_dpdk_buf_size(dev->common.requested_mtu);\n struct dpdk_mp *dmp;\n int ret = 0;\n \n@@ -866,8 +867,8 @@ netdev_dpdk_mempool_configure(struct netdev_dpdk *dev)\n return ret;\n }\n \n-static void\n-check_link_status(struct netdev_dpdk_common *common)\n+void\n+netdev_dpdk_check_link_status(struct netdev_dpdk_common *common)\n {\n struct rte_eth_link link;\n \n@@ -902,21 +903,24 @@ check_link_status(struct netdev_dpdk_common *common)\n }\n }\n \n-static void *\n-dpdk_watchdog(void *dummy OVS_UNUSED)\n+void *\n+netdev_dpdk_watchdog(void *args_)\n {\n+ struct netdev_dpdk_watchdog_params *params = args_;\n struct netdev_dpdk_common *common;\n \n+ ovs_assert(params);\n+\n pthread_detach(pthread_self());\n \n for (;;) {\n- ovs_mutex_lock(&dpdk_mutex);\n- LIST_FOR_EACH (common, list_node, &dpdk_list) {\n+ ovs_mutex_lock(params->mutex);\n+ LIST_FOR_EACH (common, list_node, params->list) {\n ovs_mutex_lock(&common->mutex);\n- check_link_status(common);\n+ netdev_dpdk_check_link_status(common);\n ovs_mutex_unlock(&common->mutex);\n }\n- ovs_mutex_unlock(&dpdk_mutex);\n+ ovs_mutex_unlock(params->mutex);\n xsleep(DPDK_PORT_WATCHDOG_INTERVAL);\n }\n \n@@ -936,7 +940,7 @@ netdev_dpdk_update_netdev_flag(struct netdev_dpdk_common *common,\n }\n }\n \n-static void\n+void\n netdev_dpdk_update_netdev_flags(struct netdev_dpdk_common *common)\n OVS_REQUIRES(common->mutex)\n {\n@@ -962,85 +966,192 @@ netdev_dpdk_update_netdev_flags(struct netdev_dpdk_common *common)\n NETDEV_TX_OFFLOAD_OUTER_UDP_CKSUM);\n }\n \n-static int\n-dpdk_eth_dev_port_config(struct netdev_dpdk_common *common,\n- const struct rte_eth_dev_info *info,\n- int n_rxq, int n_txq)\n+void\n+netdev_dpdk_detect_hw_ol_features(struct netdev_dpdk_common *common,\n+ const struct rte_eth_dev_info *info)\n+ OVS_REQUIRES(common->mutex)\n {\n- struct rte_eth_conf conf = port_conf;\n- uint16_t conf_mtu;\n- int diag = 0;\n- int i;\n+ uint32_t rx_chksm_offload_capa = RTE_ETH_RX_OFFLOAD_UDP_CKSUM |\n+ RTE_ETH_RX_OFFLOAD_TCP_CKSUM |\n+ RTE_ETH_RX_OFFLOAD_IPV4_CKSUM;\n+\n+ if (strstr(info->driver_name, \"vf\") != NULL) {\n+ VLOG_INFO(\"Virtual function detected, HW_CRC_STRIP will be enabled\");\n+ common->hw_ol_features |= NETDEV_RX_HW_CRC_STRIP;\n+ } else {\n+ common->hw_ol_features &= ~NETDEV_RX_HW_CRC_STRIP;\n+ }\n \n+ if ((info->rx_offload_capa & rx_chksm_offload_capa) !=\n+ rx_chksm_offload_capa) {\n+ VLOG_WARN(\"Rx checksum offload is not supported on port \"\n+ DPDK_PORT_ID_FMT, common->port_id);\n+ common->hw_ol_features &= ~NETDEV_RX_CHECKSUM_OFFLOAD;\n+ } else {\n+ common->hw_ol_features |= NETDEV_RX_CHECKSUM_OFFLOAD;\n+ }\n+\n+ if (info->rx_offload_capa & RTE_ETH_RX_OFFLOAD_SCATTER) {\n+ common->hw_ol_features |= NETDEV_RX_HW_SCATTER;\n+ } else {\n+ common->hw_ol_features &= ~NETDEV_RX_HW_SCATTER;\n+ }\n+\n+ if (info->tx_offload_capa & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) {\n+ common->hw_ol_features |= NETDEV_TX_IPV4_CKSUM_OFFLOAD;\n+ } else {\n+ common->hw_ol_features &= ~NETDEV_TX_IPV4_CKSUM_OFFLOAD;\n+ }\n+\n+ if (info->tx_offload_capa & RTE_ETH_TX_OFFLOAD_TCP_CKSUM) {\n+ common->hw_ol_features |= NETDEV_TX_TCP_CKSUM_OFFLOAD;\n+ } else {\n+ common->hw_ol_features &= ~NETDEV_TX_TCP_CKSUM_OFFLOAD;\n+ }\n+\n+ if (info->tx_offload_capa & RTE_ETH_TX_OFFLOAD_UDP_CKSUM) {\n+ common->hw_ol_features |= NETDEV_TX_UDP_CKSUM_OFFLOAD;\n+ } else {\n+ common->hw_ol_features &= ~NETDEV_TX_UDP_CKSUM_OFFLOAD;\n+ }\n+\n+ if (info->tx_offload_capa & RTE_ETH_TX_OFFLOAD_SCTP_CKSUM) {\n+ common->hw_ol_features |= NETDEV_TX_SCTP_CKSUM_OFFLOAD;\n+ } else {\n+ common->hw_ol_features &= ~NETDEV_TX_SCTP_CKSUM_OFFLOAD;\n+ }\n+\n+ if (info->tx_offload_capa & RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM) {\n+ common->hw_ol_features |= NETDEV_TX_OUTER_IP_CKSUM_OFFLOAD;\n+ } else {\n+ common->hw_ol_features &= ~NETDEV_TX_OUTER_IP_CKSUM_OFFLOAD;\n+ }\n+\n+ if (info->tx_offload_capa & RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM) {\n+ common->hw_ol_features |= NETDEV_TX_OUTER_UDP_CKSUM_OFFLOAD;\n+ } else {\n+ common->hw_ol_features &= ~NETDEV_TX_OUTER_UDP_CKSUM_OFFLOAD;\n+ }\n+\n+ common->hw_ol_features &= ~NETDEV_TX_TSO_OFFLOAD;\n+ if (userspace_tso_enabled()) {\n+ if (info->tx_offload_capa & RTE_ETH_TX_OFFLOAD_TCP_TSO) {\n+ common->hw_ol_features |= NETDEV_TX_TSO_OFFLOAD;\n+ } else {\n+ VLOG_WARN(\"%s: Tx TSO offload is not supported.\",\n+ netdev_get_name(&common->up));\n+ }\n+\n+ if (info->tx_offload_capa & RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO) {\n+ common->hw_ol_features |= NETDEV_TX_VXLAN_TNL_TSO_OFFLOAD;\n+ } else {\n+ VLOG_WARN(\"%s: Tx Vxlan tunnel TSO offload is not supported.\",\n+ netdev_get_name(&common->up));\n+ }\n+\n+ if (info->tx_offload_capa & RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO) {\n+ common->hw_ol_features |= NETDEV_TX_GENEVE_TNL_TSO_OFFLOAD;\n+ } else {\n+ VLOG_WARN(\"%s: Tx Geneve tunnel TSO offload is not supported.\",\n+ netdev_get_name(&common->up));\n+ }\n+\n+ if (info->tx_offload_capa & RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO) {\n+ common->hw_ol_features |= NETDEV_TX_GRE_TNL_TSO_OFFLOAD;\n+ } else {\n+ VLOG_WARN(\"%s: Tx GRE tunnel TSO offload is not supported.\",\n+ netdev_get_name(&common->up));\n+ }\n+ }\n+}\n+\n+void\n+netdev_dpdk_build_port_conf(struct netdev_dpdk_common *common,\n+ const struct rte_eth_dev_info *info,\n+ struct rte_eth_conf *conf)\n+{\n /* As of DPDK 17.11.1 a few PMDs require to explicitly enable\n * scatter to support jumbo RX.\n * Setting scatter for the device is done after checking for\n * scatter support in the device capabilites. */\n if (common->mtu > RTE_ETHER_MTU) {\n if (common->hw_ol_features & NETDEV_RX_HW_SCATTER) {\n- conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_SCATTER;\n+ conf->rxmode.offloads |= RTE_ETH_RX_OFFLOAD_SCATTER;\n }\n }\n \n- conf.intr_conf.lsc = common->lsc_interrupt_mode;\n+ conf->intr_conf.lsc = common->lsc_interrupt_mode;\n \n if (common->hw_ol_features & NETDEV_RX_CHECKSUM_OFFLOAD) {\n- conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_CHECKSUM;\n+ conf->rxmode.offloads |= RTE_ETH_RX_OFFLOAD_CHECKSUM;\n }\n \n if (!(common->hw_ol_features & NETDEV_RX_HW_CRC_STRIP)\n && info->rx_offload_capa & RTE_ETH_RX_OFFLOAD_KEEP_CRC) {\n- conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_KEEP_CRC;\n+ conf->rxmode.offloads |= RTE_ETH_RX_OFFLOAD_KEEP_CRC;\n }\n \n if (common->hw_ol_features & NETDEV_TX_IPV4_CKSUM_OFFLOAD) {\n- conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM;\n+ conf->txmode.offloads |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM;\n }\n \n if (common->hw_ol_features & NETDEV_TX_TCP_CKSUM_OFFLOAD) {\n- conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_TCP_CKSUM;\n+ conf->txmode.offloads |= RTE_ETH_TX_OFFLOAD_TCP_CKSUM;\n }\n \n if (common->hw_ol_features & NETDEV_TX_UDP_CKSUM_OFFLOAD) {\n- conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_UDP_CKSUM;\n+ conf->txmode.offloads |= RTE_ETH_TX_OFFLOAD_UDP_CKSUM;\n }\n \n if (common->hw_ol_features & NETDEV_TX_SCTP_CKSUM_OFFLOAD) {\n- conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_SCTP_CKSUM;\n+ conf->txmode.offloads |= RTE_ETH_TX_OFFLOAD_SCTP_CKSUM;\n }\n \n if (common->hw_ol_features & NETDEV_TX_TSO_OFFLOAD) {\n- conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_TCP_TSO;\n+ conf->txmode.offloads |= RTE_ETH_TX_OFFLOAD_TCP_TSO;\n }\n \n if (common->hw_ol_features & NETDEV_TX_VXLAN_TNL_TSO_OFFLOAD) {\n- conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO;\n+ conf->txmode.offloads |= RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO;\n }\n \n if (common->hw_ol_features & NETDEV_TX_GENEVE_TNL_TSO_OFFLOAD) {\n- conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO;\n+ conf->txmode.offloads |= RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO;\n }\n \n if (common->hw_ol_features & NETDEV_TX_GRE_TNL_TSO_OFFLOAD) {\n- conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO;\n+ conf->txmode.offloads |= RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO;\n }\n \n if (common->hw_ol_features & NETDEV_TX_OUTER_IP_CKSUM_OFFLOAD) {\n- conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM;\n+ conf->txmode.offloads |= RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM;\n }\n \n if (common->hw_ol_features & NETDEV_TX_OUTER_UDP_CKSUM_OFFLOAD) {\n- conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM;\n+ conf->txmode.offloads |= RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM;\n }\n \n /* Limit configured rss hash functions to only those supported\n * by the eth device. */\n- conf.rx_adv_conf.rss_conf.rss_hf &= info->flow_type_rss_offloads;\n- if (conf.rx_adv_conf.rss_conf.rss_hf == 0) {\n- conf.rxmode.mq_mode = RTE_ETH_MQ_RX_NONE;\n+ conf->rx_adv_conf.rss_conf.rss_hf &= info->flow_type_rss_offloads;\n+ if (conf->rx_adv_conf.rss_conf.rss_hf == 0) {\n+ conf->rxmode.mq_mode = RTE_ETH_MQ_RX_NONE;\n } else {\n- conf.rxmode.mq_mode = RTE_ETH_MQ_RX_RSS;\n+ conf->rxmode.mq_mode = RTE_ETH_MQ_RX_RSS;\n }\n+}\n+\n+static int\n+dpdk_eth_dev_port_config(struct netdev_dpdk_common *common,\n+ const struct rte_eth_dev_info *info,\n+ int n_rxq, int n_txq)\n+{\n+ struct rte_eth_conf conf = port_conf;\n+ uint16_t conf_mtu;\n+ int diag = 0;\n+ int i;\n+\n+ netdev_dpdk_build_port_conf(common, info, &conf);\n \n /* A device may report more queues than it makes available (this has\n * been observed for Intel xl710, which reserves some of them for\n@@ -1179,9 +1290,6 @@ dpdk_eth_dev_init(struct netdev_dpdk *dev)\n struct rte_ether_addr eth_addr;\n int diag;\n int n_rxq, n_txq;\n- uint32_t rx_chksm_offload_capa = RTE_ETH_RX_OFFLOAD_UDP_CKSUM |\n- RTE_ETH_RX_OFFLOAD_TCP_CKSUM |\n- RTE_ETH_RX_OFFLOAD_IPV4_CKSUM;\n \n if (dpif_offload_enabled()) {\n /*\n@@ -1204,95 +1312,7 @@ dpdk_eth_dev_init(struct netdev_dpdk *dev)\n \n dev->common.is_representor = !!(*info.dev_flags & RTE_ETH_DEV_REPRESENTOR);\n \n- if (strstr(info.driver_name, \"vf\") != NULL) {\n- VLOG_INFO(\"Virtual function detected, HW_CRC_STRIP will be enabled\");\n- dev->common.hw_ol_features |= NETDEV_RX_HW_CRC_STRIP;\n- } else {\n- dev->common.hw_ol_features &= ~NETDEV_RX_HW_CRC_STRIP;\n- }\n-\n- if ((info.rx_offload_capa & rx_chksm_offload_capa) !=\n- rx_chksm_offload_capa) {\n- VLOG_WARN(\"Rx checksum offload is not supported on port \"\n- DPDK_PORT_ID_FMT, dev->common.port_id);\n- dev->common.hw_ol_features &= ~NETDEV_RX_CHECKSUM_OFFLOAD;\n- } else {\n- dev->common.hw_ol_features |= NETDEV_RX_CHECKSUM_OFFLOAD;\n- }\n-\n- if (info.rx_offload_capa & RTE_ETH_RX_OFFLOAD_SCATTER) {\n- dev->common.hw_ol_features |= NETDEV_RX_HW_SCATTER;\n- } else {\n- /* Do not warn on lack of scatter support */\n- dev->common.hw_ol_features &= ~NETDEV_RX_HW_SCATTER;\n- }\n-\n- if (info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) {\n- dev->common.hw_ol_features |= NETDEV_TX_IPV4_CKSUM_OFFLOAD;\n- } else {\n- dev->common.hw_ol_features &= ~NETDEV_TX_IPV4_CKSUM_OFFLOAD;\n- }\n-\n- if (info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_TCP_CKSUM) {\n- dev->common.hw_ol_features |= NETDEV_TX_TCP_CKSUM_OFFLOAD;\n- } else {\n- dev->common.hw_ol_features &= ~NETDEV_TX_TCP_CKSUM_OFFLOAD;\n- }\n-\n- if (info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_UDP_CKSUM) {\n- dev->common.hw_ol_features |= NETDEV_TX_UDP_CKSUM_OFFLOAD;\n- } else {\n- dev->common.hw_ol_features &= ~NETDEV_TX_UDP_CKSUM_OFFLOAD;\n- }\n-\n- if (info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_SCTP_CKSUM) {\n- dev->common.hw_ol_features |= NETDEV_TX_SCTP_CKSUM_OFFLOAD;\n- } else {\n- dev->common.hw_ol_features &= ~NETDEV_TX_SCTP_CKSUM_OFFLOAD;\n- }\n-\n- if (info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM) {\n- dev->common.hw_ol_features |= NETDEV_TX_OUTER_IP_CKSUM_OFFLOAD;\n- } else {\n- dev->common.hw_ol_features &= ~NETDEV_TX_OUTER_IP_CKSUM_OFFLOAD;\n- }\n-\n- if (info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM) {\n- dev->common.hw_ol_features |= NETDEV_TX_OUTER_UDP_CKSUM_OFFLOAD;\n- } else {\n- dev->common.hw_ol_features &= ~NETDEV_TX_OUTER_UDP_CKSUM_OFFLOAD;\n- }\n-\n- dev->common.hw_ol_features &= ~NETDEV_TX_TSO_OFFLOAD;\n- if (userspace_tso_enabled()) {\n- if (info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_TCP_TSO) {\n- dev->common.hw_ol_features |= NETDEV_TX_TSO_OFFLOAD;\n- } else {\n- VLOG_WARN(\"%s: Tx TSO offload is not supported.\",\n- netdev_get_name(&dev->common.up));\n- }\n-\n- if (info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO) {\n- dev->common.hw_ol_features |= NETDEV_TX_VXLAN_TNL_TSO_OFFLOAD;\n- } else {\n- VLOG_WARN(\"%s: Tx Vxlan tunnel TSO offload is not supported.\",\n- netdev_get_name(&dev->common.up));\n- }\n-\n- if (info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO) {\n- dev->common.hw_ol_features |= NETDEV_TX_GENEVE_TNL_TSO_OFFLOAD;\n- } else {\n- VLOG_WARN(\"%s: Tx Geneve tunnel TSO offload is not supported.\",\n- netdev_get_name(&dev->common.up));\n- }\n-\n- if (info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO) {\n- dev->common.hw_ol_features |= NETDEV_TX_GRE_TNL_TSO_OFFLOAD;\n- } else {\n- VLOG_WARN(\"%s: Tx GRE tunnel TSO offload is not supported.\",\n- netdev_get_name(&dev->common.up));\n- }\n- }\n+ netdev_dpdk_detect_hw_ol_features(&dev->common, &info);\n \n n_rxq = MIN(info.max_rx_queues, dev->common.up.n_rxq);\n n_txq = MIN(info.max_tx_queues, dev->common.up.n_txq);\n@@ -1742,7 +1762,7 @@ netdev_dpdk_dealloc(struct netdev *netdev)\n rte_free(dev);\n }\n \n-static void\n+void\n netdev_dpdk_clear_xstats(struct netdev_dpdk_common *common)\n OVS_REQUIRES(common->mutex)\n {\n@@ -1774,7 +1794,7 @@ is_queue_stat(const char *s)\n ovs_scan(s + 1, \"x_q%\"SCNu16\"_bytes\", &tmp));\n }\n \n-static void\n+void\n netdev_dpdk_configure_xstats(struct netdev_dpdk_common *common)\n OVS_REQUIRES(common->mutex)\n {\n@@ -1842,46 +1862,54 @@ out:\n free(rte_xstats_names);\n }\n \n-static int\n-netdev_dpdk_get_config(const struct netdev *netdev, struct smap *args)\n+void\n+netdev_dpdk_get_config_common(struct netdev_dpdk_common *common,\n+ struct smap *args)\n+ OVS_REQUIRES(common->mutex)\n {\n- struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);\n-\n- ovs_mutex_lock(&dev->common.mutex);\n-\n- if (dev->common.devargs && dev->common.devargs[0]) {\n- smap_add_format(args, \"dpdk-devargs\", \"%s\", dev->common.devargs);\n+ if (common->devargs && common->devargs[0]) {\n+ smap_add_format(args, \"dpdk-devargs\", \"%s\", common->devargs);\n }\n \n- smap_add_format(args, \"n_rxq\", \"%d\", dev->common.user_n_rxq);\n+ smap_add_format(args, \"n_rxq\", \"%d\", common->user_n_rxq);\n \n- if (dev->common.fc_conf.mode == RTE_ETH_FC_TX_PAUSE ||\n- dev->common.fc_conf.mode == RTE_ETH_FC_FULL) {\n+ if (common->fc_conf.mode == RTE_ETH_FC_TX_PAUSE ||\n+ common->fc_conf.mode == RTE_ETH_FC_FULL) {\n smap_add(args, \"rx-flow-ctrl\", \"true\");\n }\n \n- if (dev->common.fc_conf.mode == RTE_ETH_FC_RX_PAUSE ||\n- dev->common.fc_conf.mode == RTE_ETH_FC_FULL) {\n+ if (common->fc_conf.mode == RTE_ETH_FC_RX_PAUSE ||\n+ common->fc_conf.mode == RTE_ETH_FC_FULL) {\n smap_add(args, \"tx-flow-ctrl\", \"true\");\n }\n \n- if (dev->common.fc_conf.autoneg) {\n+ if (common->fc_conf.autoneg) {\n smap_add(args, \"flow-ctrl-autoneg\", \"true\");\n }\n \n- smap_add_format(args, \"n_rxq_desc\", \"%d\", dev->common.rxq_size);\n- smap_add_format(args, \"n_txq_desc\", \"%d\", dev->common.txq_size);\n-\n- if (dev->rx_steer_flags == DPDK_RX_STEER_LACP) {\n- smap_add(args, \"rx-steering\", \"rss+lacp\");\n- }\n+ smap_add_format(args, \"n_rxq_desc\", \"%d\", common->rxq_size);\n+ smap_add_format(args, \"n_txq_desc\", \"%d\", common->txq_size);\n \n smap_add(args, \"dpdk-lsc-interrupt\",\n- dev->common.lsc_interrupt_mode ? \"true\" : \"false\");\n+ common->lsc_interrupt_mode ? \"true\" : \"false\");\n \n- if (dev->common.is_representor) {\n+ if (common->is_representor) {\n smap_add_format(args, \"dpdk-vf-mac\", ETH_ADDR_FMT,\n- ETH_ADDR_ARGS(dev->common.requested_hwaddr));\n+ ETH_ADDR_ARGS(common->requested_hwaddr));\n+ }\n+}\n+\n+static int\n+netdev_dpdk_get_config(const struct netdev *netdev, struct smap *args)\n+{\n+ struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);\n+\n+ ovs_mutex_lock(&dev->common.mutex);\n+\n+ netdev_dpdk_get_config_common(&dev->common, args);\n+\n+ if (dev->rx_steer_flags == DPDK_RX_STEER_LACP) {\n+ smap_add(args, \"rx-steering\", \"rss+lacp\");\n }\n \n ovs_mutex_unlock(&dev->common.mutex);\n@@ -1889,21 +1917,30 @@ netdev_dpdk_get_config(const struct netdev *netdev, struct smap *args)\n return 0;\n }\n \n-static struct netdev_dpdk *\n-netdev_dpdk_lookup_by_port_id(dpdk_port_t port_id)\n- OVS_REQUIRES(dpdk_mutex)\n+struct netdev_dpdk_common *\n+netdev_dpdk_lookup_by_port_id__(dpdk_port_t port_id, struct ovs_list *list)\n {\n- struct netdev_dpdk *dev;\n+ struct netdev_dpdk_common *common;\n \n- LIST_FOR_EACH (dev, common.list_node, &dpdk_list) {\n- if (dev->common.port_id == port_id) {\n- return dev;\n+ LIST_FOR_EACH (common, list_node, list) {\n+ if (common->port_id == port_id) {\n+ return common;\n }\n }\n \n return NULL;\n }\n \n+static struct netdev_dpdk *\n+netdev_dpdk_lookup_by_port_id(dpdk_port_t port_id)\n+ OVS_REQUIRES(dpdk_mutex)\n+{\n+ struct netdev_dpdk_common *common;\n+\n+ common = netdev_dpdk_lookup_by_port_id__(port_id, &dpdk_list);\n+ return common ? CONTAINER_OF(common, struct netdev_dpdk, common) : NULL;\n+}\n+\n static dpdk_port_t\n netdev_dpdk_get_port_by_mac(const char *mac_str)\n {\n@@ -1929,7 +1966,7 @@ netdev_dpdk_get_port_by_mac(const char *mac_str)\n }\n \n /* Return the first DPDK port id matching the devargs pattern. */\n-static dpdk_port_t netdev_dpdk_get_port_by_devargs(const char *devargs)\n+dpdk_port_t netdev_dpdk_get_port_by_devargs(const char *devargs)\n OVS_REQUIRES(dpdk_mutex)\n {\n dpdk_port_t port_id;\n@@ -2058,8 +2095,8 @@ dpdk_eth_event_callback(dpdk_port_t port_id, enum rte_eth_event_type type,\n return 0;\n }\n \n-static void\n-dpdk_set_rxq_config(struct netdev_dpdk_common *common,\n+void\n+netdev_dpdk_set_rxq_config(struct netdev_dpdk_common *common,\n const struct smap *args)\n OVS_REQUIRES(common->mutex)\n {\n@@ -2182,7 +2219,7 @@ netdev_dpdk_set_config(struct netdev *netdev, const struct smap *args,\n \n dpdk_set_rx_steer_config(netdev, dev, args, errp);\n \n- dpdk_set_rxq_config(&dev->common, args);\n+ netdev_dpdk_set_rxq_config(&dev->common, args);\n \n new_devargs = smap_get(args, \"dpdk-devargs\");\n \n@@ -2402,7 +2439,7 @@ netdev_dpdk_vhost_client_set_config(struct netdev *netdev,\n return 0;\n }\n \n-static int\n+int\n netdev_dpdk_get_numa_id(const struct netdev *netdev)\n {\n struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);\n@@ -2411,7 +2448,7 @@ netdev_dpdk_get_numa_id(const struct netdev *netdev)\n }\n \n /* Sets the number of tx queues for the dpdk interface. */\n-static int\n+int\n netdev_dpdk_set_tx_multiq(struct netdev *netdev, unsigned int n_txq)\n {\n struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);\n@@ -2430,7 +2467,7 @@ out:\n return 0;\n }\n \n-static struct netdev_rxq *\n+struct netdev_rxq *\n netdev_dpdk_rxq_alloc(void)\n {\n struct netdev_rxq_dpdk *rx = dpdk_rte_mzalloc(sizeof *rx);\n@@ -2442,31 +2479,25 @@ netdev_dpdk_rxq_alloc(void)\n return NULL;\n }\n \n-static struct netdev_rxq_dpdk *\n-netdev_rxq_dpdk_cast(const struct netdev_rxq *rxq)\n-{\n- return CONTAINER_OF(rxq, struct netdev_rxq_dpdk, up);\n-}\n-\n-static int\n+int\n netdev_dpdk_rxq_construct(struct netdev_rxq *rxq)\n {\n struct netdev_rxq_dpdk *rx = netdev_rxq_dpdk_cast(rxq);\n- struct netdev_dpdk *dev = netdev_dpdk_cast(rxq->netdev);\n+ struct netdev_dpdk_common *common = netdev_dpdk_common_cast(rxq->netdev);\n \n- ovs_mutex_lock(&dev->common.mutex);\n- rx->port_id = dev->common.port_id;\n- ovs_mutex_unlock(&dev->common.mutex);\n+ ovs_mutex_lock(&common->mutex);\n+ rx->port_id = common->port_id;\n+ ovs_mutex_unlock(&common->mutex);\n \n return 0;\n }\n \n-static void\n+void\n netdev_dpdk_rxq_destruct(struct netdev_rxq *rxq OVS_UNUSED)\n {\n }\n \n-static void\n+void\n netdev_dpdk_rxq_dealloc(struct netdev_rxq *rxq)\n {\n struct netdev_rxq_dpdk *rx = netdev_rxq_dpdk_cast(rxq);\n@@ -2638,7 +2669,7 @@ netdev_dpdk_prep_hwol_packet(struct netdev_dpdk_common *common,\n \n /* Prepare a batch for HWOL.\n * Return the number of good packets in the batch. */\n-static int\n+int\n netdev_dpdk_prep_hwol_batch(struct netdev_dpdk_common *common,\n struct rte_mbuf **pkts, int pkt_cnt)\n {\n@@ -2663,7 +2694,7 @@ netdev_dpdk_prep_hwol_batch(struct netdev_dpdk_common *common,\n return cnt;\n }\n \n-static void\n+void\n netdev_dpdk_mbuf_dump(const char *prefix, const char *message,\n const struct rte_mbuf *mbuf)\n {\n@@ -2696,27 +2727,32 @@ netdev_dpdk_mbuf_dump(const char *prefix, const char *message,\n * 'pkts', even in case of failure.\n *\n * Returns the number of packets that weren't transmitted. */\n-static inline int\n-netdev_dpdk_eth_tx_burst(struct netdev_dpdk *dev, int qid,\n+int\n+netdev_dpdk_eth_tx_burst(struct netdev_dpdk_common *common,\n+ dpdk_port_t port_id, int qid,\n struct rte_mbuf **pkts, int cnt)\n {\n uint32_t nb_tx = 0;\n uint16_t nb_tx_prep = cnt;\n \n- nb_tx_prep = rte_eth_tx_prepare(dev->common.port_id, qid, pkts, cnt);\n+ if (OVS_UNLIKELY(!dpdk_dev_is_started(common))) {\n+ goto out;\n+ }\n+\n+ nb_tx_prep = rte_eth_tx_prepare(port_id, qid, pkts, cnt);\n if (nb_tx_prep != cnt) {\n VLOG_WARN_RL(&rl, \"%s: Output batch contains invalid packets. \"\n \"Only %u/%u are valid: %s\",\n- netdev_get_name(&dev->common.up),\n+ netdev_get_name(&common->up),\n nb_tx_prep, cnt, rte_strerror(rte_errno));\n- netdev_dpdk_mbuf_dump(netdev_get_name(&dev->common.up),\n+ netdev_dpdk_mbuf_dump(netdev_get_name(&common->up),\n \"First invalid packet\", pkts[nb_tx_prep]);\n }\n \n while (nb_tx != nb_tx_prep) {\n uint32_t ret;\n \n- ret = rte_eth_tx_burst(dev->common.port_id, qid, pkts + nb_tx,\n+ ret = rte_eth_tx_burst(port_id, qid, pkts + nb_tx,\n nb_tx_prep - nb_tx);\n if (!ret) {\n break;\n@@ -2725,6 +2761,7 @@ netdev_dpdk_eth_tx_burst(struct netdev_dpdk *dev, int qid,\n nb_tx += ret;\n }\n \n+out:\n if (OVS_UNLIKELY(nb_tx != cnt)) {\n /* Free buffers, which we couldn't transmit. */\n rte_pktmbuf_free_bulk(&pkts[nb_tx], cnt - nb_tx);\n@@ -2926,9 +2963,9 @@ netdev_dpdk_qos_run(struct netdev_dpdk *dev, struct rte_mbuf **pkts,\n return cnt;\n }\n \n-static int\n-netdev_dpdk_filter_packet_len(struct netdev_dpdk *dev, struct rte_mbuf **pkts,\n- int pkt_cnt)\n+int\n+netdev_dpdk_filter_packet_len(struct netdev_dpdk_common *common,\n+ struct rte_mbuf **pkts, int pkt_cnt)\n {\n int i = 0;\n int cnt = 0;\n@@ -2938,12 +2975,12 @@ netdev_dpdk_filter_packet_len(struct netdev_dpdk *dev, struct rte_mbuf **pkts,\n * during the offloading preparation for performance reasons. */\n for (i = 0; i < pkt_cnt; i++) {\n pkt = pkts[i];\n- if (OVS_UNLIKELY((pkt->pkt_len > dev->common.max_packet_len)\n+ if (OVS_UNLIKELY((pkt->pkt_len > common->max_packet_len)\n && !pkt->tso_segsz)) {\n VLOG_WARN_RL(&rl, \"%s: Too big size %\" PRIu32 \" \"\n \"max_packet_len %d\",\n- dev->common.up.name, pkt->pkt_len,\n- dev->common.max_packet_len);\n+ common->up.name, pkt->pkt_len,\n+ common->max_packet_len);\n rte_pktmbuf_free(pkt);\n continue;\n }\n@@ -3111,8 +3148,8 @@ dpdk_copy_dp_packet_to_mbuf(struct rte_mempool *mp, struct dp_packet *pkt_orig)\n * DPDK memory.\n *\n * Returns the number of good packets in the batch. */\n-static size_t\n-dpdk_copy_batch_to_mbuf(struct netdev_dpdk_common *common,\n+size_t\n+netdev_dpdk_copy_batch_to_mbuf(struct netdev_dpdk_common *common,\n struct dp_packet_batch *batch)\n {\n size_t i, size = dp_packet_batch_size(batch);\n@@ -3157,13 +3194,13 @@ netdev_dpdk_common_send(struct netdev *netdev, struct dp_packet_batch *batch,\n \n /* Copy dp-packets to mbufs. */\n if (OVS_UNLIKELY(need_copy)) {\n- cnt = dpdk_copy_batch_to_mbuf(&dev->common, batch);\n+ cnt = netdev_dpdk_copy_batch_to_mbuf(&dev->common, batch);\n stats->tx_failure_drops += pkt_cnt - cnt;\n pkt_cnt = cnt;\n }\n \n /* Drop oversized packets. */\n- cnt = netdev_dpdk_filter_packet_len(dev, pkts, pkt_cnt);\n+ cnt = netdev_dpdk_filter_packet_len(&dev->common, pkts, pkt_cnt);\n stats->tx_mtu_exceeded_drops += pkt_cnt - cnt;\n pkt_cnt = cnt;\n \n@@ -3290,7 +3327,8 @@ netdev_dpdk_eth_send(struct netdev *netdev, int qid,\n \n cnt = netdev_dpdk_common_send(netdev, batch, &stats);\n \n- dropped = netdev_dpdk_eth_tx_burst(dev, qid, pkts, cnt);\n+ dropped = netdev_dpdk_eth_tx_burst(&dev->common, dev->common.port_id,\n+ qid, pkts, cnt);\n stats.tx_failure_drops += dropped;\n dropped += batch_cnt - cnt;\n if (OVS_UNLIKELY(dropped)) {\n@@ -3312,14 +3350,14 @@ netdev_dpdk_eth_send(struct netdev *netdev, int qid,\n return 0;\n }\n \n-static int\n-netdev_dpdk_set_etheraddr__(struct netdev_dpdk *dev, const struct eth_addr mac)\n- OVS_REQUIRES(dev->common.mutex)\n+int\n+netdev_dpdk_set_etheraddr__(struct netdev_dpdk_common *common,\n+ const struct eth_addr mac)\n+ OVS_REQUIRES(common->mutex)\n {\n- struct netdev_dpdk_common *common = &dev->common;\n int err = 0;\n \n- if (dev->type == DPDK_DEV_ETH) {\n+ if (common->port_id != DPDK_ETH_PORT_ID_INVALID) {\n struct rte_ether_addr ea;\n \n memcpy(ea.addr_bytes, mac.ea, ETH_ADDR_LEN);\n@@ -3336,25 +3374,25 @@ netdev_dpdk_set_etheraddr__(struct netdev_dpdk *dev, const struct eth_addr mac)\n return err;\n }\n \n-static int\n+int\n netdev_dpdk_set_etheraddr(struct netdev *netdev, const struct eth_addr mac)\n {\n- struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);\n+ struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);\n int err = 0;\n \n- ovs_mutex_lock(&dev->common.mutex);\n- if (!eth_addr_equals(dev->common.hwaddr, mac)) {\n- err = netdev_dpdk_set_etheraddr__(dev, mac);\n+ ovs_mutex_lock(&common->mutex);\n+ if (!eth_addr_equals(common->hwaddr, mac)) {\n+ err = netdev_dpdk_set_etheraddr__(common, mac);\n if (!err) {\n netdev_change_seq_changed(netdev);\n }\n }\n- ovs_mutex_unlock(&dev->common.mutex);\n+ ovs_mutex_unlock(&common->mutex);\n \n return err;\n }\n \n-static int\n+int\n netdev_dpdk_get_etheraddr(const struct netdev *netdev, struct eth_addr *mac)\n {\n struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);\n@@ -3366,7 +3404,7 @@ netdev_dpdk_get_etheraddr(const struct netdev *netdev, struct eth_addr *mac)\n return 0;\n }\n \n-static int\n+int\n netdev_dpdk_get_mtu(const struct netdev *netdev, int *mtup)\n {\n struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);\n@@ -3711,7 +3749,7 @@ out:\n return 0;\n }\n \n-static void\n+void\n netdev_dpdk_convert_xstats(struct netdev_stats *stats,\n const struct rte_eth_xstat *xstats,\n const struct rte_eth_xstat_name *names,\n@@ -3754,10 +3792,10 @@ netdev_dpdk_convert_xstats(struct netdev_stats *stats,\n #undef DPDK_XSTATS\n }\n \n-static int\n+int\n netdev_dpdk_get_carrier(const struct netdev *netdev, bool *carrier);\n \n-static int\n+int\n netdev_dpdk_get_stats(const struct netdev *netdev, struct netdev_stats *stats)\n {\n struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);\n@@ -3767,6 +3805,12 @@ netdev_dpdk_get_stats(const struct netdev *netdev, struct netdev_stats *stats)\n netdev_dpdk_get_carrier(netdev, &gg);\n ovs_mutex_lock(&common->mutex);\n \n+ if (!dpdk_dev_is_started(common)) {\n+ memset(stats, 0, sizeof *stats);\n+ ovs_mutex_unlock(&common->mutex);\n+ return 0;\n+ }\n+\n struct rte_eth_xstat *rte_xstats = NULL;\n struct rte_eth_xstat_name *rte_xstats_names = NULL;\n int rte_xstats_len, rte_xstats_new_len, rte_xstats_ret;\n@@ -3789,7 +3833,7 @@ netdev_dpdk_get_stats(const struct netdev *netdev, struct netdev_stats *stats)\n rte_xstats_names = xcalloc(rte_xstats_len, sizeof *rte_xstats_names);\n rte_xstats = xcalloc(rte_xstats_len, sizeof *rte_xstats);\n \n- /* Retreive xstats names */\n+ /* Retrieve 'xstats' names. */\n rte_xstats_new_len = rte_eth_xstats_get_names(common->port_id,\n rte_xstats_names,\n rte_xstats_len);\n@@ -3798,7 +3842,7 @@ netdev_dpdk_get_stats(const struct netdev *netdev, struct netdev_stats *stats)\n common->port_id);\n goto out;\n }\n- /* Retreive xstats values */\n+ /* Retrieve 'xstats' values. */\n memset(rte_xstats, 0xff, sizeof *rte_xstats * rte_xstats_len);\n rte_xstats_ret = rte_eth_xstats_get(common->port_id, rte_xstats,\n rte_xstats_len);\n@@ -3937,7 +3981,7 @@ netdev_dpdk_get_sw_custom_stats(const struct netdev *netdev,\n return 0;\n }\n \n-static int\n+int\n netdev_dpdk_get_features(const struct netdev *netdev,\n enum netdev_features *current,\n enum netdev_features *advertised,\n@@ -4002,7 +4046,7 @@ netdev_dpdk_get_features(const struct netdev *netdev,\n return 0;\n }\n \n-static int\n+int\n netdev_dpdk_get_speed(const struct netdev *netdev, uint32_t *current,\n uint32_t *max)\n {\n@@ -4013,7 +4057,12 @@ netdev_dpdk_get_speed(const struct netdev *netdev, uint32_t *current,\n \n ovs_mutex_lock(&common->mutex);\n link = common->link;\n- diag = rte_eth_dev_info_get(common->port_id, &dev_info);\n+ if (dpdk_dev_is_started(common)) {\n+ diag = rte_eth_dev_info_get(common->port_id, &dev_info);\n+ } else {\n+ memset(&dev_info, 0, sizeof dev_info);\n+ diag = -ENODEV;\n+ }\n ovs_mutex_unlock(&common->mutex);\n \n *current = link.link_speed != RTE_ETH_SPEED_NUM_UNKNOWN\n@@ -4158,7 +4207,7 @@ netdev_dpdk_set_policing(struct netdev* netdev, uint32_t policer_rate,\n return 0;\n }\n \n-static int\n+int\n netdev_dpdk_get_ifindex(const struct netdev *netdev)\n {\n struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);\n@@ -4173,13 +4222,13 @@ netdev_dpdk_get_ifindex(const struct netdev *netdev)\n return ifindex;\n }\n \n-static int\n+int\n netdev_dpdk_get_carrier(const struct netdev *netdev, bool *carrier)\n {\n struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);\n \n ovs_mutex_lock(&common->mutex);\n- check_link_status(common);\n+ netdev_dpdk_check_link_status(common);\n *carrier = common->link.link_status;\n \n ovs_mutex_unlock(&common->mutex);\n@@ -4205,7 +4254,7 @@ netdev_dpdk_vhost_get_carrier(const struct netdev *netdev, bool *carrier)\n return 0;\n }\n \n-static long long int\n+long long int\n netdev_dpdk_get_carrier_resets(const struct netdev *netdev)\n {\n struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);\n@@ -4218,21 +4267,19 @@ netdev_dpdk_get_carrier_resets(const struct netdev *netdev)\n return carrier_resets;\n }\n \n-static int\n+int\n netdev_dpdk_set_miimon(struct netdev *netdev OVS_UNUSED,\n long long int interval OVS_UNUSED)\n {\n return EOPNOTSUPP;\n }\n \n-static int\n-netdev_dpdk_update_flags__(struct netdev_dpdk *dev,\n+int\n+netdev_dpdk_update_flags__(struct netdev_dpdk_common *common,\n enum netdev_flags off, enum netdev_flags on,\n enum netdev_flags *old_flagsp)\n- OVS_REQUIRES(dev->common.mutex)\n+ OVS_REQUIRES(common->mutex)\n {\n- struct netdev_dpdk_common *common = &dev->common;\n-\n if ((off | on) & ~(NETDEV_UP | NETDEV_PROMISC)) {\n return EINVAL;\n }\n@@ -4245,9 +4292,8 @@ netdev_dpdk_update_flags__(struct netdev_dpdk *dev,\n return 0;\n }\n \n- if (dev->type == DPDK_DEV_ETH) {\n-\n- if ((dev->common.flags ^ *old_flagsp) & NETDEV_UP) {\n+ if (common->port_id != DPDK_ETH_PORT_ID_INVALID) {\n+ if ((common->flags ^ *old_flagsp) & NETDEV_UP) {\n int err;\n \n if (common->flags & NETDEV_UP) {\n@@ -4272,6 +4318,8 @@ netdev_dpdk_update_flags__(struct netdev_dpdk *dev,\n \n netdev_change_seq_changed(&common->up);\n } else {\n+ struct netdev_dpdk *dev = netdev_dpdk_cast(&common->up);\n+\n /* If DPDK_DEV_VHOST device's NETDEV_UP flag was changed and vhost is\n * running then change netdev's change_seq to trigger link state\n * update. */\n@@ -4293,17 +4341,17 @@ netdev_dpdk_update_flags__(struct netdev_dpdk *dev,\n return 0;\n }\n \n-static int\n+int\n netdev_dpdk_update_flags(struct netdev *netdev,\n enum netdev_flags off, enum netdev_flags on,\n enum netdev_flags *old_flagsp)\n {\n- struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);\n+ struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);\n int error;\n \n- ovs_mutex_lock(&dev->common.mutex);\n- error = netdev_dpdk_update_flags__(dev, off, on, old_flagsp);\n- ovs_mutex_unlock(&dev->common.mutex);\n+ ovs_mutex_lock(&common->mutex);\n+ error = netdev_dpdk_update_flags__(common, off, on, old_flagsp);\n+ ovs_mutex_unlock(&common->mutex);\n \n return error;\n }\n@@ -4378,7 +4426,7 @@ netdev_dpdk_vhost_user_get_status(const struct netdev *netdev,\n * Convert a given uint32_t link speed defined in DPDK to a string\n * equivalent.\n */\n-static const char *\n+const char *\n netdev_dpdk_link_speed_to_str__(uint32_t link_speed)\n {\n switch (link_speed) {\n@@ -4398,31 +4446,28 @@ netdev_dpdk_link_speed_to_str__(uint32_t link_speed)\n }\n }\n \n-static int\n-netdev_dpdk_get_status(const struct netdev *netdev, struct smap *args)\n+int\n+netdev_dpdk_get_status__(const struct netdev *netdev,\n+ struct ovs_mutex *dev_mutex,\n+ struct smap *args)\n {\n struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);\n- struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);\n struct rte_eth_dev_info dev_info;\n- size_t rx_steer_flows_num;\n- uint64_t rx_steer_flags;\n uint32_t link_speed;\n- int n_rxq;\n int diag;\n \n if (!rte_eth_dev_is_valid_port(common->port_id)) {\n return ENODEV;\n }\n \n- ovs_mutex_lock(&dpdk_mutex);\n+ ovs_assert(dev_mutex);\n+\n+ ovs_mutex_lock(dev_mutex);\n ovs_mutex_lock(&common->mutex);\n diag = rte_eth_dev_info_get(common->port_id, &dev_info);\n link_speed = common->link.link_speed;\n- rx_steer_flags = dev->rx_steer_flags;\n- rx_steer_flows_num = dev->rx_steer_flows_num;\n- n_rxq = netdev->n_rxq;\n ovs_mutex_unlock(&common->mutex);\n- ovs_mutex_unlock(&dpdk_mutex);\n+ ovs_mutex_unlock(dev_mutex);\n \n smap_add_format(args, \"port_no\", DPDK_PORT_ID_FMT, common->port_id);\n smap_add_format(args, \"numa_id\", \"%d\",\n@@ -4477,6 +4522,29 @@ netdev_dpdk_get_status(const struct netdev *netdev, struct smap *args)\n ETH_ADDR_ARGS(common->hwaddr));\n }\n \n+ return 0;\n+}\n+\n+static int\n+netdev_dpdk_get_status(const struct netdev *netdev, struct smap *args)\n+{\n+ struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);\n+ size_t rx_steer_flows_num;\n+ uint64_t rx_steer_flags;\n+ int n_rxq;\n+ int ret;\n+\n+ ret = netdev_dpdk_get_status__(netdev, &dpdk_mutex, args);\n+ if (ret) {\n+ return ret;\n+ }\n+\n+ ovs_mutex_lock(&dev->common.mutex);\n+ rx_steer_flags = dev->rx_steer_flags;\n+ rx_steer_flows_num = dev->rx_steer_flows_num;\n+ n_rxq = netdev->n_rxq;\n+ ovs_mutex_unlock(&dev->common.mutex);\n+\n if (rx_steer_flags && !rx_steer_flows_num) {\n smap_add(args, \"rx-steering\", \"unsupported\");\n } else if (rx_steer_flags == DPDK_RX_STEER_LACP) {\n@@ -4499,15 +4567,16 @@ netdev_dpdk_get_status(const struct netdev *netdev, struct smap *args)\n }\n \n static void\n-netdev_dpdk_set_admin_state__(struct netdev_dpdk *dev, bool admin_state)\n- OVS_REQUIRES(dev->common.mutex)\n+netdev_dpdk_set_admin_state__(struct netdev_dpdk_common *common,\n+ bool admin_state)\n+ OVS_REQUIRES(common->mutex)\n {\n enum netdev_flags old_flags;\n \n if (admin_state) {\n- netdev_dpdk_update_flags__(dev, 0, NETDEV_UP, &old_flags);\n+ netdev_dpdk_update_flags__(common, 0, NETDEV_UP, &old_flags);\n } else {\n- netdev_dpdk_update_flags__(dev, NETDEV_UP, 0, &old_flags);\n+ netdev_dpdk_update_flags__(common, NETDEV_UP, 0, &old_flags);\n }\n }\n \n@@ -4530,11 +4599,12 @@ netdev_dpdk_set_admin_state(struct unixctl_conn *conn, int argc,\n struct netdev *netdev = netdev_from_name(argv[1]);\n \n if (netdev && is_dpdk_class(netdev->netdev_class)) {\n- struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);\n+ struct netdev_dpdk_common *common =\n+ netdev_dpdk_common_cast(netdev);\n \n- ovs_mutex_lock(&dev->common.mutex);\n- netdev_dpdk_set_admin_state__(dev, up);\n- ovs_mutex_unlock(&dev->common.mutex);\n+ ovs_mutex_lock(&common->mutex);\n+ netdev_dpdk_set_admin_state__(common, up);\n+ ovs_mutex_unlock(&common->mutex);\n \n netdev_close(netdev);\n } else {\n@@ -4548,7 +4618,7 @@ netdev_dpdk_set_admin_state(struct unixctl_conn *conn, int argc,\n ovs_mutex_lock(&dpdk_mutex);\n LIST_FOR_EACH (dev, common.list_node, &dpdk_list) {\n ovs_mutex_lock(&dev->common.mutex);\n- netdev_dpdk_set_admin_state__(dev, up);\n+ netdev_dpdk_set_admin_state__(&dev->common, up);\n ovs_mutex_unlock(&dev->common.mutex);\n }\n ovs_mutex_unlock(&dpdk_mutex);\n@@ -5144,9 +5214,14 @@ netdev_dpdk_class_init(void)\n /* This function can be called for different classes. The initialization\n * needs to be done only once */\n if (ovsthread_once_start(&once)) {\n+ static struct netdev_dpdk_watchdog_params watchdog_params = {\n+ .mutex = &dpdk_mutex,\n+ .list = &dpdk_list,\n+ };\n int ret;\n \n- ovs_thread_create(\"dpdk_watchdog\", dpdk_watchdog, NULL);\n+ ovs_thread_create(\"dpdk_watchdog\", netdev_dpdk_watchdog,\n+ &watchdog_params);\n unixctl_command_register(\"netdev-dpdk/set-admin-state\",\n \"[netdev] up|down\", 1, 2,\n netdev_dpdk_set_admin_state, NULL);\n@@ -6158,7 +6233,8 @@ retry:\n dev->common.tx_q = NULL;\n \n if (!eth_addr_equals(dev->common.hwaddr, dev->common.requested_hwaddr)) {\n- err = netdev_dpdk_set_etheraddr__(dev, dev->common.requested_hwaddr);\n+ err = netdev_dpdk_set_etheraddr__(&dev->common,\n+ dev->common.requested_hwaddr);\n if (err) {\n goto out;\n }\n@@ -6676,7 +6752,7 @@ parse_user_mempools_list(const struct smap *ovs_other_config)\n \n user_mempools = xrealloc(user_mempools, (n_user_mempools + 1) *\n sizeof(struct user_mempool_config));\n- adj_mtu = FRAME_LEN_TO_MTU(dpdk_buf_size(mtu));\n+ adj_mtu = FRAME_LEN_TO_MTU(netdev_dpdk_buf_size(mtu));\n user_mempools[n_user_mempools].adj_mtu = adj_mtu;\n user_mempools[n_user_mempools].socket_id = socket_id;\n n_user_mempools++;\n", "prefixes": [ "ovs-dev", "v3", "08/11" ] }