+ if (l2_only)
+ {
+ mt->mt_l2_adj =
+ adj_nbr_add_or_lock(fib_path_list_get_proto(mt->mt_path_list),
+ VNET_LINK_ETHERNET,
+ &zero_addr,
+ mt->mt_sw_if_index);
+
+ mt->mt_l2_tx_arc = vlib_node_add_named_next(vlib_get_main(),
+ hi->tx_node_index,
+ "adj-l2-midchain");
+ }
+
+ return (mt->mt_sw_if_index);
+}
+
+/*
+ * mpls_tunnel_path_ext_add
+ *
+ * append a path extension to the entry's list
+ */
+static void
+mpls_tunnel_path_ext_append (mpls_tunnel_t *mt,
+ const fib_route_path_t *rpath)
+{
+ if (NULL != rpath->frp_label_stack)
+ {
+ fib_path_ext_t *path_ext;
+
+ vec_add2(mt->mt_path_exts, path_ext, 1);
+
+ fib_path_ext_init(path_ext, mt->mt_path_list, rpath);
+ }
+}
+
+/*
+ * mpls_tunnel_path_ext_insert
+ *
+ * insert, sorted, a path extension to the entry's list.
+ * It's not strictly necessary in sort the path extensions, since each
+ * extension has the path index to which it resolves. However, by being
+ * sorted the load-balance produced has a deterministic order, not an order
+ * based on the sequence of extension additions. this is a considerable benefit.
+ */
+static void
+mpls_tunnel_path_ext_insert (mpls_tunnel_t *mt,
+ const fib_route_path_t *rpath)
+{
+ if (0 == vec_len(mt->mt_path_exts))
+ return (mpls_tunnel_path_ext_append(mt, rpath));
+
+ if (NULL != rpath->frp_label_stack)
+ {
+ fib_path_ext_t path_ext;
+ int i = 0;
+
+ fib_path_ext_init(&path_ext, mt->mt_path_list, rpath);
+
+ while (i < vec_len(mt->mt_path_exts) &&
+ (fib_path_ext_cmp(&mt->mt_path_exts[i], rpath) < 0))
+ {
+ i++;
+ }
+
+ vec_insert_elts(mt->mt_path_exts, &path_ext, 1, i);
+ }
+}
+
+void
+vnet_mpls_tunnel_path_add (u32 sw_if_index,
+ fib_route_path_t *rpaths)
+{
+ mpls_tunnel_t *mt;
+ u32 mti;
+
+ mt = mpls_tunnel_get_from_sw_if_index(sw_if_index);
+
+ if (NULL == mt)
+ return;
+
+ mti = mt - mpls_tunnel_pool;
+