L2 over MPLS

[support for VPWS/VPLS]
- switch to using dpo_proto_t rather than fib_protocol_t in fib_paths so that we can describe L2 paths
- VLIB nodes to handle pop/push of MPLS labels to L2

Change-Id: Id050d06a11fd2c9c1c81ce5a0654e6c5ae6afa6e
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vnet/fib/fib_path.c b/src/vnet/fib/fib_path.c
index 3a67a54..58050cc 100644
--- a/src/vnet/fib/fib_path.c
+++ b/src/vnet/fib/fib_path.c
@@ -193,7 +193,7 @@
      * next-hop's address. We can't derive this from the address itself
      * since the address can be all zeros
      */
-    fib_protocol_t fp_nh_proto;
+    dpo_proto_t fp_nh_proto;
 
     /**
      * UCMP [unnormalised] weigth
@@ -381,7 +381,7 @@
 
     s = format (s, "      index:%d ", fib_path_get_index(path));
     s = format (s, "pl-index:%d ", path->fp_pl_index);
-    s = format (s, "%U ", format_fib_protocol, path->fp_nh_proto);
+    s = format (s, "%U ", format_dpo_proto, path->fp_nh_proto);
     s = format (s, "weight=%d ", path->fp_weight);
     s = format (s, "pref=%d ", path->fp_preference);
     s = format (s, "%s: ", fib_path_type_names[path->fp_type]);
@@ -454,7 +454,7 @@
 	}
 	break;
     case FIB_PATH_TYPE_RECURSIVE:
-	if (FIB_PROTOCOL_MPLS == path->fp_nh_proto)
+	if (DPO_PROTO_MPLS == path->fp_nh_proto)
 	{
 	    s = format (s, "via %U %U",
 			format_mpls_unicast_label,
@@ -552,14 +552,14 @@
 	 * the subnet address (the attached route) links to the
 	 * auto-adj (see below), we want that adj here too.
 	 */
-	return (adj_nbr_add_or_lock(path->fp_nh_proto,
+	return (adj_nbr_add_or_lock(dpo_proto_to_fib(path->fp_nh_proto),
 				    link,
 				    &zero_addr,
 				    path->attached_next_hop.fp_interface));
     }
     else
     {
-	return (adj_nbr_add_or_lock(path->fp_nh_proto,
+	return (adj_nbr_add_or_lock(dpo_proto_to_fib(path->fp_nh_proto),
 				    link,
 				    &path->attached_next_hop.fp_nh,
 				    path->attached_next_hop.fp_interface));
@@ -575,10 +575,10 @@
      */
     dpo_set(&path->fp_dpo,
 	    DPO_ADJACENCY,
-	    fib_proto_to_dpo(path->fp_nh_proto),
+	    path->fp_nh_proto,
 	    fib_path_attached_next_hop_get_adj(
 		 path,
-		 fib_proto_to_link(path->fp_nh_proto)));
+		 dpo_proto_to_link(path->fp_nh_proto)));
 
     /*
      * become a child of the adjacency so we receive updates
@@ -607,14 +607,14 @@
          * point-2-point interfaces do not require a glean, since
          * there is nothing to ARP. Install a rewrite/nbr adj instead
          */
-        return (adj_nbr_add_or_lock(path->fp_nh_proto,
+        return (adj_nbr_add_or_lock(dpo_proto_to_fib(path->fp_nh_proto),
                                     link,
                                     &zero_addr,
                                     path->attached.fp_interface));
     }
     else
     {
-        return (adj_glean_add_or_lock(path->fp_nh_proto,
+        return (adj_glean_add_or_lock(dpo_proto_to_fib(path->fp_nh_proto),
                                       path->attached.fp_interface,
                                       NULL));
     }
@@ -650,7 +650,7 @@
     if (path->fp_oper_flags & FIB_PATH_OPER_FLAG_RECURSIVE_LOOP)
     {
 	path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
-	dpo_copy(&via_dpo, drop_dpo_get(fib_proto_to_dpo(path->fp_nh_proto)));
+	dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto));
     }
     else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RESOLVE_HOST)
     {
@@ -668,7 +668,7 @@
 	if (fib_entry_get_best_source(path->fp_via_fib) >= FIB_SOURCE_RR)
 	{
 	    path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
-            dpo_copy(&via_dpo, drop_dpo_get(fib_proto_to_dpo(path->fp_nh_proto)));
+            dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto));
 
             /*
              * PIC edge trigger. let the load-balance maps know
@@ -685,7 +685,7 @@
 	if (!(FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(path->fp_via_fib)))
 	{
 	    path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
-            dpo_copy(&via_dpo, drop_dpo_get(fib_proto_to_dpo(path->fp_nh_proto)));
+            dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto));
 
             /*
              * PIC edge trigger. let the load-balance maps know
@@ -699,7 +699,7 @@
     if (!fib_entry_is_resolved(path->fp_via_fib))
     {
         path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
-        dpo_copy(&via_dpo, drop_dpo_get(fib_proto_to_dpo(path->fp_nh_proto)));
+        dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto));
 
         /*
          * PIC edge trigger. let the load-balance maps know
@@ -720,9 +720,7 @@
      */
     dpo_copy(dpo, &via_dpo);
 
-    FIB_PATH_DBG(path, "recursive update: %U",
-		 fib_get_lookup_main(path->fp_nh_proto),
-		 &path->fp_dpo, 2);
+    FIB_PATH_DBG(path, "recursive update:");
 
     dpo_reset(&via_dpo);
 }
@@ -804,13 +802,8 @@
 static fib_forward_chain_type_t
 fib_path_to_chain_type (const fib_path_t *path)
 {
-    switch (path->fp_nh_proto)
+    if (DPO_PROTO_MPLS == path->fp_nh_proto)
     {
-    case FIB_PROTOCOL_IP4:
-	return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
-    case FIB_PROTOCOL_IP6:
-	return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6);
-    case FIB_PROTOCOL_MPLS:
         if (FIB_PATH_TYPE_RECURSIVE == path->fp_type &&
             MPLS_EOS == path->recursive.fp_nh.fp_eos)
         {
@@ -821,7 +814,10 @@
             return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS);
         }
     }
