MTU: Software interface / Per-protocol MTU support
[vpp.git] / src / vnet / devices / virtio / vhost-user.c
index 874a97d..9244776 100644 (file)
  */
 #define VHOST_USER_TX_COPY_THRESHOLD (VHOST_USER_COPY_ARRAY_N - 40)
 
-#define UNIX_GET_FD(unixfd_idx) \
-    (unixfd_idx != ~0) ? \
+#define UNIX_GET_FD(unixfd_idx) ({ \
+    typeof(unixfd_idx) __unixfd_idx = (unixfd_idx); \
+    (__unixfd_idx != ~0) ? \
        pool_elt_at_index (file_main.file_pool, \
-                          unixfd_idx)->file_descriptor : -1;
+                          __unixfd_idx)->file_descriptor : -1; })
 
 #define foreach_virtio_trace_flags \
   _ (SIMPLE_CHAINED, 0, "Simple descriptor chaining") \
@@ -247,8 +248,8 @@ map_guest_mem (vhost_user_intf_t * vui, uword addr, u32 * hint)
   r = _mm_blend_epi16 (r, _mm_and_si128 (rl, rh), 0x88);
 
   r = _mm_shuffle_epi8 (r, _mm_set_epi64x (0, 0x0e060c040a020800));
-  i = __builtin_ctzll (_mm_movemask_epi8 (r) |
-                      (1 << VHOST_MEMORY_MAX_NREGIONS));
+  i = count_trailing_zeros (_mm_movemask_epi8 (r) |
+                           (1 << VHOST_MEMORY_MAX_NREGIONS));
 
   if (i < vui->nregions)
     {
@@ -256,7 +257,76 @@ map_guest_mem (vhost_user_intf_t * vui, uword addr, u32 * hint)
       return (void *) (vui->region_mmap_addr[i] + addr -
                       vui->regions[i].guest_phys_addr);
     }
+#elif __aarch64__ && __ARM_NEON
+  uint64x2_t al, ah, rl, rh, r;
+  uint32_t u32 = 0;
 
