From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id B6155A00BE; Tue, 19 Apr 2022 11:34:11 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 24F83427FF; Tue, 19 Apr 2022 11:33:43 +0200 (CEST) Received: from mail-pg1-f193.google.com (mail-pg1-f193.google.com [209.85.215.193]) by mails.dpdk.org (Postfix) with ESMTP id 8E9C240141 for ; Mon, 18 Apr 2022 06:29:43 +0200 (CEST) Received: by mail-pg1-f193.google.com with SMTP id q12so16713233pgj.13 for ; Sun, 17 Apr 2022 21:29:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oneconvergence.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=xS6VZIa3z4/BbPEz3tVcaGwmkSoCiE6gUuwWRZ0icOI=; b=WyNkQz+/AvJRg5jJ9x1wBgX0o+nWlo3FLByAp0YFkLXc4zSgbSChyMNcLSc7hhN8UM F6vRwKHd97CQ81d8r8YI35qxbtqn6bBJsdbLXNlUwn2EgjW4owTIJaJbHSrxJxNg1i5q /uUU1f+YSav42Q1q46YcxxPaOL9J4RZaA41jc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=xS6VZIa3z4/BbPEz3tVcaGwmkSoCiE6gUuwWRZ0icOI=; b=tj3lgVykPP/5vMnEEj0XjeyCcQHMjbANdveZYQgmDXvcDk/C1AkOL6eDY7Jr9ZqTt0 a1hsVuus16VURAeZox7oPD/ZRuOszqnfX2e640DeRnvqkbfrTnFUV4Lc+A103KPp3nmZ W0EPWyQiHjA7UdC4rhy3r2Y4DFN+FdmSep7iiSlU0vPvur7RwDdiUhvY66Ermo4164w+ ibqQqqDWktL3YxNozvMgYTemPFdjCsrRk/MZxUQImZmEJL0C3+w6VFxzUAh1KhFMXORT HOAXnCmMhhr9vL8mE+/4V/FxHlvBgjiSHJy3qVYKwnG3m2KIzf0LS2EmIPP7y2rDx7ig WoFg== X-Gm-Message-State: AOAM5311JrBcb2ZoWeTgLIqI4EMXbZn9r0XHxnkJNWPfKBK1jhwIcwQh E6uqAPVVyZpJh5KRWozt97ByXA== X-Google-Smtp-Source: ABdhPJyKq+SlP+0Zi/JL8mp7jwlIt+KA3VkTcOqlR20tEEgeKM1ZmB7eBrMniul4V/Wd3OciR/CGYA== X-Received: by 2002:a63:492:0:b0:39d:adac:638b with SMTP id 140-20020a630492000000b0039dadac638bmr8423010pge.314.1650256182750; Sun, 17 Apr 2022 21:29:42 -0700 (PDT) Received: from srikanth-ThinkPad-T450.. ([49.37.158.191]) by smtp.gmail.com with ESMTPSA id e14-20020aa78c4e000000b00506475da4cesm10377577pfd.49.2022.04.17.21.29.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 17 Apr 2022 21:29:41 -0700 (PDT) From: Srikanth Kaka To: Stephen Hemminger , Long Li Cc: dev@dpdk.org, Vag Singh , Anand Thulasiram , Srikanth Kaka Subject: [PATCH v4 04/14] bus/vmbus: scan and get the network device on FreeBSD Date: Mon, 18 Apr 2022 09:59:05 +0530 Message-Id: <20220418042915.5765-5-srikanth.k@oneconvergence.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220418042915.5765-1-srikanth.k@oneconvergence.com> References: <20220217160613.70161-16-srikanth.k@oneconvergence.com> <20220418042915.5765-1-srikanth.k@oneconvergence.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Mailman-Approved-At: Tue, 19 Apr 2022 11:33:36 +0200 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Using sysctl, all the devices on the VMBUS are identified by the PMD. On finding the Network device's device id, it is added to VMBUS dev list. Signed-off-by: Srikanth Kaka Signed-off-by: Vag Singh Signed-off-by: Anand Thulasiram --- drivers/bus/vmbus/freebsd/vmbus_bus.c | 268 ++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 drivers/bus/vmbus/freebsd/vmbus_bus.c diff --git a/drivers/bus/vmbus/freebsd/vmbus_bus.c b/drivers/bus/vmbus/freebsd/vmbus_bus.c new file mode 100644 index 0000000000..8cf3bc5a6a --- /dev/null +++ b/drivers/bus/vmbus/freebsd/vmbus_bus.c @@ -0,0 +1,268 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2018, Microsoft Corporation. + * All Rights Reserved. + */ + +#include +#include + +#include "private.h" +#include "vmbus_osi.h" + +#include +#include +#include + +/* Parse UUID. Caller must pass NULL terminated string */ +static int +parse_sysfs_uuid(const char *filename, rte_uuid_t uu) +{ + char in[BUFSIZ]; + + memcpy(in, filename, BUFSIZ); + if (rte_uuid_parse(in, uu) < 0) { + VMBUS_LOG(ERR, "%s not a valid UUID", in); + return -1; + } + + return 0; +} + +/* Scan one vmbus entry, and fill the devices list from it. */ +static int +vmbus_scan_one(const char *name, unsigned int unit_num) +{ + struct rte_vmbus_device *dev, *dev2; + char sysctlBuffer[PATH_MAX], sysctlVar[PATH_MAX]; + size_t guid_len = 36, len = PATH_MAX; + char classid[guid_len + 1], deviceid[guid_len + 1]; + + dev = calloc(1, sizeof(*dev)); + if (dev == NULL) + return -1; + + /* get class id and device id */ + snprintf(sysctlVar, len, "dev.%s.%u.%%pnpinfo", name, unit_num); + if (sysctlbyname(sysctlVar, &sysctlBuffer, &len, NULL, 0) < 0) + goto error; + + /* pnpinfo: classid=f912ad6d-2b17-48ea-bd65-f927a61c7684 + * deviceid=d34b2567-b9b6-42b9-8778-0a4ec0b955bf + */ + if (sysctlBuffer[0] == 'c' && sysctlBuffer[1] == 'l' && + sysctlBuffer[7] == '=') { + memcpy(classid, &sysctlBuffer[8], guid_len); + classid[guid_len] = '\0'; + } + if (parse_sysfs_uuid(classid, dev->class_id) < 0) + goto error; + + /* skip non-network devices */ + if (rte_uuid_compare(dev->class_id, vmbus_nic_uuid) != 0) { + free(dev); + return 0; + } + + if (sysctlBuffer[45] == 'd' && sysctlBuffer[46] == 'e' && + sysctlBuffer[47] == 'v' && sysctlBuffer[53] == '=') { + memcpy(deviceid, &sysctlBuffer[54], guid_len); + deviceid[guid_len] = '\0'; + } + if (parse_sysfs_uuid(deviceid, dev->device_id) < 0) + goto error; + + if (!strcmp(name, "hv_uio")) + dev->uio_num = unit_num; + else + dev->uio_num = -1; + dev->device.bus = &rte_vmbus_bus.bus; + dev->device.numa_node = 0; + dev->device.name = strdup(deviceid); + if (!dev->device.name) + goto error; + + dev->device.devargs = vmbus_devargs_lookup(dev); + + dev->intr_handle = rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE); + if (dev->intr_handle == NULL) + goto error; + + /* device is valid, add in list (sorted) */ + VMBUS_LOG(DEBUG, "Adding vmbus device %s", name); + + TAILQ_FOREACH(dev2, &rte_vmbus_bus.device_list, next) { + int ret; + + ret = rte_uuid_compare(dev->device_id, dev2->device_id); + if (ret > 0) + continue; + + if (ret < 0) { + vmbus_insert_device(dev2, dev); + } else { /* already registered */ + VMBUS_LOG(NOTICE, + "%s already registered", name); + free(dev); + } + return 0; + } + + vmbus_add_device(dev); + return 0; +error: + VMBUS_LOG(DEBUG, "failed"); + + free(dev); + return -1; +} + +static int +vmbus_unpack(char *walker, char *ep, char **str) +{ + int ret = 0; + + *str = strdup(walker); + if (*str == NULL) { + ret = -ENOMEM; + goto exit; + } + + if (walker + strnlen(walker, ep - walker) >= ep) { + ret = -EINVAL; + goto exit; + } +exit: + return ret; +} + +/* + * Scan the content of the vmbus, and the devices in the devices list + */ +int +rte_vmbus_scan(void) +{ + struct u_device udev; + struct u_businfo ubus; + int dev_idx, dev_ptr, name2oid[2], oid[CTL_MAXNAME + 12], error; + size_t oidlen, rlen, ub_size; + uintptr_t vmbus_handle = 0; + char *walker, *ep; + char name[16] = "hw.bus.devices"; + char *dd_name, *dd_desc, *dd_drivername, *dd_pnpinfo, *dd_location; + + /* + * devinfo FreeBSD APP logic to fetch all the VMBus devices + * using SYSCTLs + */ + name2oid[0] = 0; + name2oid[1] = 3; + oidlen = sizeof(oid); + error = sysctl(name2oid, 2, oid, &oidlen, name, strlen(name)); + if (error < 0) { + VMBUS_LOG(DEBUG, "can't find hw.bus.devices sysctl node"); + return -ENOENT; + } + oidlen /= sizeof(int); + if (oidlen > CTL_MAXNAME) { + VMBUS_LOG(DEBUG, "hw.bus.devices oid is too large"); + return -EINVAL; + } + + ub_size = sizeof(ubus); + if (sysctlbyname("hw.bus.info", &ubus, &ub_size, NULL, 0) != 0) { + VMBUS_LOG(DEBUG, "sysctlbyname(\"hw.bus.info\", ...) failed"); + return -EINVAL; + } + if ((ub_size != sizeof(ubus)) || + (ubus.ub_version != BUS_USER_VERSION)) { + VMBUS_LOG(DEBUG, + "kernel bus interface version mismatch: kernel %d expected %d", + ubus.ub_version, BUS_USER_VERSION); + return -EINVAL; + } + + oid[oidlen++] = ubus.ub_generation; + dev_ptr = oidlen++; + + /* + * Scan devices. + * + * Stop after a fairly insane number to avoid death in the case + * of kernel corruption. + */ + + for (dev_idx = 0; dev_idx < 10000; dev_idx++) { + /* + * Get the device information. + */ + oid[dev_ptr] = dev_idx; + rlen = sizeof(udev); + error = sysctl(oid, oidlen, &udev, &rlen, NULL, 0); + if (error < 0) { + if (errno == ENOENT) /* end of list */ + break; + if (errno != EINVAL) /* gen count skip, restart */ + VMBUS_LOG(DEBUG, "sysctl hw.bus.devices.%d", + dev_idx); + return errno; + } + if (rlen != sizeof(udev)) { + VMBUS_LOG(DEBUG, + "sysctl returned wrong data %zd bytes instead of %zd", + rlen, sizeof(udev)); + return -EINVAL; + } + + walker = udev.dv_fields; + ep = walker + sizeof(udev.dv_fields); + dd_name = NULL; + dd_desc = NULL; + dd_drivername = NULL; + dd_pnpinfo = NULL; + dd_location = NULL; + + error = vmbus_unpack(walker, ep, &dd_name); + if (error < 0) + return error; + walker += strlen(walker) + 1; + + error = vmbus_unpack(walker, ep, &dd_desc); + if (error < 0) + return error; + walker += strlen(walker) + 1; + + error = vmbus_unpack(walker, ep, &dd_drivername); + if (error < 0) + return error; + walker += strlen(walker) + 1; + + error = vmbus_unpack(walker, ep, &dd_pnpinfo); + if (error < 0) + return error; + walker += strlen(walker) + 1; + + error = vmbus_unpack(walker, ep, &dd_location); + if (error < 0) + return error; + + if (*dd_drivername && !(strcmp(dd_drivername, "vmbus"))) + vmbus_handle = udev.dv_handle; + + if (vmbus_handle && (vmbus_handle == udev.dv_parent) + && *dd_pnpinfo && *dd_name) { + unsigned int driver_len = 0, unit_num = 0; + char *endptr; + + driver_len = strlen(dd_drivername); + unit_num = strtoull(&dd_name[driver_len], &endptr, 10); + VMBUS_LOG(DEBUG, "Device name:%s, pnpinfo:%s", + dd_name, dd_pnpinfo); + + if (vmbus_scan_one(dd_drivername, unit_num) < 0) + goto error; + } + } + return 0; +error: + return -1; +} -- 2.30.2