vlib: add format_vnet_buffer_no_chain
[vpp.git] / src / vnet / pg / stream.c
index 88c8937..605567c 100644 (file)
@@ -102,9 +102,8 @@ format_pg_output_trace (u8 * s, va_list * va)
   pg_output_trace_t *t = va_arg (*va, pg_output_trace_t *);
   u32 indent = format_get_indent (s);
 
-  s = format (s, "%Ubuffer 0x%x: %U",
-             format_white_space, indent,
-             t->buffer_index, format_vnet_buffer, &t->buffer);
+  s = format (s, "%Ubuffer 0x%x: %U", format_white_space, indent,
+             t->buffer_index, format_vnet_buffer_no_chain, &t->buffer);
 
   s = format (s, "\n%U%U", format_white_space, indent,
              format_ethernet_header_with_length, t->buffer.pre_data,
@@ -139,6 +138,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 +178,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* */
 
@@ -195,9 +228,29 @@ pg_interface_enable_disable_coalesce (pg_interface_t * pi, u8 enable,
     }
 }
 
+u8 *
+format_pg_tun_tx_trace (u8 *s, va_list *args)
+{
+  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
+  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
+
+  s = format (s, "PG: tunnel (no-encap)");
+  return s;
+}
+
+VNET_HW_INTERFACE_CLASS (pg_tun_hw_interface_class) = {
+  .name = "PG-tun",
+  //.format_header = format_gre_header_with_length,
+  //.unformat_header = unformat_gre_header,
+  .build_rewrite = NULL,
+  //.update_adjacency = gre_update_adj,
+  .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
+};
+
 u32
-pg_interface_add_or_get (pg_main_t * pg, uword if_id, u8 gso_enabled,
-                        u32 gso_size, u8 coalesce_enabled)
+pg_interface_add_or_get (pg_main_t *pg, uword if_id, u8 gso_enabled,
+                        u32 gso_size, u8 coalesce_enabled,
+                        pg_interface_mode_t mode)
 {
   vnet_main_t *vnm = vnet_get_main ();
   vlib_main_t *vm = vlib_get_main ();
@@ -228,12 +281,24 @@ pg_interface_add_or_get (pg_main_t * pg, uword if_id, u8 gso_enabled,
       hw_addr[1] = 0xfe;
 
       pi->id = if_id;
-      ethernet_register_interface (vnm, pg_dev_class.index, i, hw_addr,
-                                  &pi->hw_if_index, pg_eth_flag_change);
+      pi->mode = mode;
+
+      switch (pi->mode)
+       {
+       case PG_MODE_ETHERNET:
+         ethernet_register_interface (vnm, pg_dev_class.index, i, hw_addr,
+                                      &pi->hw_if_index, pg_eth_flag_change);
+         break;
+       case PG_MODE_IP4:
+       case PG_MODE_IP6:
+         pi->hw_if_index = vnet_register_interface (
+           vnm, pg_dev_class.index, i, pg_tun_hw_interface_class.index, i);
+         break;
+       }
       hi = vnet_get_hw_interface (vnm, pi->hw_if_index);
       if (gso_enabled)
        {
-         hi->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO;
+         hi->caps |= VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO;
          pi->gso_enabled = 1;
          pi->gso_size = gso_size;
          if (coalesce_enabled)
@@ -245,6 +310,9 @@ pg_interface_add_or_get (pg_main_t * pg, uword if_id, u8 gso_enabled,
 
       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,
@@ -473,9 +541,9 @@ 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, 0 /* gso_enabled */ ,
-                            0 /* gso_size */ , 0 /* coalesce_enabled */ );
+  s->pg_if_index = pg_interface_add_or_get (
+    pg, s->if_id, 0 /* gso_enabled */, 0 /* gso_size */,
+    0 /* coalesce_enabled */, PG_MODE_ETHERNET);
 
   if (s->sw_if_index[VLIB_RX] == ~0)
     {