dpdk: allow configure individual VMBUS devices

now startup.conf supports confuguration for VMBUS
devices as for PCI devices for whitelisting/blacklisting

dpdk { dev fa5a6e7a-cf3a-4b98-9569-addb479b84bc }
 with sub-configuration as for PCI devices
dpdk { blacklist fa5a6e7a-cf3a-4b98-9569-addb479b84bc }
 where fa5a6e7a-cf3a-4b98-9569-addb479b84bc - example of UUID

struct vlib_vmbus_addr_t changed to union with UUID described
 fields

Added device_config_index_by_vmbus_addr
      blacklist_by_vmbus_addr
to enumerate available device configs

hash_key is as_u32[0] field(last 4 bytes of UUID)
Lost of precision against full UUID, but 2^32 is enough
to handle all the devices available

Added is_blacklisted check while creating vnet devices in
order to supress creation of dev if it's blacklisted

Type: feature

Signed-off-by: Vladimir Ratnikov <vratnikov@netgate.com>
Change-Id: Id82611e54fed082190e488c7e5fbe14ecbe5b2ab
diff --git a/src/vlib/linux/vmbus.c b/src/vlib/linux/vmbus.c
index 2fc438b..d50b539 100644
--- a/src/vlib/linux/vmbus.c
+++ b/src/vlib/linux/vmbus.c
@@ -118,8 +118,8 @@
  * "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;
@@ -137,8 +137,8 @@
 }
 
 /* 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];
@@ -297,15 +297,21 @@
       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)
 	{
-	  close (fd);
-	  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);
diff --git a/src/vlib/vmbus/vmbus.c b/src/vlib/vmbus/vmbus.c
index eadf5f1..045e2dd 100644
--- a/src/vlib/vmbus/vmbus.c
+++ b/src/vlib/vmbus/vmbus.c
@@ -25,11 +25,24 @@
 #include <net/if.h>
 
 /* this is a stub replaced by the Linux specfic version */
-vlib_vmbus_addr_t * __attribute__ ((weak)) vlib_vmbus_get_all_dev_addrs ()
+vlib_vmbus_addr_t *__clib_weak
+vlib_vmbus_get_all_dev_addrs ()
 {
   return NULL;
 }
 
+u8 *__clib_weak
+format_vlib_vmbus_addr (u8 *s, va_list *va)
+{
+  return 0;
+}
+
+uword __clib_weak
+unformat_vlib_vmbus_addr (unformat_input_t *input, va_list *args)
+{
+  return 0;
+}
+
 clib_error_t *
 vmbus_bus_init (vlib_main_t * vm)
 {
diff --git a/src/vlib/vmbus/vmbus.h b/src/vlib/vmbus/vmbus.h
index 0927b89..7df62ab 100644
--- a/src/vlib/vmbus/vmbus.h
+++ b/src/vlib/vmbus/vmbus.h
@@ -21,10 +21,12 @@
 
 #include <vlib/vlib.h>
 
-typedef struct
+typedef union
 {
   u8 guid[16];
+  u32 as_u32[4];
 } vlib_vmbus_addr_t;
+
 typedef u32 vlib_vmbus_dev_handle_t;
 
 vlib_vmbus_addr_t *vlib_vmbus_get_all_dev_addrs ();
@@ -33,6 +35,8 @@
 void vlib_vmbus_set_private_data (vlib_vmbus_dev_handle_t h,
 				  uword private_data);
 
+format_function_t format_vlib_vmbus_addr;
+unformat_function_t unformat_vlib_vmbus_addr;
 clib_error_t *vlib_vmbus_bind_to_uio (vlib_vmbus_addr_t * addr);
 #endif /* included_vlib_vmbus_h */