X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvlib%2Flinux%2Fvmbus.c;h=b0663819a45d279efa99c0667526d9d1ecc065bd;hb=87a8826d173c4e4ff3da3a613f19eb9a91673a75;hp=2dba80253267e1356547d07f17bff64b6540f490;hpb=f6266b56ecd6bca3074886b37d48cf5c20f37fa3;p=vpp.git diff --git a/src/vlib/linux/vmbus.c b/src/vlib/linux/vmbus.c index 2dba8025326..b0663819a45 100644 --- a/src/vlib/linux/vmbus.c +++ b/src/vlib/linux/vmbus.c @@ -31,8 +31,6 @@ #include #include -#include - static const char sysfs_vmbus_dev_path[] = "/sys/bus/vmbus/devices"; static const char sysfs_vmbus_drv_path[] = "/sys/bus/vmbus/drivers"; static const char sysfs_class_net_path[] = "/sys/class/net"; @@ -118,33 +116,70 @@ linux_vmbus_main_t linux_vmbus_main; * "f2c086b2-ff2e-11e8-88de-7bad0a57de05" and convert * it to u8[16] */ -static uword -unformat_vlib_vmbus_addr (unformat_input_t * input, va_list * args) +uword +unformat_vlib_vmbus_addr (unformat_input_t *input, va_list *args) { vlib_vmbus_addr_t *addr = va_arg (*args, vlib_vmbus_addr_t *); uword ret = 0; - u8 *s; + u8 *s = 0; - if (!unformat (input, "%s", &s)) + if (!unformat (input, "%U", unformat_token, "a-zA-Z0-9-", &s)) return 0; - if (uuid_parse ((char *) s, addr->guid) == 0) - ret = 1; + if (vec_len (s) != 36) + goto fail; - vec_free (s); + if (s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-') + goto fail; + + clib_memmove (s + 8, s + 9, 4); + clib_memmove (s + 12, s + 14, 4); + clib_memmove (s + 16, s + 19, 4); + clib_memmove (s + 20, s + 24, 12); + + for (int i = 0; i < 32; i++) + if (s[i] >= '0' && s[i] <= '9') + s[i] -= '0'; + else if (s[i] >= 'A' && s[i] <= 'F') + s[i] -= 'A' - 10; + else if (s[i] >= 'a' && s[i] <= 'f') + s[i] -= 'a' - 10; + else + goto fail; + for (int i = 0; i < 16; i++) + addr->guid[i] = s[2 * i] * 16 + s[2 * i + 1]; + + ret = 1; + +fail: + vec_free (s); return ret; } /* Convert bus address to standard UUID string */ -static u8 * -format_vlib_vmbus_addr (u8 * s, va_list * va) +u8 * +format_vlib_vmbus_addr (u8 *s, va_list *va) { vlib_vmbus_addr_t *addr = va_arg (*va, vlib_vmbus_addr_t *); - char tmp[40]; - - uuid_unparse (addr->guid, tmp); - return format (s, "%s", tmp); + u8 *bytes = addr->guid; + + for (int i = 0; i < 4; i++) + s = format (s, "%02X", bytes++[0]); + vec_add1 (s, '-'); + for (int i = 0; i < 2; i++) + s = format (s, "%02X", bytes++[0]); + vec_add1 (s, '-'); + for (int i = 0; i < 2; i++) + s = format (s, "%02X", bytes++[0]); + vec_add1 (s, '-'); + for (int i = 0; i < 2; i++) + s = format (s, "%02X", bytes++[0]); + vec_add1 (s, '-'); + for (int i = 0; i < 6; i++) + s = format (s, "%02X", bytes++[0]); + + return s; } /* workaround for mlx bug, bring lower device up before unbind */ @@ -199,6 +234,16 @@ done: return error; } +static int +directory_exists (char *path) +{ + struct stat s = { 0 }; + if (stat (path, &s) == -1) + return 0; + + return S_ISDIR (s.st_mode); +} + clib_error_t * vlib_vmbus_bind_to_uio (vlib_vmbus_addr_t * addr) { @@ -208,21 +253,23 @@ vlib_vmbus_bind_to_uio (vlib_vmbus_addr_t * addr) static int uio_new_id_needed = 1; struct dirent *e; struct ifreq ifr; - u8 *s, *driver_name; + u8 *s = 0, *driver_name; DIR *dir; int fd; dev_dir_name = format (0, "%s/%U", sysfs_vmbus_dev_path, format_vlib_vmbus_addr, addr); - s = format (0, "%v/driver%c", dev_dir_name, 0); - driver_name = clib_sysfs_link_to_name ((char *) s); - vec_reset_length (s); + driver_name = clib_file_get_resolved_basename ("%v/driver", dev_dir_name); /* skip if not using the Linux kernel netvsc driver */ if (!driver_name || strcmp ("hv_netvsc", (char *) driver_name) != 0) goto done; + /* if uio_hv_generic is not loaded, then can't use native DPDK driver. */ + if (!directory_exists ("/sys/module/uio_hv_generic")) + goto done; + s = format (s, "%v/net%c", dev_dir_name, 0); dir = opendir ((char *) s); vec_reset_length (s); @@ -270,34 +317,42 @@ vlib_vmbus_bind_to_uio (vlib_vmbus_addr_t * addr) if (ifr.ifr_flags & IFF_UP) { - error = clib_error_return (0, - "Skipping VMBUS device %U as host interface %s is up", - format_vlib_vmbus_addr, addr, e->d_name); + error = clib_error_return ( + 0, "Skipping VMBUS device %U as host interface %s is up", + format_vlib_vmbus_addr, addr, ifname); close (fd); goto done; } - error = vlib_vmbus_raise_lower (fd, ifname); - close (fd); - - if (error) - goto done; - - /* tell uio_hv_generic about netvsc device type */ if (uio_new_id_needed) { vec_reset_length (s); s = format (s, "%s/%s/new_id%c", sysfs_vmbus_drv_path, uio_drv_name, 0); error = clib_sysfs_write ((char *) s, "%s", netvsc_uuid); - + /* If device already exists, we can bind/unbind/override driver */ if (error) - goto done; + { + if (error->code == EEXIST) + { + clib_error_free (error); + } + else + { + close (fd); + goto done; + } + } uio_new_id_needed = 0; - } + error = vlib_vmbus_raise_lower (fd, ifname); + close (fd); + + if (error) + goto done; + /* prefer the simplier driver_override model */ vec_reset_length (s); s = format (s, "%/driver_override%c", dev_dir_name, 0); @@ -361,7 +416,13 @@ vmbus_addr_cmp (void *v1, void *v2) vlib_vmbus_addr_t *a1 = v1; vlib_vmbus_addr_t *a2 = v2; - return uuid_compare (a1->guid, a2->guid); + for (int i = 0; i < ARRAY_LEN (a1->guid); i++) + if (a1->guid[i] > a2->guid[i]) + return 1; + else if (a1->guid[i] < a2->guid[i]) + return -1; + + return 0; } vlib_vmbus_addr_t * @@ -391,10 +452,15 @@ linux_vmbus_init (vlib_main_t * vm) pm->vlib_main = vm; - return vlib_call_init_function (vm, unix_input_init); + return 0; } -VLIB_INIT_FUNCTION (linux_vmbus_init); +/* *INDENT-OFF* */ +VLIB_INIT_FUNCTION (linux_vmbus_init) = +{ + .runs_before = VLIB_INITS("unix_input_init"), +}; +/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON