Allow vlans to be programmed on 40GE VF interfaces
[vpp.git] / vnet / vnet / devices / dpdk / init.c
index c9187d5..8bb253a 100644 (file)
@@ -158,23 +158,6 @@ static u32 dpdk_flag_change (vnet_main_t * vnm,
        {
          int rv;
       
-         /*
-          * DAW-FIXME: The DPDK VMXNET3 driver does not currently support
-          *            multi-buffer packets.  Max out at 1518 bytes for now.
-          *
-          *            If/when the driver gets fixed, then this should be
-          *            removed.
-          */
-         if ((xd->pmd == VNET_DPDK_PMD_VMXNET3) &&
-             (hi->max_packet_bytes > 1518))
-           {
-             hi->max_packet_bytes = 1518;
-
-             vlib_cli_output (vlib_get_main(), 
-                              "VMXNET3 driver does not  support jumbo frames "
-                              "yet -- setting mtu to 1518!");
-           }
-
          xd->port_conf.rxmode.max_rx_pkt_len = hi->max_packet_bytes;
 
          if (xd->admin_up)
@@ -465,6 +448,10 @@ dpdk_lib_init (dpdk_main_t * dm)
             xd->af_packet_port_id = af_packet_port_id++;
             break;
 
+          case VNET_DPDK_PMD_BOND:
+            xd->port_type = VNET_DPDK_PORT_TYPE_ETH_BOND;
+            break;
+
           default:
             xd->port_type = VNET_DPDK_PORT_TYPE_UNKNOWN;
         }
@@ -711,17 +698,6 @@ dpdk_lib_init (dpdk_main_t * dm)
   return 0;
 }
 
