fib: Don't use [midchain] adjacencies to change an interface's feature arc
[vpp.git] / src / plugins / pppoe / pppoe.c
index ad05b8e..182f93b 100644 (file)
@@ -37,6 +37,8 @@
 
 pppoe_main_t pppoe_main;
 
+static fib_source_t pppoe_fib_src;
+
 u8 *
 format_pppoe_session (u8 * s, va_list * args)
 {
@@ -96,23 +98,53 @@ pppoe_build_rewrite (vnet_main_t * vnm,
                     u32 sw_if_index,
                     vnet_link_t link_type, const void *dst_address)
 {
-  int len = sizeof (pppoe_header_t) + sizeof (ethernet_header_t);
   pppoe_main_t *pem = &pppoe_main;
   pppoe_session_t *t;
+  vnet_hw_interface_t *hi;
+  vnet_sw_interface_t *si;
+  pppoe_header_t *pppoe;
   u32 session_id;
   u8 *rw = 0;
 
   session_id = pem->session_index_by_sw_if_index[sw_if_index];
   t = pool_elt_at_index (pem->sessions, session_id);
 
+  int len = sizeof (pppoe_header_t) + sizeof (ethernet_header_t);
+  si = vnet_get_sw_interface (vnm, t->encap_if_index);
+  if (si->type == VNET_SW_INTERFACE_TYPE_SUB)
+    {
+      if (si->sub.eth.flags.one_tag == 1)
+       {
+         len += sizeof (ethernet_vlan_header_t);
+       }
+    }
+
   vec_validate_aligned (rw, len - 1, CLIB_CACHE_LINE_BYTES);
 
   ethernet_header_t *eth_hdr = (ethernet_header_t *) rw;
-  clib_memcpy (eth_hdr->dst_address, t->client_mac, 6);
-  clib_memcpy (eth_hdr->src_address, t->local_mac, 6);
   eth_hdr->type = clib_host_to_net_u16 (ETHERNET_TYPE_PPPOE_SESSION);
+  pppoe = (pppoe_header_t *) (eth_hdr + 1);
+
+  if (si->type == VNET_SW_INTERFACE_TYPE_SUB)
+    {
+      if (si->sub.eth.flags.one_tag == 1)
+       {
+         eth_hdr->type = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
+         ethernet_vlan_header_t *vlan =
+           (ethernet_vlan_header_t *) (eth_hdr + 1);
+         vlan->type = clib_host_to_net_u16 (ETHERNET_TYPE_PPPOE_SESSION);
+         vlan->priority_cfi_and_id =
+           clib_host_to_net_u16 (si->sub.eth.outer_vlan_id);
+         pppoe = (pppoe_header_t *) (vlan + 1);
+       }
+      si = vnet_get_sw_interface (vnm, si->sup_sw_if_index);
+    }
+
+  // set the right mac addresses
+  hi = vnet_get_hw_interface (vnm, si->hw_if_index);
+  clib_memcpy (eth_hdr->src_address, hi->hw_address, 6);
+  clib_memcpy (eth_hdr->dst_address, t->client_mac, 6);
 
-  pppoe_header_t *pppoe = (pppoe_header_t *) (eth_hdr + 1);
   pppoe->ver_type = PPPOE_VER_TYPE;
   pppoe->code = 0;
   pppoe->session_id = clib_host_to_net_u16 (t->session_id);
@@ -138,22 +170,18 @@ pppoe_build_rewrite (vnet_main_t * vnm,
  */
 static void
 pppoe_fixup (vlib_main_t * vm,
-            ip_adjacency_t * adj, vlib_buffer_t * b0, const void *data)
+            const ip_adjacency_t * adj, vlib_buffer_t * b0, const void *data)
 {
-  const pppoe_session_t *t;
+  //const pppoe_session_t *t;
   pppoe_header_t *pppoe0;
+  uword len = (uword) data;
 
   /* update the rewrite string */
-  pppoe0 = vlib_buffer_get_current (b0) + sizeof (ethernet_header_t);
+  pppoe0 = vlib_buffer_get_current (b0) + len;
 
   pppoe0->length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)
                                         - sizeof (pppoe_header_t)
-                                        + sizeof (pppoe0->ppp_proto)
-                                        - sizeof (ethernet_header_t));
-  /* Swap to the the packet's output interface to the encap (not the
-   * session) interface */
-  t = data;
-  vnet_buffer (b0)->sw_if_index[VLIB_TX] = t->encap_if_index;
+                                        + sizeof (pppoe0->ppp_proto) - len);
 }
 
 static void
@@ -163,6 +191,7 @@ pppoe_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai)
   dpo_id_t dpo = DPO_INVALID;
   ip_adjacency_t *adj;
   pppoe_session_t *t;
+  vnet_sw_interface_t *si;
   u32 session_id;
 
   ASSERT (ADJ_INDEX_INVALID != ai);
@@ -171,12 +200,23 @@ pppoe_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai)
   session_id = pem->session_index_by_sw_if_index[sw_if_index];
   t = pool_elt_at_index (pem->sessions, session_id);
 