-    return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
+    else
+    {
+        return (fib_forw_chain_type_from_dpo_proto(path->fp_nh_proto));
+    }
 }
 
 /*
@@ -927,7 +923,7 @@
 
             ai = fib_path_attached_next_hop_get_adj(
                      path,
-                     fib_proto_to_link(path->fp_nh_proto));
+                     dpo_proto_to_link(path->fp_nh_proto));
 
             path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
             if (if_is_up && adj_is_up(ai))
@@ -935,9 +931,7 @@
                 path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
             }
 
-            dpo_set(&path->fp_dpo, DPO_ADJACENCY,
-                    fib_proto_to_dpo(path->fp_nh_proto),
-                    ai);
+            dpo_set(&path->fp_dpo, DPO_ADJACENCY, path->fp_nh_proto, ai);
             adj_unlock(ai);
 
             if (!if_is_up)
@@ -1141,7 +1135,7 @@
 	else
 	{
 	    path->fp_type = FIB_PATH_TYPE_RECURSIVE;
-	    if (FIB_PROTOCOL_MPLS == path->fp_nh_proto)
+	    if (DPO_PROTO_MPLS == path->fp_nh_proto)
 	    {
 		path->recursive.fp_nh.fp_local_label = rpath->frp_local_label;
                 path->recursive.fp_nh.fp_eos = rpath->frp_eos;
@@ -1167,7 +1161,7 @@
  */
 fib_node_index_t
 fib_path_create_special (fib_node_index_t pl_index,
-			 fib_protocol_t nh_proto,
+			 dpo_proto_t nh_proto,
 			 fib_path_cfg_flags_t flags,
 			 const dpo_id_t *dpo)
 {
@@ -1433,7 +1427,7 @@
 	    res = (path->attached.fp_interface - rpath->frp_sw_if_index);
 	    break;
 	case FIB_PATH_TYPE_RECURSIVE:
-            if (FIB_PROTOCOL_MPLS == path->fp_nh_proto)
+            if (DPO_PROTO_MPLS == path->fp_nh_proto)
             {
                 res = path->recursive.fp_nh.fp_local_label - rpath->frp_local_label;
 
@@ -1535,8 +1529,7 @@
 	    FIB_PATH_DBG(path, "recursive loop formed");
 	    path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RECURSIVE_LOOP;
 
-	    dpo_copy(&path->fp_dpo,
-                    drop_dpo_get(fib_proto_to_dpo(path->fp_nh_proto)));
+	    dpo_copy(&path->fp_dpo, drop_dpo_get(path->fp_nh_proto));
 	}
 	else
 	{
@@ -1590,8 +1583,7 @@
      */
     if (fib_path_is_permanent_drop(path))
     {
-	dpo_copy(&path->fp_dpo,
-                 drop_dpo_get(fib_proto_to_dpo(path->fp_nh_proto)));
+	dpo_copy(&path->fp_dpo, drop_dpo_get(path->fp_nh_proto));
 	path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
 	return (fib_path_is_resolved(path_index));
     }
@@ -1612,9 +1604,9 @@
 	}
         dpo_set(&path->fp_dpo,
                 DPO_ADJACENCY,
-                fib_proto_to_dpo(path->fp_nh_proto),
+                path->fp_nh_proto,
                 fib_path_attached_get_adj(path,
-                                          fib_proto_to_link(path->fp_nh_proto)));
+                                          dpo_proto_to_link(path->fp_nh_proto)));
 
 	/*
 	 * become a child of the adjacency so we receive updates
@@ -1639,7 +1631,7 @@
 
 	ASSERT(FIB_NODE_INDEX_INVALID == path->fp_via_fib);
 
-	if (FIB_PROTOCOL_MPLS == path->fp_nh_proto)
+	if (DPO_PROTO_MPLS == path->fp_nh_proto)
 	{
 	    fib_prefix_from_mpls_label(path->recursive.fp_nh.fp_local_label,
                                        path->recursive.fp_nh.fp_eos,
@@ -1680,8 +1672,7 @@
 	/*
 	 * Resolve via the drop
 	 */