-/*
- * Tell the vlib physical memory allocator that we've handled
- * the initialization. We don't actually do so until
- * vlib_main(...) callls the dpdk config function.
- */
-int vlib_app_physmem_init (vlib_main_t * vm, physmem_main_t * pm,
-                           int physmem_required)
-{
-  return 1;
-}
-
 static clib_error_t *
 write_sys_fs (char * file_name, char * fmt, ...)
 {
@@ -891,8 +867,6 @@ static clib_error_t * dpdk_bind_eth_kernel_drivers (vlib_main_t * vm,
           _vec_len (path) = 0;
           path = format (path, "/sys/bus/pci/drivers/%s/new_id%c", driver_name, 0);
           error = write_sys_fs ((char *) path, "%s %s", pci_vid, pci_did);
-          if (error)
-            continue;
 
           _vec_len (path) = 0;
           path = format (path, "/sys/bus/pci/drivers/%s/bind%c", driver_name, 0);
@@ -916,33 +890,6 @@ static clib_error_t * dpdk_bind_eth_kernel_drivers (vlib_main_t * vm,
   return error;
 }
 
-static uword
-unformat_socket_mem (unformat_input_t * input, va_list * va)
-{
-  uword ** r = va_arg (* va, uword **);
-  int i = 0;
-  u32 mem;
-
-  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
-    {
-      if (unformat (input, ","))
-        hash_set (*r, i, 1024);
-      else if (unformat (input, "%u,", &mem))
-        hash_set (*r, i, mem);
-      else if (unformat (input, "%u", &mem))
-        hash_set (*r, i, mem);
-      else
-        {
-          unformat_put_input (input);
-          goto done;
-        }
-      i++;
-    }
-
-done:
-  return 1;
-}
-
 static u32
 get_node_free_hugepages_num (u32 node, u32 page_size)
 {
@@ -1182,11 +1129,11 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
                  u32 pages_avail;
 
                  pages_avail = get_node_free_hugepages_num(c, 1048576);
-                 if (!(pages_avail >= pages_num_1g))
+                 if (!pages_avail || !(pages_avail >= pages_num_1g))
                    use_1g = 0;
 
                  pages_avail = get_node_free_hugepages_num(c, 2048);
-                 if (!(pages_avail >= pages_num_2m))
+                 if (!pages_avail || !(pages_avail >= pages_num_2m))
                    use_2m = 0;
               }
            }
@@ -1453,14 +1400,18 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
   if (ret < 0)
     return clib_error_return (0, "rte_eal_init returned %d", ret);
 
+  /* Dump the physical memory layout prior to creating the mbuf_pool */
+  fprintf(stdout, "DPDK physical memory layout:\n");
+  rte_dump_physmem_layout(stdout);
+
   /* main thread 1st */
-  error = vlib_buffer_pool_create(vm, dm->num_mbufs, MBUF_SIZE, rte_socket_id());
+  error = vlib_buffer_pool_create(vm, dm->num_mbufs, rte_socket_id());
   if (error)
     return error;
 
   for (i = 0; i < RTE_MAX_LCORE; i++)
     {
-      error = vlib_buffer_pool_create(vm, dm->num_mbufs, MBUF_SIZE,
+      error = vlib_buffer_pool_create(vm, dm->num_mbufs,
                                       rte_lcore_to_socket_id(i));
       if (error)
         return error;
@@ -1589,7 +1540,9 @@ dpdk_process (vlib_main_t * vm,
               vlib_frame_t * f)
 {
   clib_error_t * error;
+  vnet_main_t * vnm = vnet_get_main();
   dpdk_main_t * dm = &dpdk_main;
+  ethernet_main_t * em = &ethernet_main;
   dpdk_device_t * xd;
   vlib_thread_main_t * tm = vlib_get_thread_main();
   void *vu_state;
@@ -1630,9 +1583,54 @@ dpdk_process (vlib_main_t * vm,
       dpdk_update_link_state (xd, now);
     }
 
+{ // Setup MACs for bond interfaces and their links which was initialized in
+  // dpdk_port_setup() but needs to be done again here to take effect.
+  int nports = rte_eth_dev_count();
+  if (nports > 0) {
+      for (i = 0; i < nports; i++) {
+         struct rte_eth_dev_info dev_info;
+         rte_eth_dev_info_get(i, &dev_info);
+         if (!dev_info.driver_name)
+             dev_info.driver_name = dev_info.pci_dev->driver->name;
+         ASSERT(dev_info.driver_name);
+         if (strncmp(dev_info.driver_name, "rte_bond_pmd", 12) == 0) {
+             u8  addr[6]; 
+             u8  slink[16];
+             int nlink = rte_eth_bond_slaves_get(i, slink, 16);
+             if (nlink > 0) {
+                 vnet_hw_interface_t * hi;
+                 ethernet_interface_t * ei;
+                 /* Get MAC of 1st slave link */
+                 rte_eth_macaddr_get(slink[0], (struct ether_addr *)addr);
+                 /* Set MAC of bounded interface to that of 1st slave link */
+                 rte_eth_bond_mac_address_set(i, (struct ether_addr *)addr);
+                 /* Populate MAC of bonded interface in VPP hw tables */
+                 hi = vnet_get_hw_interface (
+                     vnm, dm->devices[i].vlib_hw_if_index);
+                 ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
+                 memcpy (hi->hw_address, addr, 6);
+                 memcpy (ei->address, addr, 6);
+                 /* Add MAC to other slave links */
+                 while (nlink > 1) {
+                     nlink--;
+                     rte_eth_dev_mac_addr_add(
+                         slink[nlink], (struct ether_addr *)addr, 0);
+                 }
+             }
+         }
+      }
+  }
+}
+
   while (1)
     {
-      vlib_process_wait_for_event_or_clock (vm, 5.0);
+      /*
+       * check each time through the loop in case intervals are changed
+       */
+      f64 min_wait = dm->link_state_poll_interval < dm->stat_poll_interval ?
+                     dm->link_state_poll_interval : dm->stat_poll_interval;
+
+      vlib_process_wait_for_event_or_clock (vm, min_wait);
 
       if (dpdk_get_admin_up_down_in_progress())
           /* skip the poll if an admin up down is in progress (on any interface) */
@@ -1641,9 +1639,9 @@ dpdk_process (vlib_main_t * vm,
       vec_foreach (xd, dm->devices)
        {
          f64 now = vlib_time_now (vm);
-         if ((now - xd->time_last_stats_update) >= DPDK_STATS_POLL_INTERVAL)
+          if ((now - xd->time_last_stats_update) >= dm->stat_poll_interval)
            dpdk_update_counters (xd, now);
-         if ((now - xd->time_last_link_update) >= DPDK_LINK_POLL_INTERVAL)
+          if ((now - xd->time_last_link_update) >= dm->link_state_poll_interval)
            dpdk_update_link_state (xd, now);
 
       if (xd->dev_type == VNET_DPDK_DEV_VHOST_USER)
@@ -1664,6 +1662,26 @@ VLIB_REGISTER_NODE (dpdk_process_node,static) = {
     .process_log2_n_stack_bytes = 17,
 };
 
+int dpdk_set_stat_poll_interval (f64 interval)
+{
+  if (interval < DPDK_MIN_STATS_POLL_INTERVAL)
+      return (VNET_API_ERROR_INVALID_VALUE);
+
+  dpdk_main.stat_poll_interval = interval;
+
+  return 0;
+}
+
+int dpdk_set_link_state_poll_interval (f64 interval)
+{
+  if (interval < DPDK_MIN_LINK_POLL_INTERVAL)
+      return (VNET_API_ERROR_INVALID_VALUE);
+
+  dpdk_main.link_state_poll_interval = interval;
+
+  return 0;
+}
+
 clib_error_t *
 dpdk_init (vlib_main_t * vm)
 {
@@ -1733,6 +1751,10 @@ do {                                                  \
   _(rte_cxgbe_driver)
 #endif
 
+#ifdef RTE_LIBRTE_PMD_BOND
+  _(bond_drv)
+#endif
+
 #undef _
 
 /* 
@@ -1788,6 +1810,9 @@ _(rte_nicvf_pmd_init)
      | IP_BUFFER_L4_CHECKSUM_COMPUTED
      | IP_BUFFER_L4_CHECKSUM_CORRECT);
 
+  dm->stat_poll_interval = DPDK_STATS_POLL_INTERVAL;
+  dm->link_state_poll_interval = DPDK_LINK_POLL_INTERVAL;
+
   /* init CLI */
   if ((error = vlib_call_init_function (vm, dpdk_cli_init)))
     return error;