+  uword len = sizeof (ethernet_header_t);
+
+  si = vnet_get_sw_interface (vnm, t->encap_if_index);
+  if (si->type == VNET_SW_INTERFACE_TYPE_SUB)
+    {
+      if (si->sub.eth.flags.one_tag == 1)
+       {
+         len += sizeof (ethernet_vlan_header_t);
+       }
+    }
+
   switch (adj->lookup_next_index)
     {
     case IP_LOOKUP_NEXT_ARP:
     case IP_LOOKUP_NEXT_GLEAN:
     case IP_LOOKUP_NEXT_BCAST:
-      adj_nbr_midchain_update_rewrite (ai, pppoe_fixup, t,
+      adj_nbr_midchain_update_rewrite (ai, pppoe_fixup, (void *) len,
                                       ADJ_FLAG_NONE,
                                       pppoe_build_rewrite (vnm,
                                                            sw_if_index,
@@ -188,7 +228,7 @@ pppoe_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai)
        * Construct a partial rewrite from the known ethernet mcast dest MAC
        * There's no MAC fixup, so the last 2 parameters are 0
        */
-      adj_mcast_midchain_update_rewrite (ai, pppoe_fixup, t,
+      adj_mcast_midchain_update_rewrite (ai, pppoe_fixup, (void *) len,
                                         ADJ_FLAG_NONE,
                                         pppoe_build_rewrite (vnm,
                                                              sw_if_index,
@@ -373,10 +413,12 @@ int vnet_pppoe_add_del_session
       si->flags &= ~VNET_SW_INTERFACE_FLAG_HIDDEN;
       vnet_sw_interface_set_flags (vnm, sw_if_index,
                                   VNET_SW_INTERFACE_FLAG_ADMIN_UP);
+      vnet_set_interface_l3_output_node (vnm->vlib_main, sw_if_index,
+                                        (u8 *) "tunnel-output");
 
       /* add reverse route for client ip */
       fib_table_entry_path_add (a->decap_fib_index, &pfx,
-                               FIB_SOURCE_PLUGIN_HI, FIB_ENTRY_FLAG_NONE,
+                               pppoe_fib_src, FIB_ENTRY_FLAG_NONE,
                                fib_proto_to_dpo (pfx.fp_proto),
                                &pfx.fp_addr, sw_if_index, ~0,
                                1, NULL, FIB_ROUTE_PATH_FLAG_NONE);
@@ -391,6 +433,7 @@ int vnet_pppoe_add_del_session
       t = pool_elt_at_index (pem->sessions, result.fields.session_index);
       sw_if_index = t->sw_if_index;
 
+      vnet_reset_interface_l3_output_node (vnm->vlib_main, sw_if_index);
       vnet_sw_interface_set_flags (vnm, t->sw_if_index, 0 /* down */ );
       vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, t->sw_if_index);
       si->flags |= VNET_SW_INTERFACE_FLAG_HIDDEN;
@@ -408,7 +451,7 @@ int vnet_pppoe_add_del_session
 
       /* delete reverse route for client ip */
       fib_table_entry_path_remove (a->decap_fib_index, &pfx,
-                                  FIB_SOURCE_PLUGIN_HI,
+                                  pppoe_fib_src,
                                   fib_proto_to_dpo (pfx.fp_proto),
                                   &pfx.fp_addr,
                                   sw_if_index, ~0, 1,
@@ -592,10 +635,10 @@ show_pppoe_session_command_fn (vlib_main_t * vm,
   if (pool_elts (pem->sessions) == 0)
     vlib_cli_output (vm, "No pppoe sessions configured...");
 
-  pool_foreach (t, pem->sessions,
-               ({
+  pool_foreach (t, pem->sessions)
+                {
                    vlib_cli_output (vm, "%U",format_pppoe_session, t);
-               }));
+               }
 
   return 0;
 }
@@ -626,7 +669,7 @@ typedef struct pppoe_show_walk_ctx_t_
   u32 total_entries;
 } pppoe_show_walk_ctx_t;
 
-static void
+static int
 pppoe_show_walk_cb (BVT (clib_bihash_kv) * kvp, void *arg)
 {
   pppoe_show_walk_ctx_t *ctx = arg;
@@ -654,6 +697,8 @@ pppoe_show_walk_cb (BVT (clib_bihash_kv) * kvp, void *arg)
                   result.fields.session_index == ~0
                   ? -1 : result.fields.session_index);
   ctx->total_entries++;
+
+  return (BIHASH_WALK_CONTINUE);
 }
 
 /** Display the contents of the PPPoE Fib. */
@@ -679,7 +724,7 @@ show_pppoe_fib_command_fn (vlib_main_t * vm,
 }
 
 /*?
- * This command dispays the MAC Address entries of the PPPoE FIB table.
+ * This command displays the MAC Address entries of the PPPoE FIB table.
  * Output can be filtered to just get the number of MAC Addresses or display
  * each MAC Address.
  *
@@ -687,9 +732,9 @@ show_pppoe_fib_command_fn (vlib_main_t * vm,
  * Example of how to display the number of MAC Address entries in the PPPoE
  * FIB table:
  * @cliexstart{show pppoe fib}
- *     Mac Address      session_id      Interface           sw_if_index  session_index
- *  52:54:00:53:18:33     1          GigabitEthernet0/8/0        2          0
- *  52:54:00:53:18:55     2          GigabitEthernet0/8/1        3          1
+ *    Mac Address    session_id    Interface         sw_if_index session_index
+ * 52:54:00:53:18:33   1        GigabitEthernet0/8/0      2          0
+ * 52:54:00:53:18:55   2        GigabitEthernet0/8/1      3          1
  * @cliexend
 ?*/
 /* *INDENT-OFF* */
@@ -721,6 +766,10 @@ pppoe_init (vlib_main_t * vm)
   ethernet_register_input_type (vm, ETHERNET_TYPE_PPPOE_DISCOVERY,
                                pppoe_cp_dispatch_node.index);
 
+  pppoe_fib_src = fib_source_allocate ("pppoe",
+                                      FIB_SOURCE_PRIORITY_HI,
+                                      FIB_SOURCE_BH_API);
+
   return 0;
 }