ip-neighbor: Use ip_address_t rather than ip46_address_t
[vpp.git] / src / vnet / pg / stream.c
index ddd15d6..6ea8090 100644 (file)
@@ -139,6 +139,39 @@ pg_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
   return 0;
 }
 
+static int
+pg_mac_address_cmp (const mac_address_t * m1, const mac_address_t * m2)
+{
+  return (!mac_address_cmp (m1, m2));
+}
+
+static clib_error_t *
+pg_add_del_mac_address (vnet_hw_interface_t * hi,
+                       const u8 * address, u8 is_add)
+{
+  pg_main_t *pg = &pg_main;
+
+  if (ethernet_address_cast (address))
+    {
+      mac_address_t mac;
+      pg_interface_t *pi;
+
+      pi = pool_elt_at_index (pg->interfaces, hi->dev_instance);
+
+      mac_address_from_bytes (&mac, address);
+      if (is_add)
+       vec_add1 (pi->allowed_mcast_macs, mac);
+      else
+       {
+         u32 pos = vec_search_with_function (pi->allowed_mcast_macs, &mac,
+                                             pg_mac_address_cmp);
+         if (~0 != pos)
+           vec_del1 (pi->allowed_mcast_macs, pos);
+       }
+    }
+  return (NULL);
+}
+
 /* *INDENT-OFF* */
 VNET_DEVICE_CLASS (pg_dev_class) = {
   .name = "pg",
@@ -146,6 +179,7 @@ VNET_DEVICE_CLASS (pg_dev_class) = {
   .format_device_name = format_pg_interface_name,
   .format_tx_trace = format_pg_output_trace,
   .admin_up_down_function = pg_interface_admin_up_down,
+  .mac_addr_add_del_function = pg_add_del_mac_address,
 };
 /* *INDENT-ON* */
 
@@ -178,8 +212,26 @@ pg_eth_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi, u32 flags)
   return 0;
 }
 
+void
+pg_interface_enable_disable_coalesce (pg_interface_t * pi, u8 enable,
+                                     u32 tx_node_index)
+{
+  if (enable)
+    {
+      gro_flow_table_init (&pi->flow_table, 1 /* is_l2 */ ,
+                          tx_node_index);
+      pi->coalesce_enabled = 1;
+    }
+  else
+    {
+      pi->coalesce_enabled = 0;
+      gro_flow_table_free (pi->flow_table);
+    }
+}
+
 u32
-pg_interface_add_or_get (pg_main_t * pg, uword if_id)
+pg_interface_add_or_get (pg_main_t * pg, uword if_id, u8 gso_enabled,
+                        u32 gso_size, u8 coalesce_enabled)
 {
   vnet_main_t *vnm = vnet_get_main ();
   vlib_main_t *vm = vlib_get_main ();
@@ -213,10 +265,23 @@ pg_interface_add_or_get (pg_main_t * pg, uword if_id)
       ethernet_register_interface (vnm, pg_dev_class.index, i, hw_addr,
                                   &pi->hw_if_index, pg_eth_flag_change);
       hi = vnet_get_hw_interface (vnm, pi->hw_if_index);
+      if (gso_enabled)
+       {
+         hi->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO;
+         pi->gso_enabled = 1;
+         pi->gso_size = gso_size;
+         if (coalesce_enabled)
+           {
+             pg_interface_enable_disable_coalesce (pi, 1, hi->tx_node_index);
+           }
+       }
       pi->sw_if_index = hi->sw_if_index;
 
       hash_set (pg->if_index_by_if_id, if_id, i);
 
+      vec_validate (pg->if_id_by_sw_if_index, hi->sw_if_index);
+      pg->if_id_by_sw_if_index[hi->sw_if_index] = i;
+
       if (vlib_num_workers ())
        {
          pi->lockp = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES,
@@ -437,7 +502,7 @@ pg_stream_add (pg_main_t * pg, pg_stream_t * s_init)
   {
     int n;
 
-    s->buffer_bytes = VLIB_BUFFER_DATA_SIZE;
+    s->buffer_bytes = vlib_buffer_get_default_data_size (vm);
     n = s->max_packet_bytes / s->buffer_bytes;
     n += (s->max_packet_bytes % s->buffer_bytes) != 0;
 
@@ -445,18 +510,20 @@ pg_stream_add (pg_main_t * pg, pg_stream_t * s_init)
   }
 
   /* Find an interface to use. */
-  s->pg_if_index = pg_interface_add_or_get (pg, s->if_id);
+  s->pg_if_index =
+    pg_interface_add_or_get (pg, s->if_id, 0 /* gso_enabled */ ,
+                            0 /* gso_size */ , 0 /* coalesce_enabled */ );
 
-  {
-    pg_interface_t *pi = pool_elt_at_index (pg->interfaces, s->pg_if_index);
-    vlib_rx_or_tx_t rx_or_tx;
-
-    vlib_foreach_rx_tx (rx_or_tx)
+  if (s->sw_if_index[VLIB_RX] == ~0)
     {
-      if (s->sw_if_index[rx_or_tx] == ~0)
-       s->sw_if_index[rx_or_tx] = pi->sw_if_index;
+      pg_interface_t *pi = pool_elt_at_index (pg->interfaces, s->pg_if_index);
+      /*
+       * Default the RX interface if unset. It's a bad mistake to
+       * set [VLIB_TX] prior to ip lookup, since the ip lookup code
+       * interprets [VLIB_TX] as a fib index...
+       */
+      s->sw_if_index[VLIB_RX] = pi->sw_if_index;
     }
-  }
 
   /* Connect the graph. */
   s->next_index = vlib_node_add_next (vm, device_input_node.index,
@@ -483,6 +550,31 @@ pg_stream_del (pg_main_t * pg, uword index)
   pool_put (pg->streams, s);
 }
 
+void
+pg_stream_change (pg_main_t * pg, pg_stream_t * s)
+{
+  /* Determine packet size. */
+  switch (s->packet_size_edit_type)
+    {
+    case PG_EDIT_INCREMENT:
+    case PG_EDIT_RANDOM:
+      if (s->min_packet_bytes == s->max_packet_bytes)
+       s->packet_size_edit_type = PG_EDIT_FIXED;
+    case PG_EDIT_FIXED:
+      break;
+
+    default:
+      /* Get packet size from fixed edits. */
+      s->packet_size_edit_type = PG_EDIT_FIXED;
+      if (!s->replay_packet_templates)
+       s->min_packet_bytes = s->max_packet_bytes =
+         vec_len (s->fixed_packet_data);
+      break;
+    }
+
+  s->last_increment_packet_size = s->min_packet_bytes;
+}
+
 
 /*
  * fd.io coding-style-patch-verification: ON