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 7B055A00C4; Tue, 26 Apr 2022 10:33:19 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 32C3442810; Tue, 26 Apr 2022 10:32:43 +0200 (CEST) Received: from mail-pf1-f194.google.com (mail-pf1-f194.google.com [209.85.210.194]) by mails.dpdk.org (Postfix) with ESMTP id 8688540042 for ; Sat, 23 Apr 2022 06:29:59 +0200 (CEST) Received: by mail-pf1-f194.google.com with SMTP id y14so9029286pfe.10 for ; Fri, 22 Apr 2022 21:29:59 -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=MXm7xPl3w9O8OAflDZPQpi169kzfUg0coum28GXJksM=; b=HDfZVkM5j+73YJgdj3Wv70hbRXoTV8uTcMNEkXnlwah9w9ZDucmyBlH8+0yQz+C6m5 7UB+tt5i9G0vxGY+2sKsLOiT1DgMK/NugPrvViDZBxZBde2O/C9qxacbVMENyr+nx79p PkKPUPHjSEIKggLu0odw1snC1TtJ7xc9apyv0= 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=MXm7xPl3w9O8OAflDZPQpi169kzfUg0coum28GXJksM=; b=y5HFkPhk80w0PDOxKs6jnDERZK2cr5itnB1GxnCNCn5ex6Ag+uVP7NZe5dTkVx/Uae Qv5Pb8fSn07S9ZKioErgJ19YYCu18MkzFw3HOZbrgFNeMSsKBILbJE9curVwjEPF+/XX MMgKJUBEO9xout9X9YGn/rNznsDm46Q7+fRpLQ1bsnHWf03MJTfw1T01Ja4wJWktRuCt J1cfwQNySHN1JvHL0nEJ77W0HZS+YOFhC2W2pI3dVceqBCfx0ozVBdWhGfDtYdUVt+Lw 7AoJEMgR9XEBf7awZURaQz1+6UIVlH/fFmO4rRq/uxzVIR/uOCmzxxbYLyBE7iHfrPBp kr9w== X-Gm-Message-State: AOAM531HI8BDMPBYJkpcLWoIgj1cIGRF6uK9T77O7GOxow77o/3x98h1 8cV0Alo2MAFcq6pUYEWx/xK3ZQ== X-Google-Smtp-Source: ABdhPJyQdTmnB60bvN+EIYPXAD8sSZVqypGHBq59JP+g9ykWwRwXwzowZuSzDwquaXYhs0wuKV7Ocw== X-Received: by 2002:a63:6687:0:b0:3aa:193b:7a70 with SMTP id a129-20020a636687000000b003aa193b7a70mr6675724pgc.493.1650688198710; Fri, 22 Apr 2022 21:29:58 -0700 (PDT) Received: from home-desktop.localdomain ([49.37.158.191]) by smtp.gmail.com with ESMTPSA id g6-20020a17090a714600b001d7f3bb11d7sm4056438pjs.53.2022.04.22.21.29.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 22 Apr 2022 21:29:58 -0700 (PDT) From: Srikanth Kaka To: Stephen Hemminger , Long Li Cc: dev@dpdk.org, Vag Singh , Anand Thulasiram , Srikanth Kaka Subject: [PATCH v5 04/14] bus/vmbus: scan and get the network device on FreeBSD Date: Sat, 23 Apr 2022 09:58:39 +0530 Message-Id: <20220423042849.7718-5-srikanth.k@oneconvergence.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220423042849.7718-1-srikanth.k@oneconvergence.com> References: <20220418042915.5765-1-srikanth.k@oneconvergence.com> <20220423042849.7718-1-srikanth.k@oneconvergence.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Mailman-Approved-At: Tue, 26 Apr 2022 10:32:34 +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 0000000..c1a3a5f --- /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_unix.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 sysctl_buf[PATH_MAX], sysctl_var[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(sysctl_var, len, "dev.%s.%u.%%pnpinfo", name, unit_num); + if (sysctlbyname(sysctl_var, &sysctl_buf, &len, NULL, 0) < 0) + goto error; + + /* pnpinfo: classid=f912ad6d-2b17-48ea-bd65-f927a61c7684 + * deviceid=d34b2567-b9b6-42b9-8778-0a4ec0b955bf + */ + if (sysctl_buf[0] == 'c' && sysctl_buf[1] == 'l' && + sysctl_buf[7] == '=') { + memcpy(classid, &sysctl_buf[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 (sysctl_buf[45] == 'd' && sysctl_buf[46] == 'e' && + sysctl_buf[47] == 'v' && sysctl_buf[53] == '=') { + memcpy(deviceid, &sysctl_buf[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; +} -- 1.8.3.1