+  al = vdupq_n_u64 (addr + 1);
+  ah = vdupq_n_u64 (addr);
+
+  /*First Iteration */
+  rl = vld1q_u64 (&vui->region_guest_addr_lo[0]);
+  rl = vcgtq_u64 (al, rl);
+  rh = vld1q_u64 (&vui->region_guest_addr_hi[0]);
+  rh = vcgtq_u64 (rh, ah);
+  r = vandq_u64 (rl, rh);
+  u32 |= (vgetq_lane_u8 (vreinterpretq_u8_u64 (r), 0) & 0x1);
+  u32 |= ((vgetq_lane_u8 (vreinterpretq_u8_u64 (r), 8) & 0x1) << 1);
+
+  if (u32)
+    {
+      i = count_trailing_zeros (u32);
+      goto vhost_map_guest_mem_done;
+    }
+
+  /*Second Iteration */
+  rl = vld1q_u64 (&vui->region_guest_addr_lo[2]);
+  rl = vcgtq_u64 (al, rl);
+  rh = vld1q_u64 (&vui->region_guest_addr_hi[2]);
+  rh = vcgtq_u64 (rh, ah);
+  r = vandq_u64 (rl, rh);
+  u32 |= ((vgetq_lane_u8 (vreinterpretq_u8_u64 (r), 0) & 0x1) << 2);
+  u32 |= ((vgetq_lane_u8 (vreinterpretq_u8_u64 (r), 8) & 0x1) << 3);
+
+  if (u32)
+    {
+      i = count_trailing_zeros (u32);
+      goto vhost_map_guest_mem_done;
+    }
+
+  /*Third Iteration */
+  rl = vld1q_u64 (&vui->region_guest_addr_lo[4]);
+  rl = vcgtq_u64 (al, rl);
+  rh = vld1q_u64 (&vui->region_guest_addr_hi[4]);
+  rh = vcgtq_u64 (rh, ah);
+  r = vandq_u64 (rl, rh);
+  u32 |= ((vgetq_lane_u8 (vreinterpretq_u8_u64 (r), 0) & 0x1) << 4);
+  u32 |= ((vgetq_lane_u8 (vreinterpretq_u8_u64 (r), 8) & 0x1) << 5);
+
+  if (u32)
+    {
+      i = count_trailing_zeros (u32);
+      goto vhost_map_guest_mem_done;
+    }
+
+  /*Fourth Iteration */
+  rl = vld1q_u64 (&vui->region_guest_addr_lo[6]);
+  rl = vcgtq_u64 (al, rl);
+  rh = vld1q_u64 (&vui->region_guest_addr_hi[6]);
+  rh = vcgtq_u64 (rh, ah);
+  r = vandq_u64 (rl, rh);
+  u32 |= ((vgetq_lane_u8 (vreinterpretq_u8_u64 (r), 0) & 0x1) << 6);
+  u32 |= ((vgetq_lane_u8 (vreinterpretq_u8_u64 (r), 8) & 0x1) << 7);
+
+  i = count_trailing_zeros (u32 | (1 << VHOST_MEMORY_MAX_NREGIONS));
+
+vhost_map_guest_mem_done:
+  if (i < vui->nregions)
+    {
+      *hint = i;
+      return (void *) (vui->region_mmap_addr[i] + addr -
+                      vui->regions[i].guest_phys_addr);
+    }
 #else
   for (i = 0; i < vui->nregions; i++)
     {
@@ -306,7 +376,7 @@ unmap_all_mem_regions (vhost_user_intf_t * vui)
   int i, r;
   for (i = 0; i < vui->nregions; i++)
     {
-      if (vui->region_mmap_addr[i] != (void *) -1)
+      if (vui->region_mmap_addr[i] != MAP_FAILED)
        {
 
          long page_sz = get_huge_page_size (vui->region_mmap_fd[i]);
@@ -323,7 +393,7 @@ unmap_all_mem_regions (vhost_user_intf_t * vui)
            ("unmap memory region %d addr 0x%lx len 0x%lx page_sz 0x%x", i,
             vui->region_mmap_addr[i], map_sz, page_sz);
 
-         vui->region_mmap_addr[i] = (void *) -1;
+         vui->region_mmap_addr[i] = MAP_FAILED;
 
          if (r == -1)
            {
@@ -829,7 +899,7 @@ vhost_user_socket_read (clib_file_t * uf)
 
          long page_sz = get_huge_page_size (fds[i]);
 
-         /* align size to 2M page */
+         /* align size to page */
          ssize_t map_sz = (vui->regions[i].memory_size +
                            vui->regions[i].mmap_offset +
                            page_sz - 1) & ~(page_sz - 1);
@@ -1076,7 +1146,7 @@ vhost_user_socket_read (clib_file_t * uf)
          }
 
        fd = fds[0];
-       /* align size to 2M page */
+       /* align size to page */
        long page_sz = get_huge_page_size (fd);
        ssize_t map_sz =
          (msg.log.size + msg.log.offset + page_sz - 1) & ~(page_sz - 1);
@@ -1213,7 +1283,15 @@ vhost_user_socksvr_accept_ready (clib_file_t * uf)
   if (client_fd < 0)
     return clib_error_return_unix (0, "accept");
 
-  DBG_SOCK ("New client socket for vhost interface %d", vui->sw_if_index);
+  if (vui->clib_file_index != ~0)
+    {
+      DBG_SOCK ("Close client socket for vhost interface %d, fd %d",
+               vui->sw_if_index, UNIX_GET_FD (vui->clib_file_index));
+      clib_file_del (&file_main, file_main.file_pool + vui->clib_file_index);
+    }
+
+  DBG_SOCK ("New client socket for vhost interface %d, fd %d",
+           vui->sw_if_index, client_fd);
   template.read_function = vhost_user_socket_read;
   template.error_function = vhost_user_socket_error;
   template.file_descriptor = client_fd;
@@ -2470,16 +2548,14 @@ vhost_user_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index,
                                    u32 flags)
 {
   vnet_hw_interface_t *hif = vnet_get_hw_interface (vnm, hw_if_index);
-  uword is_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
   vhost_user_main_t *vum = &vhost_user_main;
   vhost_user_intf_t *vui =
     pool_elt_at_index (vum->vhost_user_interfaces, hif->dev_instance);
+  u32 hw_flags = 0;
+  vui->admin_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
+  hw_flags = vui->admin_up ? VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
 
-  vui->admin_up = is_up;
-
-  if (is_up && vui->is_up)
-    vnet_hw_interface_set_flags (vnm, vui->hw_if_index,
-                                VNET_HW_INTERFACE_FLAG_LINK_UP);
+  vnet_hw_interface_set_flags (vnm, vui->hw_if_index, hw_flags);
 
   return /* no error */ 0;
 }
@@ -2791,8 +2867,7 @@ vhost_user_create_ethernet (vnet_main_t * vnm, vlib_main_t * vm,
   if (error)
     clib_error_report (error);
 
-  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, vui->hw_if_index);
-  hi->max_l3_packet_bytes[VLIB_RX] = hi->max_l3_packet_bytes[VLIB_TX] = 9000;
+  vnet_sw_interface_set_mtu (vnm, vui->sw_if_index, 9000);
 }
 
 /*
@@ -3175,6 +3250,13 @@ show_vhost_user_command_fn (vlib_main_t * vm,
       if (unformat
          (input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
        {
+         hi = vnet_get_hw_interface (vnm, hw_if_index);
+         if (vhost_user_dev_class.index != hi->dev_class_index)
+           {
+             error = clib_error_return (0, "unknown input `%U'",
+                                        format_unformat_error, input);
+             goto done;
+           }
          vec_add1 (hw_if_indices, hw_if_index);
        }
       else if (unformat (input, "descriptors") || unformat (input, "desc"))