From patchwork Tue Feb 2 10:35:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 375908 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-24.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EEB91C433E0 for ; Tue, 2 Feb 2021 10:36:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C2E7864E41 for ; Tue, 2 Feb 2021 10:36:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229852AbhBBKgZ (ORCPT ); Tue, 2 Feb 2021 05:36:25 -0500 Received: from hqnvemgate24.nvidia.com ([216.228.121.143]:7188 "EHLO hqnvemgate24.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229633AbhBBKgQ (ORCPT ); Tue, 2 Feb 2021 05:36:16 -0500 Received: from hqmail.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate24.nvidia.com (using TLS: TLSv1.2, AES256-SHA) id ; Tue, 02 Feb 2021 02:35:36 -0800 Received: from sw-mtx-036.mtx.labs.mlnx (172.20.145.6) by HQMAIL107.nvidia.com (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Tue, 2 Feb 2021 10:35:35 +0000 From: Parav Pandit To: , , , , , CC: Parav Pandit Subject: [PATCH iproute2-next v3 1/5] Add kernel headers Date: Tue, 2 Feb 2021 12:35:14 +0200 Message-ID: <20210202103518.3858-2-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210202103518.3858-1-parav@nvidia.com> References: <20210122112654.9593-3-parav@nvidia.com> <20210202103518.3858-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [172.20.145.6] X-ClientProxiedBy: HQMAIL111.nvidia.com (172.20.187.18) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1612262136; bh=Zx7Y+EElvznYsinOctSzijr05C7rIpbbJtcqWI5Cu0w=; h=From:To:CC:Subject:Date:Message-ID:X-Mailer:In-Reply-To: References:MIME-Version:Content-Transfer-Encoding:Content-Type: X-Originating-IP:X-ClientProxiedBy; b=HNyQ1qychsYEuJ5VGRJHtmCAF/hGUBjytRmNIYszWiRpM8GStR8Zv97CI3pl2fd7b NAdM31JvbhhJYGwvC8Fn+y2jtWySPfHzHnQcKxbNxCkpw3bc40u2yLO9guM265eUT6 xUl1a8uWzcTWYw+yG7YeAtALXlTlh4AnYau08j0bhaBU9WjxVdc5MI9OZvoGwYq3X6 V4Y/AE1z54WYbqfEvgf29A+gd9kemml4KRsb0lzxIgiBBKcmgDlvB2j11orOVCaP1v u2SOrUFAH3iHzdNGh6gJT7ojskB64TsHDXNi4sfaHUjbSQUaxxWba+52ZyNciDMNj4 qgQyo+mKBFK3Q== Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add kernel headers to commit from kernel tree [1]. 79991caf5202c7 ("vdpa_sim_net: Add support for user supported devices") [1] https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git branch: linux-next Signed-off-by: Parav Pandit --- include/uapi/linux/vdpa.h | 40 +++++++++++++++++++++++ include/uapi/linux/virtio_ids.h | 58 +++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 include/uapi/linux/vdpa.h create mode 100644 include/uapi/linux/virtio_ids.h diff --git a/include/uapi/linux/vdpa.h b/include/uapi/linux/vdpa.h new file mode 100644 index 00000000..66a41e4e --- /dev/null +++ b/include/uapi/linux/vdpa.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * vdpa device management interface + * Copyright (c) 2020 Mellanox Technologies Ltd. All rights reserved. + */ + +#ifndef _UAPI_LINUX_VDPA_H_ +#define _UAPI_LINUX_VDPA_H_ + +#define VDPA_GENL_NAME "vdpa" +#define VDPA_GENL_VERSION 0x1 + +enum vdpa_command { + VDPA_CMD_UNSPEC, + VDPA_CMD_MGMTDEV_NEW, + VDPA_CMD_MGMTDEV_GET, /* can dump */ + VDPA_CMD_DEV_NEW, + VDPA_CMD_DEV_DEL, + VDPA_CMD_DEV_GET, /* can dump */ +}; + +enum vdpa_attr { + VDPA_ATTR_UNSPEC, + + /* bus name (optional) + dev name together make the parent device handle */ + VDPA_ATTR_MGMTDEV_BUS_NAME, /* string */ + VDPA_ATTR_MGMTDEV_DEV_NAME, /* string */ + VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES, /* u64 */ + + VDPA_ATTR_DEV_NAME, /* string */ + VDPA_ATTR_DEV_ID, /* u32 */ + VDPA_ATTR_DEV_VENDOR_ID, /* u32 */ + VDPA_ATTR_DEV_MAX_VQS, /* u32 */ + VDPA_ATTR_DEV_MAX_VQ_SIZE, /* u16 */ + + /* new attributes must be added above here */ + VDPA_ATTR_MAX, +}; + +#endif diff --git a/include/uapi/linux/virtio_ids.h b/include/uapi/linux/virtio_ids.h new file mode 100644 index 00000000..bc1c0621 --- /dev/null +++ b/include/uapi/linux/virtio_ids.h @@ -0,0 +1,58 @@ +#ifndef _LINUX_VIRTIO_IDS_H +#define _LINUX_VIRTIO_IDS_H +/* + * Virtio IDs + * + * This header is BSD licensed so anyone can use the definitions to implement + * compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of IBM 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 IBM 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. */ + +#define VIRTIO_ID_NET 1 /* virtio net */ +#define VIRTIO_ID_BLOCK 2 /* virtio block */ +#define VIRTIO_ID_CONSOLE 3 /* virtio console */ +#define VIRTIO_ID_RNG 4 /* virtio rng */ +#define VIRTIO_ID_BALLOON 5 /* virtio balloon */ +#define VIRTIO_ID_IOMEM 6 /* virtio ioMemory */ +#define VIRTIO_ID_RPMSG 7 /* virtio remote processor messaging */ +#define VIRTIO_ID_SCSI 8 /* virtio scsi */ +#define VIRTIO_ID_9P 9 /* 9p virtio console */ +#define VIRTIO_ID_MAC80211_WLAN 10 /* virtio WLAN MAC */ +#define VIRTIO_ID_RPROC_SERIAL 11 /* virtio remoteproc serial link */ +#define VIRTIO_ID_CAIF 12 /* Virtio caif */ +#define VIRTIO_ID_MEMORY_BALLOON 13 /* virtio memory balloon */ +#define VIRTIO_ID_GPU 16 /* virtio GPU */ +#define VIRTIO_ID_CLOCK 17 /* virtio clock/timer */ +#define VIRTIO_ID_INPUT 18 /* virtio input */ +#define VIRTIO_ID_VSOCK 19 /* virtio vsock transport */ +#define VIRTIO_ID_CRYPTO 20 /* virtio crypto */ +#define VIRTIO_ID_SIGNAL_DIST 21 /* virtio signal distribution device */ +#define VIRTIO_ID_PSTORE 22 /* virtio pstore device */ +#define VIRTIO_ID_IOMMU 23 /* virtio IOMMU */ +#define VIRTIO_ID_MEM 24 /* virtio mem */ +#define VIRTIO_ID_FS 26 /* virtio filesystem */ +#define VIRTIO_ID_PMEM 27 /* virtio pmem */ +#define VIRTIO_ID_MAC80211_HWSIM 29 /* virtio mac80211-hwsim */ + +#endif /* _LINUX_VIRTIO_IDS_H */ From patchwork Tue Feb 2 10:35:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 375033 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AE6ADC433E9 for ; Tue, 2 Feb 2021 10:36:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6D14964E40 for ; Tue, 2 Feb 2021 10:36:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229909AbhBBKgZ (ORCPT ); Tue, 2 Feb 2021 05:36:25 -0500 Received: from hqnvemgate26.nvidia.com ([216.228.121.65]:1352 "EHLO hqnvemgate26.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229634AbhBBKgT (ORCPT ); Tue, 2 Feb 2021 05:36:19 -0500 Received: from hqmail.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate26.nvidia.com (using TLS: TLSv1.2, AES256-SHA) id ; Tue, 02 Feb 2021 02:35:37 -0800 Received: from sw-mtx-036.mtx.labs.mlnx (172.20.145.6) by HQMAIL107.nvidia.com (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Tue, 2 Feb 2021 10:35:36 +0000 From: Parav Pandit To: , , , , , CC: Parav Pandit Subject: [PATCH iproute2-next v3 2/5] utils: Add helper routines for indent handling Date: Tue, 2 Feb 2021 12:35:15 +0200 Message-ID: <20210202103518.3858-3-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210202103518.3858-1-parav@nvidia.com> References: <20210122112654.9593-3-parav@nvidia.com> <20210202103518.3858-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [172.20.145.6] X-ClientProxiedBy: HQMAIL111.nvidia.com (172.20.187.18) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1612262137; bh=HDT133gXudxB52omx1TuwZ9j1XEiBgbv7aS9W5cuFWc=; h=From:To:CC:Subject:Date:Message-ID:X-Mailer:In-Reply-To: References:MIME-Version:Content-Transfer-Encoding:Content-Type: X-Originating-IP:X-ClientProxiedBy; b=F0kHY59seyuMIo83PNO700wEQKWx/LGg2pWsTnPsgm2xuLlGaZiY8lopzEdksj28v JqSQNS0+0u4IFyjuPICUZ868WR1AjbZtzSeLwESS1tcY313aHvoN3J6Iynrrpm0Ols b2V7uFKTK/B5p3rc6Xrcz5T0VVCAHefePb1F24oUhZet7iUqVFu2wpEu8rt2XIG5/w l/J5ypU9osePvD9H+2AEU7U2nlWgcXIxIYBLfWDEvnsa94yUvbpOGQke8O8BWaaO8H HX2XoUkQPxpPJYpt9oij3Fhlznm47GPdaGungMX+ARRQH8Xy4bC41poY3rM6Xasl9x d26ApxyZeeHyA== Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Subsequent patch needs to use 2 char indentation for nested objects. Hence introduce a generic helpers to allocate, deallocate, increment, decrement and to print indent block. Signed-off-by: Parav Pandit --- changelog: v2->v3: - patch split from vdpa tool patch --- include/utils.h | 16 ++++++++++++ lib/utils.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/include/utils.h b/include/utils.h index e66090ae..9b76c92a 100644 --- a/include/utils.h +++ b/include/utils.h @@ -349,4 +349,20 @@ int str_map_lookup_str(const struct str_num_map *map, const char *needle); const char *str_map_lookup_u16(const struct str_num_map *map, uint16_t val); const char *str_map_lookup_u8(const struct str_num_map *map, uint8_t val); +unsigned int get_str_char_count(const char *str, int match); +int str_split_by_char(char *str, char **before, char **after, int match); + +#define INDENT_STR_MAXLEN 32 + +struct indent_mem { + int indent_level; + char indent_str[INDENT_STR_MAXLEN + 1]; +}; + +struct indent_mem *alloc_indent_mem(void); +void free_indent_mem(struct indent_mem *mem); +void inc_indent(struct indent_mem *mem); +void dec_indent(struct indent_mem *mem); +void print_indent(struct indent_mem *mem); + #endif /* __UTILS_H__ */ diff --git a/lib/utils.c b/lib/utils.c index af1b553c..cc6d0e34 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -1978,3 +1978,69 @@ const char *str_map_lookup_u8(const struct str_num_map *map, uint8_t val) } return NULL; } + +unsigned int get_str_char_count(const char *str, int match) +{ + unsigned int count = 0; + const char *pos = str; + + while ((pos = strchr(pos, match))) { + count++; + pos++; + } + return count; +} + +int str_split_by_char(char *str, char **before, char **after, int match) +{ + char *slash; + + slash = strrchr(str, match); + if (!slash) + return -EINVAL; + *slash = '\0'; + *before = str; + *after = slash + 1; + return 0; +} + +struct indent_mem *alloc_indent_mem(void) +{ + struct indent_mem *mem = malloc(sizeof(*mem)); + + if (!mem) + return NULL; + strcpy(mem->indent_str, ""); + mem->indent_level = 0; + return mem; +} + +void free_indent_mem(struct indent_mem *mem) +{ + free(mem); +} + +#define INDENT_STR_STEP 2 + +void inc_indent(struct indent_mem *mem) +{ + if (mem->indent_level + INDENT_STR_STEP > INDENT_STR_MAXLEN) + return; + mem->indent_level += INDENT_STR_STEP; + memset(mem->indent_str, ' ', sizeof(mem->indent_str)); + mem->indent_str[mem->indent_level] = '\0'; +} + +void dec_indent(struct indent_mem *mem) +{ + if (mem->indent_level - INDENT_STR_STEP < 0) + return; + mem->indent_level -= INDENT_STR_STEP; + mem->indent_str[mem->indent_level] = '\0'; +} + +void print_indent(struct indent_mem *mem) +{ + if (mem->indent_level) + printf("%s", mem->indent_str); +} From patchwork Tue Feb 2 10:35:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 375906 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AC1CFC433E0 for ; Tue, 2 Feb 2021 10:37:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6D87564EDA for ; Tue, 2 Feb 2021 10:37:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229986AbhBBKhC (ORCPT ); Tue, 2 Feb 2021 05:37:02 -0500 Received: from hqnvemgate24.nvidia.com ([216.228.121.143]:7257 "EHLO hqnvemgate24.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229643AbhBBKg7 (ORCPT ); Tue, 2 Feb 2021 05:36:59 -0500 Received: from hqmail.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate24.nvidia.com (using TLS: TLSv1.2, AES256-SHA) id ; Tue, 02 Feb 2021 02:35:39 -0800 Received: from sw-mtx-036.mtx.labs.mlnx (172.20.145.6) by HQMAIL107.nvidia.com (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Tue, 2 Feb 2021 10:35:38 +0000 From: Parav Pandit To: , , , , , CC: Parav Pandit Subject: [PATCH iproute2-next v3 4/5] utils: Add helper to map string to unsigned int Date: Tue, 2 Feb 2021 12:35:17 +0200 Message-ID: <20210202103518.3858-5-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210202103518.3858-1-parav@nvidia.com> References: <20210122112654.9593-3-parav@nvidia.com> <20210202103518.3858-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [172.20.145.6] X-ClientProxiedBy: HQMAIL111.nvidia.com (172.20.187.18) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1612262139; bh=wb+dkpPaTiWpTz3BlBWkumEuJWVmUA/mgN3gQd43q88=; h=From:To:CC:Subject:Date:Message-ID:X-Mailer:In-Reply-To: References:MIME-Version:Content-Transfer-Encoding:Content-Type: X-Originating-IP:X-ClientProxiedBy; b=hZsuxxZvFFv6nQ0NHttPB3MW7sY+Kuh8g8EbFQlDzXKJ8JQZiDYGwzANt3ZYL9qBC ck1xSWTOfqFKn8PtQZ8dko/s/9OSYZz5nUn5PabKmwHbGMRyGPcEdjNp61xU55oI/W ueVFqnS9SEzAsUAzu1IQ+OuQ8hB9Uv5bibB8zafoGkE9Yegty88zWzbPnpGm4Ii+ky DzfxXurEcYeaVNJBn5NpEbRQcFo0tZzdo7jhurna+vnkuXf+5k/HREu/UlkIQ87I0c qRgDwcRHp70GFYEyN7Z561Mgfkc+AOy3y5A5fxMI1JGNgz/cAGYlUdhBqZ0iEF1j4T lpvlX36noyJGA== Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org In subsequent patch need to map a string to a unsigned int. Hence, add an API to map a string to unsigned int. Signed-off-by: Parav Pandit --- changelog: v2->v3: - new patch to reuse string to unsigned int mapping --- include/utils.h | 4 +++- lib/utils.c | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/include/utils.h b/include/utils.h index 9b76c92a..b29c3798 100644 --- a/include/utils.h +++ b/include/utils.h @@ -342,10 +342,12 @@ int parse_mapping(int *argcp, char ***argvp, bool allow_all, struct str_num_map { const char *str; - int num; + unsigned int num; }; int str_map_lookup_str(const struct str_num_map *map, const char *needle); +const char *str_map_lookup_uint(const struct str_num_map *map, + unsigned int val); const char *str_map_lookup_u16(const struct str_num_map *map, uint16_t val); const char *str_map_lookup_u8(const struct str_num_map *map, uint8_t val); diff --git a/lib/utils.c b/lib/utils.c index cc6d0e34..633f6359 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -1953,9 +1953,22 @@ int str_map_lookup_str(const struct str_num_map *map, const char *needle) return -EINVAL; } +const char *str_map_lookup_uint(const struct str_num_map *map, unsigned int val) +{ + unsigned int num = val; + + while (map && map->str) { + if (num == map->num) + return map->str; + + map++; + } + return NULL; +} + const char *str_map_lookup_u16(const struct str_num_map *map, uint16_t val) { - int num = val; + unsigned int num = val; while (map && map->str) { if (num == map->num) @@ -1968,7 +1981,7 @@ const char *str_map_lookup_u16(const struct str_num_map *map, uint16_t val) const char *str_map_lookup_u8(const struct str_num_map *map, uint8_t val) { - int num = val; + unsigned int num = val; while (map && map->str) { if (num == map->num) From patchwork Tue Feb 2 10:35:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 375907 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 07A43C433E0 for ; Tue, 2 Feb 2021 10:36:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A3AFC64EBF for ; Tue, 2 Feb 2021 10:36:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229693AbhBBKgo (ORCPT ); Tue, 2 Feb 2021 05:36:44 -0500 Received: from hqnvemgate25.nvidia.com ([216.228.121.64]:4821 "EHLO hqnvemgate25.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229724AbhBBKgV (ORCPT ); Tue, 2 Feb 2021 05:36:21 -0500 Received: from hqmail.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate25.nvidia.com (using TLS: TLSv1.2, AES256-SHA) id ; Tue, 02 Feb 2021 02:35:40 -0800 Received: from sw-mtx-036.mtx.labs.mlnx (172.20.145.6) by HQMAIL107.nvidia.com (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Tue, 2 Feb 2021 10:35:39 +0000 From: Parav Pandit To: , , , , , CC: Parav Pandit Subject: [PATCH iproute2-next v3 5/5] vdpa: Add vdpa tool Date: Tue, 2 Feb 2021 12:35:18 +0200 Message-ID: <20210202103518.3858-6-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210202103518.3858-1-parav@nvidia.com> References: <20210122112654.9593-3-parav@nvidia.com> <20210202103518.3858-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [172.20.145.6] X-ClientProxiedBy: HQMAIL111.nvidia.com (172.20.187.18) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1612262140; bh=z7sryTrXYLILEqH4Hu7FHNiCUSVQEG1ECrI1QzICLrM=; h=From:To:CC:Subject:Date:Message-ID:X-Mailer:In-Reply-To: References:MIME-Version:Content-Transfer-Encoding:Content-Type: X-Originating-IP:X-ClientProxiedBy; b=Dyhs065oshWoRpkplVaYG2l9KPRLs91krsTRGe9+L/s1PSRUZ0w9NZmDZKIGxqDI8 VUp7qAnEoyeYftbzwLo6ltBQt5boJbW0J1TlemlER4l9E1Np6hzSl3VLQ8aVU/7dbE pEYLR2LBXdTVX6tMC1s17ma9i+vZBig6RvhwidPfDO7GjsE5GjpRV2ORyADI0vaWhw h0cTxefl+XCvgLVKcuW9ryF0On5Bbki905HSpiZrM1rYesNC/ISSKsJBW00SH0KrTi vSzOP0NccrbVLES221NzfMDdcKw7JZyiJSB9Rix/HxcY+Q34Tcn0Yv2dYFgCsb0i9N 0j/QDWw/cnKHQ== Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org vdpa tool is created to create, delete and query vdpa devices. examples: Show vdpa management device that supports creating, deleting vdpa devices. $ vdpa mgmtdev show vdpasim: supported_classes net $ vdpa mgmtdev show -jp { "show": { "vdpasim": { "supported_classes": [ "net" ] } } } Create a vdpa device of type networking named as "foo2" from the management device vdpasim_net: $ vdpa dev add mgmtdev vdpasim_net name foo2 Show the newly created vdpa device by its name: $ vdpa dev show foo2 foo2: type network mgmtdev vdpasim_net vendor_id 0 max_vqs 2 max_vq_size 256 $ vdpa dev show foo2 -jp { "dev": { "foo2": { "type": "network", "mgmtdev": "vdpasim_net", "vendor_id": 0, "max_vqs": 2, "max_vq_size": 256 } } } Delete the vdpa device after its use: $ vdpa dev del foo2 Signed-off-by: Parav Pandit --- Makefile | 2 +- man/man8/vdpa-dev.8 | 96 ++++++ man/man8/vdpa-mgmtdev.8 | 53 ++++ man/man8/vdpa.8 | 76 +++++ vdpa/Makefile | 24 ++ vdpa/vdpa.c | 675 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 925 insertions(+), 1 deletion(-) create mode 100644 man/man8/vdpa-dev.8 create mode 100644 man/man8/vdpa-mgmtdev.8 create mode 100644 man/man8/vdpa.8 create mode 100644 vdpa/Makefile create mode 100644 vdpa/vdpa.c diff --git a/Makefile b/Makefile index e64c6599..19bd163e 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,7 @@ WFLAGS += -Wmissing-declarations -Wold-style-definition -Wformat=2 CFLAGS := $(WFLAGS) $(CCOPTS) -I../include -I../include/uapi $(DEFINES) $(CFLAGS) YACCFLAGS = -d -t -v -SUBDIRS=lib ip tc bridge misc netem genl tipc devlink rdma dcb man +SUBDIRS=lib ip tc bridge misc netem genl tipc devlink rdma dcb man vdpa LIBNETLINK=../lib/libutil.a ../lib/libnetlink.a LDLIBS += $(LIBNETLINK) diff --git a/man/man8/vdpa-dev.8 b/man/man8/vdpa-dev.8 new file mode 100644 index 00000000..36433519 --- /dev/null +++ b/man/man8/vdpa-dev.8 @@ -0,0 +1,96 @@ +.TH DEVLINK\-DEV 8 "5 Jan 2021" "iproute2" "Linux" +.SH NAME +vdpa-dev \- vdpa device configuration +.SH SYNOPSIS +.sp +.ad l +.in +8 +.ti -8 +.B vdpa +.B dev +.RI "[ " OPTIONS " ] " +.RI " { " COMMAND | " " +.BR help " }" +.sp + +.ti -8 +.IR OPTIONS " := { " +\fB\-V\fR[\fIersion\fR] +} + +.ti -8 +.B vdpa dev show +.RI "[ " DEV " ]" + +.ti -8 +.B vdpa dev help + +.ti -8 +.B vdpa dev add +.B name +.I NAME +.B mgmtdev +.I MGMTDEV + +.ti -8 +.B vdpa dev del +.I DEV + +.SH "DESCRIPTION" +.SS vdpa dev show - display vdpa device attributes + +.PP +.I "DEV" +- specifies the vdpa device to show. +If this argument is omitted all devices are listed. + +.in +4 +Format is: +.in +2 +VDPA_DEVICE_NAME + +.SS vdpa dev add - add a new vdpa device. + +.TP +.BI name " NAME" +Name of the new vdpa device to add. + +.TP +.BI mgmtdev " MGMTDEV" +Name of the management device to use for device addition. + +.SS vdpa dev del - Delete the vdpa device. + +.PP +.I "DEV" +- specifies the vdpa device to delete. + +.SH "EXAMPLES" +.PP +vdpa dev show +.RS 4 +Shows the all vdpa devices on the system. +.RE +.PP +vdpa dev show foo +.RS 4 +Shows the specified vdpa device. +.RE +.PP +vdpa dev add name foo mgmtdev vdpa_sim_net +.RS 4 +Add the vdpa device named foo on the management device vdpa_sim_net. +.RE +.PP +vdpa dev del foo +.RS 4 +Delete the vdpa device named foo which was previously created. +.RE + +.SH SEE ALSO +.BR vdpa (8), +.BR vdpa-mgmtdev (8), +.br + +.SH AUTHOR +Parav Pandit diff --git a/man/man8/vdpa-mgmtdev.8 b/man/man8/vdpa-mgmtdev.8 new file mode 100644 index 00000000..cae2cbd0 --- /dev/null +++ b/man/man8/vdpa-mgmtdev.8 @@ -0,0 +1,53 @@ +.TH DEVLINK\-DEV 8 "5 Jan 2021" "iproute2" "Linux" +.SH NAME +vdpa-dev \- vdpa management device view +.SH SYNOPSIS +.sp +.ad l +.in +8 +.ti -8 +.B vdpa +.B mgmtdev +.RI " { " COMMAND | " " +.BR help " }" +.sp + +.ti -8 +.IR OPTIONS " := { " +\fB\-V\fR[\fIersion\fR] +} + +.ti -8 +.B vdpa mgmtdev show +.RI "[ " MGMTDEV " ]" + +.ti -8 +.B vdpa mgmtdev help + +.SH "DESCRIPTION" +.SS vdpa mgmtdev show - display vdpa management device attributes + +.PP +.I "MGMTDEV" +- specifies the vdpa management device to show. +If this argument is omitted all management devices are listed. + +.SH "EXAMPLES" +.PP +vdpa mgmtdev show +.RS 4 +Shows all the vdpa management devices on the system. +.RE +.PP +vdpa mgmtdev show bar +.RS 4 +Shows the specified vdpa management device. +.RE + +.SH SEE ALSO +.BR vdpa (8), +.BR vdpa-dev (8), +.br + +.SH AUTHOR +Parav Pandit diff --git a/man/man8/vdpa.8 b/man/man8/vdpa.8 new file mode 100644 index 00000000..d1aaecec --- /dev/null +++ b/man/man8/vdpa.8 @@ -0,0 +1,76 @@ +.TH VDPA 8 "5 Jan 2021" "iproute2" "Linux" +.SH NAME +vdpa \- vdpa management tool +.SH SYNOPSIS +.sp +.ad l +.in +8 +.ti -8 +.B vdpa +.RI "[ " OPTIONS " ] { " dev | mgmtdev " } { " COMMAND " | " +.BR help " }" +.sp + +.SH OPTIONS + +.TP +.BR "\-V" , " --Version" +Print the version of the +.B vdpa +utility and exit. + +.TP +.BR "\-j" , " --json" +Generate JSON output. + +.TP +.BR "\-p" , " --pretty" +When combined with -j generate a pretty JSON output. + +.SS +.I OBJECT + +.TP +.B dev +- vdpa device. + +.TP +.B mgmtdev +- vdpa management device. + +.SS +.I COMMAND + +Specifies the action to perform on the object. +The set of possible actions depends on the object type. +It is possible to +.B show +(or +.B list +) objects. The +.B help +command is available for all objects. It prints +out a list of available commands and argument syntax conventions. +.sp +If no command is given, some default command is assumed. +Usually it is +.B show +or, if the objects of this class cannot be listed, +.BR "help" . + +.SH EXIT STATUS +Exit status is 0 if command was successful or a positive integer upon failure. + +.SH SEE ALSO +.BR vdpa-dev (8), +.BR vdpa-mgmtdev (8), +.br + +.SH REPORTING BUGS +Report any bugs to the Network Developers mailing list +.B +where the development and maintenance is primarily done. +You do not have to be subscribed to the list to send a message there. + +.SH AUTHOR +Parav Pandit diff --git a/vdpa/Makefile b/vdpa/Makefile new file mode 100644 index 00000000..275f9ded --- /dev/null +++ b/vdpa/Makefile @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +include ../config.mk + +TARGETS := + +ifeq ($(HAVE_MNL),y) + +VDPAOBJ = vdpa.o +TARGETS += vdpa + +endif + +all: $(TARGETS) $(LIBS) + +vdpa: $(VDPAOBJ) + $(QUIET_LINK)$(CC) $^ $(LDFLAGS) $(LDLIBS) -o $@ + +install: all + for i in $(TARGETS); \ + do install -m 0755 $$i $(DESTDIR)$(SBINDIR); \ + done + +clean: + rm -f $(VDPAOBJ) $(TARGETS) diff --git a/vdpa/vdpa.c b/vdpa/vdpa.c new file mode 100644 index 00000000..7fdb36b9 --- /dev/null +++ b/vdpa/vdpa.c @@ -0,0 +1,675 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "mnl_utils.h" + +#include "version.h" +#include "json_print.h" +#include "utils.h" + +#define VDPA_OPT_MGMTDEV_HANDLE BIT(0) +#define VDPA_OPT_VDEV_MGMTDEV_HANDLE BIT(1) +#define VDPA_OPT_VDEV_NAME BIT(2) +#define VDPA_OPT_VDEV_HANDLE BIT(3) + +struct vdpa_opts { + uint64_t present; /* flags of present items */ + char *mdev_bus_name; + char *mdev_name; + const char *vdev_name; + unsigned int device_id; +}; + +struct vdpa { + struct mnlu_gen_socket nlg; + struct vdpa_opts opts; + bool json_output; + struct indent_mem *indent; +}; + +static void pr_out_section_start(struct vdpa *vdpa, const char *name) +{ + open_json_object(NULL); + open_json_object(name); +} + +static void pr_out_section_end(struct vdpa *vdpa) +{ + close_json_object(); + close_json_object(); +} + +static void pr_out_array_start(struct vdpa *vdpa, const char *name) +{ + if (!vdpa->json_output) { + print_nl(); + inc_indent(vdpa->indent); + print_indent(vdpa->indent); + } + open_json_array(PRINT_ANY, name); +} + +static void pr_out_array_end(struct vdpa *vdpa) +{ + close_json_array(PRINT_JSON, NULL); + if (!vdpa->json_output) + dec_indent(vdpa->indent); +} + +static const enum mnl_attr_data_type vdpa_policy[VDPA_ATTR_MAX + 1] = { + [VDPA_ATTR_MGMTDEV_BUS_NAME] = MNL_TYPE_NUL_STRING, + [VDPA_ATTR_MGMTDEV_DEV_NAME] = MNL_TYPE_NUL_STRING, + [VDPA_ATTR_DEV_NAME] = MNL_TYPE_STRING, + [VDPA_ATTR_DEV_ID] = MNL_TYPE_U32, + [VDPA_ATTR_DEV_VENDOR_ID] = MNL_TYPE_U32, + [VDPA_ATTR_DEV_MAX_VQS] = MNL_TYPE_U32, + [VDPA_ATTR_DEV_MAX_VQ_SIZE] = MNL_TYPE_U16, +}; + +static int attr_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type; + + if (mnl_attr_type_valid(attr, VDPA_ATTR_MAX) < 0) + return MNL_CB_OK; + + type = mnl_attr_get_type(attr); + if (mnl_attr_validate(attr, vdpa_policy[type]) < 0) + return MNL_CB_ERROR; + + tb[type] = attr; + return MNL_CB_OK; +} + +static int vdpa_argv_handle(struct vdpa *vdpa, int argc, char **argv, + char **p_mdev_bus_name, + char **p_mdev_name) +{ + unsigned int slashcount; + char *str; + + if (argc <= 0 || *argv == NULL) { + fprintf(stderr, + "vdpa identification (\"mgmtdev_bus_name/mgmtdev_name\") expected\n"); + return -EINVAL; + } + str = *argv; + slashcount = get_str_char_count(str, '/'); + if (slashcount > 1) { + fprintf(stderr, + "Wrong vdpa mgmtdev identification string format\n"); + fprintf(stderr, "Expected \"mgmtdev_bus_name/mgmtdev_name\"\n"); + fprintf(stderr, "Expected \"mgmtdev_name\"\n"); + return -EINVAL; + } + switch (slashcount) { + case 0: + *p_mdev_bus_name = NULL; + *p_mdev_name = str; + return 0; + case 1: + str_split_by_char(str, p_mdev_bus_name, p_mdev_name, '/'); + return 0; + default: + return -EINVAL; + } +} + +static int vdpa_argv_str(struct vdpa *vdpa, int argc, char **argv, + const char **p_str) +{ + if (argc <= 0 || *argv == NULL) { + fprintf(stderr, "String parameter expected\n"); + return -EINVAL; + } + *p_str = *argv; + return 0; +} + +struct vdpa_args_metadata { + uint64_t o_flag; + const char *err_msg; +}; + +static const struct vdpa_args_metadata vdpa_args_required[] = { + {VDPA_OPT_VDEV_MGMTDEV_HANDLE, "management device handle not set."}, + {VDPA_OPT_VDEV_NAME, "device name is not set."}, + {VDPA_OPT_VDEV_HANDLE, "device name is not set."}, +}; + +static int vdpa_args_finding_required_validate(uint64_t o_required, + uint64_t o_found) +{ + uint64_t o_flag; + int i; + + for (i = 0; i < ARRAY_SIZE(vdpa_args_required); i++) { + o_flag = vdpa_args_required[i].o_flag; + if ((o_required & o_flag) && !(o_found & o_flag)) { + fprintf(stderr, "%s\n", vdpa_args_required[i].err_msg); + return -EINVAL; + } + } + if (o_required & ~o_found) { + fprintf(stderr, + "BUG: unknown argument required but not found\n"); + return -EINVAL; + } + return 0; +} + +static void vdpa_opts_put(struct nlmsghdr *nlh, struct vdpa *vdpa) +{ + struct vdpa_opts *opts = &vdpa->opts; + + if ((opts->present & VDPA_OPT_MGMTDEV_HANDLE) || + (opts->present & VDPA_OPT_VDEV_MGMTDEV_HANDLE)) { + if (opts->mdev_bus_name) + mnl_attr_put_strz(nlh, VDPA_ATTR_MGMTDEV_BUS_NAME, + opts->mdev_bus_name); + mnl_attr_put_strz(nlh, VDPA_ATTR_MGMTDEV_DEV_NAME, + opts->mdev_name); + } + if ((opts->present & VDPA_OPT_VDEV_NAME) || + (opts->present & VDPA_OPT_VDEV_HANDLE)) + mnl_attr_put_strz(nlh, VDPA_ATTR_DEV_NAME, opts->vdev_name); +} + +static int vdpa_argv_parse(struct vdpa *vdpa, int argc, char **argv, + uint64_t o_required) +{ + struct vdpa_opts *opts = &vdpa->opts; + uint64_t o_all = o_required; + uint64_t o_found = 0; + int err; + + if (o_required & VDPA_OPT_MGMTDEV_HANDLE) { + err = vdpa_argv_handle(vdpa, argc, argv, &opts->mdev_bus_name, + &opts->mdev_name); + if (err) + return err; + + NEXT_ARG_FWD(); + o_found |= VDPA_OPT_MGMTDEV_HANDLE; + } else if (o_required & VDPA_OPT_VDEV_HANDLE) { + err = vdpa_argv_str(vdpa, argc, argv, &opts->vdev_name); + if (err) + return err; + + NEXT_ARG_FWD(); + o_found |= VDPA_OPT_VDEV_HANDLE; + } + + while (NEXT_ARG_OK()) { + if ((matches(*argv, "name") == 0) && + (o_all & VDPA_OPT_VDEV_NAME)) { + const char *namestr; + + NEXT_ARG_FWD(); + err = vdpa_argv_str(vdpa, argc, argv, &namestr); + if (err) + return err; + opts->vdev_name = namestr; + NEXT_ARG_FWD(); + o_found |= VDPA_OPT_VDEV_NAME; + } else if ((matches(*argv, "mgmtdev") == 0) && + (o_all & VDPA_OPT_VDEV_MGMTDEV_HANDLE)) { + NEXT_ARG_FWD(); + err = vdpa_argv_handle(vdpa, argc, argv, + &opts->mdev_bus_name, + &opts->mdev_name); + if (err) + return err; + + NEXT_ARG_FWD(); + o_found |= VDPA_OPT_VDEV_MGMTDEV_HANDLE; + } else { + fprintf(stderr, "Unknown option \"%s\"\n", *argv); + return -EINVAL; + } + } + + opts->present = o_found; + + return vdpa_args_finding_required_validate(o_required, o_found); +} + +static int vdpa_argv_parse_put(struct nlmsghdr *nlh, struct vdpa *vdpa, + int argc, char **argv, + uint64_t o_required) +{ + int err; + + err = vdpa_argv_parse(vdpa, argc, argv, o_required); + if (err) + return err; + vdpa_opts_put(nlh, vdpa); + return 0; +} + +static void cmd_mgmtdev_help(void) +{ + fprintf(stderr, "Usage: vdpa mgmtdev show [ DEV ]\n"); +} + +static void pr_out_handle_start(struct vdpa *vdpa, struct nlattr **tb) +{ + const char *mdev_bus_name = NULL; + const char *mdev_name; + SPRINT_BUF(buf); + + mdev_name = mnl_attr_get_str(tb[VDPA_ATTR_MGMTDEV_DEV_NAME]); + if (tb[VDPA_ATTR_MGMTDEV_BUS_NAME]) { + mdev_bus_name = mnl_attr_get_str(tb[VDPA_ATTR_MGMTDEV_BUS_NAME]); + sprintf(buf, "%s/%s", mdev_bus_name, mdev_name); + } else { + sprintf(buf, "%s", mdev_name); + } + + if (vdpa->json_output) + open_json_object(buf); + else + printf("%s: ", buf); +} + +static void pr_out_handle_end(struct vdpa *vdpa) +{ + if (vdpa->json_output) + close_json_object(); + else + print_nl(); +} + +static void __pr_out_vdev_handle_start(struct vdpa *vdpa, const char *vdev_name) +{ + SPRINT_BUF(buf); + + sprintf(buf, "%s", vdev_name); + if (vdpa->json_output) + open_json_object(buf); + else + printf("%s: ", buf); +} + +static void pr_out_vdev_handle_start(struct vdpa *vdpa, struct nlattr **tb) +{ + const char *vdev_name; + + vdev_name = mnl_attr_get_str(tb[VDPA_ATTR_DEV_NAME]); + __pr_out_vdev_handle_start(vdpa, vdev_name); +} + +static void pr_out_vdev_handle_end(struct vdpa *vdpa) +{ + if (vdpa->json_output) + close_json_object(); + else + print_nl(); +} + +static struct str_num_map class_map[] = { + { .str = "net", .num = VIRTIO_ID_NET }, + { .str = "block", .num = VIRTIO_ID_BLOCK }, + { .str = NULL, }, +}; + +static const char *parse_class(int num) +{ + const char *class; + + class = str_map_lookup_uint(class_map, num); + return class ? class : "< unknown class >"; +} + +static void pr_out_mgmtdev_show(struct vdpa *vdpa, const struct nlmsghdr *nlh, + struct nlattr **tb) +{ + const char *class; + unsigned int i; + + pr_out_handle_start(vdpa, tb); + + if (tb[VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES]) { + uint64_t classes = mnl_attr_get_u64(tb[VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES]); + + pr_out_array_start(vdpa, "supported_classes"); + + for (i = 1; i < 64; i++) { + if ((classes & (1ULL << i)) == 0) + continue; + + class = parse_class(i); + print_string(PRINT_ANY, NULL, " %s", class); + } + pr_out_array_end(vdpa); + } + + pr_out_handle_end(vdpa); +} + +static int cmd_mgmtdev_show_cb(const struct nlmsghdr *nlh, void *data) +{ + struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); + struct nlattr *tb[VDPA_ATTR_MAX + 1] = {}; + struct vdpa *vdpa = data; + + mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); + + if (!tb[VDPA_ATTR_MGMTDEV_DEV_NAME]) + return MNL_CB_ERROR; + + pr_out_mgmtdev_show(vdpa, nlh, tb); + + return MNL_CB_OK; +} + +static int cmd_mgmtdev_show(struct vdpa *vdpa, int argc, char **argv) +{ + uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; + struct nlmsghdr *nlh; + int err; + + if (argc == 0) + flags |= NLM_F_DUMP; + + nlh = mnlu_gen_socket_cmd_prepare(&vdpa->nlg, VDPA_CMD_MGMTDEV_GET, + flags); + if (argc > 0) { + err = vdpa_argv_parse_put(nlh, vdpa, argc, argv, + VDPA_OPT_MGMTDEV_HANDLE); + if (err) + return err; + } + + pr_out_section_start(vdpa, "mgmtdev"); + err = mnlu_gen_socket_sndrcv(&vdpa->nlg, nlh, cmd_mgmtdev_show_cb, vdpa); + pr_out_section_end(vdpa); + return err; +} + +static int cmd_mgmtdev(struct vdpa *vdpa, int argc, char **argv) +{ + if (!argc || matches(*argv, "help") == 0) { + cmd_mgmtdev_help(); + return 0; + } else if (matches(*argv, "show") == 0 || + matches(*argv, "list") == 0) { + return cmd_mgmtdev_show(vdpa, argc - 1, argv + 1); + } + fprintf(stderr, "Command \"%s\" not found\n", *argv); + return -ENOENT; +} + +static void cmd_dev_help(void) +{ + fprintf(stderr, "Usage: vdpa dev show [ DEV ]\n"); + fprintf(stderr, " vdpa dev add name NAME mgmtdev MANAGEMENTDEV\n"); + fprintf(stderr, " vdpa dev del DEV\n"); +} + +static const char *device_type_name(uint32_t type) +{ + switch (type) { + case 0x1: return "network"; + case 0x2: return "block"; + default: return ""; + } +} + +static void pr_out_dev(struct vdpa *vdpa, struct nlattr **tb) +{ + const char *mdev_name = mnl_attr_get_str(tb[VDPA_ATTR_MGMTDEV_DEV_NAME]); + uint32_t device_id = mnl_attr_get_u32(tb[VDPA_ATTR_DEV_ID]); + const char *mdev_bus_name = NULL; + char mgmtdev_buf[128]; + + if (tb[VDPA_ATTR_MGMTDEV_BUS_NAME]) + mdev_bus_name = mnl_attr_get_str(tb[VDPA_ATTR_MGMTDEV_BUS_NAME]); + + if (mdev_bus_name) + sprintf(mgmtdev_buf, "%s/%s", mdev_bus_name, mdev_name); + else + sprintf(mgmtdev_buf, "%s", mdev_name); + pr_out_vdev_handle_start(vdpa, tb); + print_string(PRINT_ANY, "type", "type %s", device_type_name(device_id)); + print_string(PRINT_ANY, "mgmtdev", " mgmtdev %s", mgmtdev_buf); + + if (tb[VDPA_ATTR_DEV_VENDOR_ID]) + print_uint(PRINT_ANY, "vendor_id", " vendor_id %u", + mnl_attr_get_u32(tb[VDPA_ATTR_DEV_VENDOR_ID])); + if (tb[VDPA_ATTR_DEV_MAX_VQS]) + print_uint(PRINT_ANY, "max_vqs", " max_vqs %u", + mnl_attr_get_u32(tb[VDPA_ATTR_DEV_MAX_VQS])); + if (tb[VDPA_ATTR_DEV_MAX_VQ_SIZE]) + print_uint(PRINT_ANY, "max_vq_size", " max_vq_size %u", + mnl_attr_get_u16(tb[VDPA_ATTR_DEV_MAX_VQ_SIZE])); + pr_out_vdev_handle_end(vdpa); +} + +static int cmd_dev_show_cb(const struct nlmsghdr *nlh, void *data) +{ + struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); + struct nlattr *tb[VDPA_ATTR_MAX + 1] = {}; + struct vdpa *vdpa = data; + + mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); + if (!tb[VDPA_ATTR_MGMTDEV_DEV_NAME] || + !tb[VDPA_ATTR_DEV_NAME] || !tb[VDPA_ATTR_DEV_ID]) + return MNL_CB_ERROR; + pr_out_dev(vdpa, tb); + return MNL_CB_OK; +} + +static int cmd_dev_show(struct vdpa *vdpa, int argc, char **argv) +{ + uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; + struct nlmsghdr *nlh; + int err; + + if (argc <= 0) + flags |= NLM_F_DUMP; + + nlh = mnlu_gen_socket_cmd_prepare(&vdpa->nlg, VDPA_CMD_DEV_GET, flags); + if (argc > 0) { + err = vdpa_argv_parse_put(nlh, vdpa, argc, argv, + VDPA_OPT_VDEV_HANDLE); + if (err) + return err; + } + + pr_out_section_start(vdpa, "dev"); + err = mnlu_gen_socket_sndrcv(&vdpa->nlg, nlh, cmd_dev_show_cb, vdpa); + pr_out_section_end(vdpa); + return err; +} + +static int cmd_dev_add(struct vdpa *vdpa, int argc, char **argv) +{ + struct nlmsghdr *nlh; + int err; + + nlh = mnlu_gen_socket_cmd_prepare(&vdpa->nlg, VDPA_CMD_DEV_NEW, + NLM_F_REQUEST | NLM_F_ACK); + err = vdpa_argv_parse_put(nlh, vdpa, argc, argv, + VDPA_OPT_VDEV_MGMTDEV_HANDLE | VDPA_OPT_VDEV_NAME); + if (err) + return err; + + return mnlu_gen_socket_sndrcv(&vdpa->nlg, nlh, NULL, NULL); +} + +static int cmd_dev_del(struct vdpa *vdpa, int argc, char **argv) +{ + struct nlmsghdr *nlh; + int err; + + nlh = mnlu_gen_socket_cmd_prepare(&vdpa->nlg, VDPA_CMD_DEV_DEL, + NLM_F_REQUEST | NLM_F_ACK); + err = vdpa_argv_parse_put(nlh, vdpa, argc, argv, VDPA_OPT_VDEV_HANDLE); + if (err) + return err; + + return mnlu_gen_socket_sndrcv(&vdpa->nlg, nlh, NULL, NULL); +} + +static int cmd_dev(struct vdpa *vdpa, int argc, char **argv) +{ + if (!argc) + return cmd_dev_show(vdpa, argc - 1, argv + 1); + + if (matches(*argv, "help") == 0) { + cmd_dev_help(); + return 0; + } else if (matches(*argv, "show") == 0 || + matches(*argv, "list") == 0) { + return cmd_dev_show(vdpa, argc - 1, argv + 1); + } else if (matches(*argv, "add") == 0) { + return cmd_dev_add(vdpa, argc - 1, argv + 1); + } else if (matches(*argv, "del") == 0) { + return cmd_dev_del(vdpa, argc - 1, argv + 1); + } + fprintf(stderr, "Command \"%s\" not found\n", *argv); + return -ENOENT; +} + +static void help(void) +{ + fprintf(stderr, + "Usage: vdpa [ OPTIONS ] OBJECT { COMMAND | help }\n" + "where OBJECT := { mgmtdev | dev }\n" + " OPTIONS := { -V[ersion] | -n[o-nice-names] | -j[son] | -p[retty] | -v[erbose] }\n"); +} + +static int vdpa_cmd(struct vdpa *vdpa, int argc, char **argv) +{ + if (!argc || matches(*argv, "help") == 0) { + help(); + return 0; + } else if (matches(*argv, "mgmtdev") == 0) { + return cmd_mgmtdev(vdpa, argc - 1, argv + 1); + } else if (matches(*argv, "dev") == 0) { + return cmd_dev(vdpa, argc - 1, argv + 1); + } + fprintf(stderr, "Object \"%s\" not found\n", *argv); + return -ENOENT; +} + +static int vdpa_init(struct vdpa *vdpa) +{ + int err; + + err = mnlu_gen_socket_open(&vdpa->nlg, VDPA_GENL_NAME, + VDPA_GENL_VERSION); + if (err) { + fprintf(stderr, "Failed to connect to vdpa Netlink\n"); + return -errno; + } + new_json_obj_plain(vdpa->json_output); + return 0; +} + +static void vdpa_fini(struct vdpa *vdpa) +{ + delete_json_obj_plain(); + mnlu_gen_socket_close(&vdpa->nlg); +} + +static struct vdpa *vdpa_alloc(void) +{ + struct vdpa *vdpa = calloc(1, sizeof(struct vdpa)); + + if (!vdpa) + return NULL; + + vdpa->indent = alloc_indent_mem(); + if (!vdpa->indent) + goto indent_err; + + return vdpa; + +indent_err: + free(vdpa); + return NULL; +} + +static void vdpa_free(struct vdpa *vdpa) +{ + free_indent_mem(vdpa->indent); + free(vdpa); +} + +int main(int argc, char **argv) +{ + static const struct option long_options[] = { + { "Version", no_argument, NULL, 'V' }, + { "json", no_argument, NULL, 'j' }, + { "pretty", no_argument, NULL, 'p' }, + { "help", no_argument, NULL, 'h' }, + { NULL, 0, NULL, 0 } + }; + struct vdpa *vdpa; + int opt; + int err; + int ret; + + vdpa = vdpa_alloc(); + if (!vdpa) { + fprintf(stderr, "Failed to allocate memory for vdpa\n"); + return EXIT_FAILURE; + } + + while ((opt = getopt_long(argc, argv, "Vjpsh", long_options, NULL)) >= 0) { + switch (opt) { + case 'V': + printf("vdpa utility, iproute2-%s\n", version); + ret = EXIT_SUCCESS; + goto vdpa_free; + case 'j': + vdpa->json_output = true; + break; + case 'p': + pretty = true; + break; + case 'h': + help(); + ret = EXIT_SUCCESS; + goto vdpa_free; + default: + fprintf(stderr, "Unknown option.\n"); + help(); + ret = EXIT_FAILURE; + goto vdpa_free; + } + } + + argc -= optind; + argv += optind; + + err = vdpa_init(vdpa); + if (err) { + ret = EXIT_FAILURE; + goto vdpa_free; + } + + err = vdpa_cmd(vdpa, argc, argv); + if (err) { + ret = EXIT_FAILURE; + goto vdpa_fini; + } + + ret = EXIT_SUCCESS; + +vdpa_fini: + vdpa_fini(vdpa); +vdpa_free: + vdpa_free(vdpa); + return ret; +}