-	dpo_copy(&path->fp_dpo,
-                 drop_dpo_get(fib_proto_to_dpo(path->fp_nh_proto)));
+	dpo_copy(&path->fp_dpo, drop_dpo_get(path->fp_nh_proto));
 	break;
     case FIB_PATH_TYPE_DEAG:
     {
@@ -1696,7 +1687,7 @@
                 LOOKUP_UNICAST);
 
         lookup_dpo_add_or_lock_w_fib_index(path->deag.fp_tbl_id,
-                                           fib_proto_to_dpo(path->fp_nh_proto),
+                                           path->fp_nh_proto,
                                            cast,
                                            LOOKUP_INPUT_DST_ADDR,
                                            LOOKUP_TABLE_FROM_CONFIG,
@@ -1707,7 +1698,7 @@
 	/*
 	 * Resolve via a receive DPO.
 	 */
-	receive_dpo_add_or_lock(fib_proto_to_dpo(path->fp_nh_proto),
+	receive_dpo_add_or_lock(path->fp_nh_proto,
                                 path->receive.fp_interface,
                                 &path->receive.fp_addr,
                                 &path->fp_dpo);
@@ -1716,7 +1707,7 @@
 	/*
 	 * Resolve via a receive DPO.
 	 */
-	interface_dpo_add_or_lock(fib_proto_to_dpo(path->fp_nh_proto),
+	interface_dpo_add_or_lock(path->fp_nh_proto,
                                   path->intf_rx.fp_interface,
                                   &path->fp_dpo);
 	break;
@@ -2035,7 +2026,7 @@
                     /*
                      * Create the adj needed for sending IP multicast traffic
                      */
-                    ai = adj_mcast_add_or_lock(path->fp_nh_proto,
+                    ai = adj_mcast_add_or_lock(dpo_proto_to_fib(path->fp_nh_proto),
                                                fib_forw_chain_type_to_link_type(fct),
                                                path->attached.fp_interface);
                     dpo_set(dpo, DPO_ADJACENCY,
@@ -2187,7 +2178,7 @@
     return (FIB_PATH_LIST_WALK_CONTINUE);
 }
 
-fib_protocol_t
+dpo_proto_t
 fib_path_get_proto (fib_node_index_t path_index)
 {
     fib_path_t *path;