#include <vnet/ip/udp.h>
#include <vnet/ethernet/ethernet.h>
#include <vnet/lisp-gpe/lisp_gpe.h>
+#include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h>
+#include <vnet/lisp-gpe/lisp_gpe_tenant.h>
+#include <vnet/lisp-gpe/lisp_gpe_adjacency.h>
#include <vnet/adj/adj.h>
#include <vnet/fib/fib_table.h>
#include <vnet/fib/ip4_fib.h>
#include <vnet/fib/ip6_fib.h>
+#include <vnet/lisp-cp/lisp_cp_dpo.h>
+
+/**
+ * @brief The VLIB node arc/edge from the interface's TX node, to the L2
+ * load-balanceing node. Which is where all packets go
+ */
+static uword l2_arc_to_lb;
#define foreach_lisp_gpe_tx_next \
_(DROP, "error-drop") \
.format_device_name = format_lisp_gpe_name,
.format_tx_trace = format_lisp_gpe_tx_trace,
.tx_function = lisp_gpe_interface_tx,
- .no_flatten_output_chains = 1,
};
/* *INDENT-ON* */
-static uword
-dummy_set_rewrite (vnet_main_t * vnm, u32 sw_if_index, u32 l3_type,
- void *dst_address, void *rewrite, uword max_rewrite_bytes)
-{
- return 0;
-}
-
u8 *
format_lisp_gpe_header_with_length (u8 * s, va_list * args)
{
VNET_HW_INTERFACE_CLASS (lisp_gpe_hw_class) = {
.name = "LISP_GPE",
.format_header = format_lisp_gpe_header_with_length,
- .set_rewrite = dummy_set_rewrite,
+ .build_rewrite = lisp_gpe_build_rewrite,
+ .update_adjacency = lisp_gpe_update_adjacency,
};
/* *INDENT-ON* */
-static void
-add_del_lisp_gpe_default_route (u32 table_id, fib_protocol_t proto, u8 is_add)
-{
- fib_prefix_t prefix = {
- .fp_proto = proto,
- };
- u32 fib_index;
-
- if (is_add)
- {
- /*
- * Add a deafult route that results in a control plane punt DPO
- */
- dpo_id_t cp_punt = DPO_NULL;
-
- dpo_set (&cp_punt, DPO_LISP_CP, fib_proto_to_dpo (proto), proto);
-
- fib_index =
- fib_table_find_or_create_and_lock (prefix.fp_proto, table_id);
- fib_table_entry_special_dpo_add (fib_index, &prefix, FIB_SOURCE_LISP,
- FIB_ENTRY_FLAG_EXCLUSIVE, &cp_punt);
- dpo_unlock (&cp_punt);
- }
- else
- {
- fib_index = fib_table_find (prefix.fp_proto, table_id);
- fib_table_entry_special_remove (fib_index, &prefix, FIB_SOURCE_LISP);
- fib_table_unlock (fib_index, prefix.fp_proto);
- }
-}
-
-void
-lisp_gpe_iface_set_table (u32 sw_if_index, u32 table_id)
-{
- fib_node_index_t fib_index;
-
- fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id);
- vec_validate (ip4_main.fib_index_by_sw_if_index, sw_if_index);
- ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
- ip4_sw_interface_enable_disable (sw_if_index, 1);
-
- fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, table_id);
- vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index);
- ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
- ip6_sw_interface_enable_disable (sw_if_index, 1);
-}
-
-#define foreach_l2_lisp_gpe_tx_next \
- _(DROP, "error-drop") \
- _(IP4_LOOKUP, "ip4-lookup") \
- _(IP6_LOOKUP, "ip6-lookup") \
- _(LISP_CP_LOOKUP, "lisp-cp-lookup")
-
-typedef enum
-{
-#define _(sym,str) L2_LISP_GPE_TX_NEXT_##sym,
- foreach_l2_lisp_gpe_tx_next
-#undef _
- L2_LISP_GPE_TX_N_NEXT,
-} l2_lisp_gpe_tx_next_t;
typedef struct
{
- u32 tunnel_index;
+ u32 lb_index;
} l2_lisp_gpe_tx_trace_t;
-u8 *
+static u8 *
format_l2_lisp_gpe_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 *);
l2_lisp_gpe_tx_trace_t *t = va_arg (*args, l2_lisp_gpe_tx_trace_t *);
- s = format (s, "L2-LISP-GPE-TX: tunnel %d", t->tunnel_index);
+ s = format (s, "L2-LISP-GPE-TX: load-balance %d", t->lb_index);
return s;
}
-always_inline void
-l2_process_tunnel_action (vlib_buffer_t * b0, u8 action, u32 * next0)
-{
- if (LISP_SEND_MAP_REQUEST == action)
- {
- next0[0] = L2_LISP_GPE_TX_NEXT_LISP_CP_LOOKUP;
- vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_MAC;
- }
- else
- {
- next0[0] = L2_LISP_GPE_TX_NEXT_DROP;
- }
-}
-
-always_inline u32
-ip_flow_hash (void *data)
-{
- ip4_header_t *iph = (ip4_header_t *) data;
-
- if ((iph->ip_version_and_header_length & 0xF0) == 0x40)
- return ip4_compute_flow_hash (iph, IP_FLOW_HASH_DEFAULT);
- else
- return ip6_compute_flow_hash ((ip6_header_t *) iph, IP_FLOW_HASH_DEFAULT);
-}
-
-always_inline u32
-l2_flow_hash (vlib_buffer_t * b0)
-{
- ethernet_header_t *eh;
- u64 a, b, c;
- uword is_ip, eh_size;
- u16 eh_type;
-
- eh = vlib_buffer_get_current (b0);
- eh_type = clib_net_to_host_u16 (eh->type);
- eh_size = ethernet_buffer_header_size (b0);
-
- is_ip = (eh_type == ETHERNET_TYPE_IP4 || eh_type == ETHERNET_TYPE_IP6);
-
- /* since we have 2 cache lines, use them */
- if (is_ip)
- a = ip_flow_hash ((u8 *) vlib_buffer_get_current (b0) + eh_size);
- else
- a = eh->type;
-
- b = mac_to_u64 ((u8 *) eh->dst_address);
- c = mac_to_u64 ((u8 *) eh->src_address);
- hash_mix64 (a, b, c);
-
- return (u32) c;
-}
-
-/* always_inline void */
-/* l2_process_one (lisp_gpe_main_t * lgm, vlib_buffer_t * b0, u32 ti0, */
-/* u32 * next0) */
-/* { */
-/* lisp_gpe_tunnel_t *t0; */
-
-/* t0 = pool_elt_at_index (lgm->tunnels, ti0); */
-/* ASSERT (0 != t0); */
-
-/* if (PREDICT_TRUE (LISP_NO_ACTION == t0->action)) */
-/* { */
-/* /\* compute 'flow' hash *\/ */
-/* if (PREDICT_TRUE (t0->sub_tunnels_lbv_count > 1)) */
-/* vnet_buffer (b0)->ip.flow_hash = l2_flow_hash (b0); */
-/* encap_one_inline (lgm, b0, t0, next0); */
-/* } */
-/* else */
-/* { */
-/* l2_process_tunnel_action (b0, t0->action, next0); */
-/* } */
-/* } */
-
-/* always_inline void */
-/* l2_process_two (lisp_gpe_main_t * lgm, vlib_buffer_t * b0, vlib_buffer_t * b1, */
-/* u32 ti0, u32 ti1, u32 * next0, u32 * next1) */
-/* { */
-/* lisp_gpe_tunnel_t *t0, *t1; */
-
-/* t0 = pool_elt_at_index (lgm->tunnels, ti0); */
-/* t1 = pool_elt_at_index (lgm->tunnels, ti1); */
-
-/* ASSERT (0 != t0 && 0 != t1); */
-
-/* if (PREDICT_TRUE (LISP_NO_ACTION == t0->action */
-/* && LISP_NO_ACTION == t1->action)) */
-/* { */
-/* if (PREDICT_TRUE (t0->sub_tunnels_lbv_count > 1)) */
-/* vnet_buffer (b0)->ip.flow_hash = l2_flow_hash (b0); */
-/* if (PREDICT_TRUE (t1->sub_tunnels_lbv_count > 1)) */
-/* vnet_buffer (b1)->ip.flow_hash = l2_flow_hash (b1); */
-/* encap_two_inline (lgm, b0, b1, t0, t1, next0, next1); */
-/* } */
-/* else */
-/* { */
-/* if (LISP_NO_ACTION == t0->action) */
-/* { */
-/* if (PREDICT_TRUE (t0->sub_tunnels_lbv_count > 1)) */
-/* vnet_buffer (b0)->ip.flow_hash = l2_flow_hash (b0); */
-/* encap_one_inline (lgm, b0, t0, next0); */
-/* l2_process_tunnel_action (b1, t1->action, next1); */
-/* } */
-/* else if (LISP_NO_ACTION == t1->action) */
-/* { */
-/* if (PREDICT_TRUE (t1->sub_tunnels_lbv_count > 1)) */
-/* vnet_buffer (b1)->ip.flow_hash = l2_flow_hash (b1); */
-/* encap_one_inline (lgm, b1, t1, next1); */
-/* l2_process_tunnel_action (b0, t0->action, next0); */
-/* } */
-/* else */
-/* { */
-/* l2_process_tunnel_action (b0, t0->action, next0); */
-/* l2_process_tunnel_action (b1, t1->action, next1); */
-/* } */
-/* } */
-/* } */
-
/**
* @brief LISP-GPE interface TX (encap) function for L2 overlays.
* @node l2_lisp_gpe_interface_tx
vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
- while (n_left_from >= 4 && n_left_to_next >= 2)
- {
- u32 bi0, bi1;
- vlib_buffer_t *b0, *b1;
- u32 next0, next1;
- lisp_gpe_tunnel_t *t0 = 0, *t1 = 0;
- // ethernet_header_t *e0, *e1;
-
- next0 = next1 = L2_LISP_GPE_TX_NEXT_LISP_CP_LOOKUP;
-
- /* Prefetch next iteration. */
- {
- vlib_buffer_t *p2, *p3;
-
- p2 = vlib_get_buffer (vm, from[2]);
- p3 = vlib_get_buffer (vm, from[3]);
-
- vlib_prefetch_buffer_header (p2, LOAD);
- vlib_prefetch_buffer_header (p3, LOAD);
-
- CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
- CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
- }
-
- bi0 = from[0];
- bi1 = from[1];
- to_next[0] = bi0;
- to_next[1] = bi1;
- from += 2;
- to_next += 2;
- n_left_to_next -= 2;
- n_left_from -= 2;
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
-
- /* e0 = vlib_buffer_get_current (b0); */
- /* e1 = vlib_buffer_get_current (b1); */
-
- /* lookup dst + src mac */
- /* ti0 = lisp_l2_fib_lookup (lgm, vnet_buffer (b0)->l2.bd_index, */
- /* e0->src_address, e0->dst_address); */
- /* ti1 = lisp_l2_fib_lookup (lgm, vnet_buffer (b1)->l2.bd_index, */
- /* e1->src_address, e1->dst_address); */
-
- /* if (PREDICT_TRUE ((u32) ~ 0 != ti0) && (u32) ~ 0 != ti1) */
- /* { */
- /* /\* process both tunnels *\/ */
- /* l2_process_two (lgm, b0, b1, ti0, ti1, &next0, &next1); */
- /* } */
- /* else */
- /* { */
- /* if ((u32) ~ 0 != ti0) */
- /* { */
- /* /\* process tunnel for b0 *\/ */
- /* l2_process_one (lgm, b0, ti0, &next0); */
-
- /* /\* no tunnel found for b1, send to control plane *\/ */
- /* next1 = L2_LISP_GPE_TX_NEXT_LISP_CP_LOOKUP; */
- /* vnet_buffer (b1)->lisp.overlay_afi = LISP_AFI_MAC; */
- /* } */
- /* else if ((u32) ~ 0 != ti1) */
- /* { */
- /* /\* process tunnel for b1 *\/ */
- /* l2_process_one (lgm, b1, ti1, &next1); */
-
- /* /\* no tunnel found b0, send to control plane *\/ */
- /* next0 = L2_LISP_GPE_TX_NEXT_LISP_CP_LOOKUP; */
- /* vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_MAC; */
- /* } */
- /* else */
- /* { */
- /* /\* no tunnels found *\/ */
- /* next0 = L2_LISP_GPE_TX_NEXT_LISP_CP_LOOKUP; */
- /* vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_MAC; */
- /* next1 = L2_LISP_GPE_TX_NEXT_LISP_CP_LOOKUP; */
- /* vnet_buffer (b1)->lisp.overlay_afi = LISP_AFI_MAC; */
- /* } */
- /* } */
-
- if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
- {
- l2_lisp_gpe_tx_trace_t *tr = vlib_add_trace (vm, node, b0,
- sizeof (*tr));
- tr->tunnel_index = t0 - lgm->tunnels;
- }
- if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
- {
- l2_lisp_gpe_tx_trace_t *tr = vlib_add_trace (vm, node, b1,
- sizeof (*tr));
- tr->tunnel_index = t1 - lgm->tunnels;
- }
-
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
- n_left_to_next, bi0, bi1, next0,
- next1);
- }
-
while (n_left_from > 0 && n_left_to_next > 0)
{
vlib_buffer_t *b0;
- u32 bi0, ti0, next0 = L2_LISP_GPE_TX_NEXT_LISP_CP_LOOKUP;
+ u32 bi0, lbi0;
ethernet_header_t *e0;
bi0 = from[0];
b0 = vlib_get_buffer (vm, bi0);
e0 = vlib_buffer_get_current (b0);
+ vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_MAC;
+
/* lookup dst + src mac */
- ti0 = lisp_l2_fib_lookup (lgm, vnet_buffer (b0)->l2.bd_index,
- e0->src_address, e0->dst_address);
-
- /* if (PREDICT_TRUE ((u32) ~ 0 != ti0)) */
- /* { */
- /* l2_process_one (lgm, b0, ti0, &next0); */
- /* } */
- /* else */
- /* { */
- /* /\* no tunnel found send to control plane *\/ */
- /* next0 = L2_LISP_GPE_TX_NEXT_LISP_CP_LOOKUP; */
- /* vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_MAC; */
- /* } */
+ lbi0 = lisp_l2_fib_lookup (lgm, vnet_buffer (b0)->l2.bd_index,
+ e0->src_address, e0->dst_address);
+ vnet_buffer (b0)->ip.adj_index[VLIB_TX] = lbi0;
+
if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
{
l2_lisp_gpe_tx_trace_t *tr = vlib_add_trace (vm, node, b0,
sizeof (*tr));
- tr->tunnel_index = ti0 ? ti0 : ~0;
+ tr->lb_index = lbi0;
}
vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
- n_left_to_next, bi0, next0);
+ n_left_to_next, bi0, l2_arc_to_lb);
}
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
VNET_DEVICE_CLASS (l2_lisp_gpe_device_class,static) = {
.name = "L2_LISP_GPE",
.format_device_name = format_l2_lisp_gpe_name,
- .format_tx_trace = format_lisp_gpe_tx_trace,
+ .format_tx_trace = format_l2_lisp_gpe_tx_trace,
.tx_function = l2_lisp_gpe_interface_tx,
- .no_flatten_output_chains = 1,
};
/* *INDENT-ON* */
static vnet_hw_interface_t *
-create_lisp_gpe_iface (lisp_gpe_main_t * lgm, u32 vni, u32 dp_table,
+lisp_gpe_create_iface (lisp_gpe_main_t * lgm, u32 vni, u32 dp_table,
vnet_device_class_t * dev_class,
tunnel_lookup_t * tuns)
{
}
static void
-remove_lisp_gpe_iface (lisp_gpe_main_t * lgm, u32 hi_index, u32 dp_table,
+lisp_gpe_remove_iface (lisp_gpe_main_t * lgm, u32 hi_index, u32 dp_table,
tunnel_lookup_t * tuns)
{
vnet_main_t *vnm = lgm->vnet_main;
hash_unset (tuns->vni_by_sw_if_index, hi->sw_if_index);
}
+static void
+lisp_gpe_iface_set_table (u32 sw_if_index, u32 table_id)
+{
+ fib_node_index_t fib_index;
+
+ fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id);
+ vec_validate (ip4_main.fib_index_by_sw_if_index, sw_if_index);
+ ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
+ ip4_sw_interface_enable_disable (sw_if_index, 1);
+
+ fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, table_id);
+ vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index);
+ ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
+ ip6_sw_interface_enable_disable (sw_if_index, 1);
+}
+
+static void
+lisp_gpe_tenant_del_default_routes (u32 table_id)
+{
+ fib_protocol_t proto;
+
+ FOR_EACH_FIB_IP_PROTOCOL (proto)
+ {
+ fib_prefix_t prefix = {
+ .fp_proto = proto,
+ };
+ u32 fib_index;
+
+ fib_index = fib_table_find (prefix.fp_proto, table_id);
+ fib_table_entry_special_remove (fib_index, &prefix, FIB_SOURCE_LISP);
+ fib_table_unlock (fib_index, prefix.fp_proto);
+ }
+}
+
+static void
+lisp_gpe_tenant_add_default_routes (u32 table_id)
+{
+ fib_protocol_t proto;
+
+ FOR_EACH_FIB_IP_PROTOCOL (proto)
+ {
+ fib_prefix_t prefix = {
+ .fp_proto = proto,
+ };
+ u32 fib_index;
+
+ /*
+ * Add a deafult route that results in a control plane punt DPO
+ */
+ fib_index = fib_table_find_or_create_and_lock (prefix.fp_proto, table_id);
+ fib_table_entry_special_dpo_add (fib_index, &prefix, FIB_SOURCE_LISP,
+ FIB_ENTRY_FLAG_EXCLUSIVE,
+ lisp_cp_dpo_get (fib_proto_to_dpo
+ (proto)));
+ }
+}
+
+
/**
* @brief Add/del LISP-GPE L3 interface.
*
*
* @return number of vectors in frame.
*/
-static int
-lisp_gpe_add_del_l3_iface (lisp_gpe_main_t * lgm,
- vnet_lisp_gpe_add_del_iface_args_t * a)
+u32
+lisp_gpe_add_l3_iface (lisp_gpe_main_t * lgm, u32 vni, u32 table_id)
{
vnet_main_t *vnm = lgm->vnet_main;
tunnel_lookup_t *l3_ifaces = &lgm->l3_ifaces;
vnet_hw_interface_t *hi;
uword *hip, *si;
- hip = hash_get (l3_ifaces->hw_if_index_by_dp_table, a->table_id);
+ hip = hash_get (l3_ifaces->hw_if_index_by_dp_table, table_id);
- if (a->is_add)
+ if (hip)
{
- if (hip)
- {
- clib_warning ("vrf %d already mapped to a vni", a->table_id);
- return -1;
- }
+ clib_warning ("vrf %d already mapped to a vni", table_id);
+ return ~0;
+ }
- si = hash_get (l3_ifaces->sw_if_index_by_vni, a->vni);
- if (si)
- {
- clib_warning ("Interface for vni %d already exists", a->vni);
- return -1;
- }
+ si = hash_get (l3_ifaces->sw_if_index_by_vni, vni);
+
+ if (si)
+ {
+ clib_warning ("Interface for vni %d already exists", vni);
+ }
- /* create lisp iface and populate tunnel tables */
- hi = create_lisp_gpe_iface (lgm, a->vni, a->table_id,
- &lisp_gpe_device_class, l3_ifaces);
+ /* create lisp iface and populate tunnel tables */
+ hi = lisp_gpe_create_iface (lgm, vni, table_id,
+ &lisp_gpe_device_class, l3_ifaces);
- /* insert default routes that point to lisp-cp lookup */
- lisp_gpe_iface_set_table (hi->sw_if_index, a->table_id);
- add_del_lisp_gpe_default_route (a->table_id, FIB_PROTOCOL_IP4, 1);
- add_del_lisp_gpe_default_route (a->table_id, FIB_PROTOCOL_IP6, 1);
+ /* insert default routes that point to lisp-cp lookup */
+ lisp_gpe_iface_set_table (hi->sw_if_index, table_id);
+ lisp_gpe_tenant_add_default_routes (table_id);
- /* enable interface */
- vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
- VNET_SW_INTERFACE_FLAG_ADMIN_UP);
- vnet_hw_interface_set_flags (vnm, hi->hw_if_index,
- VNET_HW_INTERFACE_FLAG_LINK_UP);
- }
- else
- {
- if (hip == 0)
- {
- clib_warning ("The interface for vrf %d doesn't exist",
- a->table_id);
- return -1;
- }
+ /* enable interface */
+ vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
+ VNET_SW_INTERFACE_FLAG_ADMIN_UP);
+ vnet_hw_interface_set_flags (vnm, hi->hw_if_index,
+ VNET_HW_INTERFACE_FLAG_LINK_UP);
- hi = vnet_get_hw_interface (vnm, hip[0]);
+ return (hi->sw_if_index);
+}
+
+void
+lisp_gpe_del_l3_iface (lisp_gpe_main_t * lgm, u32 vni, u32 table_id)
+{
+ vnet_main_t *vnm = lgm->vnet_main;
+ tunnel_lookup_t *l3_ifaces = &lgm->l3_ifaces;
+ vnet_hw_interface_t *hi;
+ uword *hip;
- remove_lisp_gpe_iface (lgm, hip[0], a->table_id, &lgm->l3_ifaces);
+ hip = hash_get (l3_ifaces->hw_if_index_by_dp_table, table_id);
- /* unset default routes */
- ip4_sw_interface_enable_disable (hi->sw_if_index, 0);
- ip6_sw_interface_enable_disable (hi->sw_if_index, 0);
- add_del_lisp_gpe_default_route (a->table_id, FIB_PROTOCOL_IP4, 0);
- add_del_lisp_gpe_default_route (a->table_id, FIB_PROTOCOL_IP6, 0);
+ if (hip == 0)
+ {
+ clib_warning ("The interface for vrf %d doesn't exist", table_id);
+ return;
}
- return 0;
+ hi = vnet_get_hw_interface (vnm, hip[0]);
+
+ lisp_gpe_remove_iface (lgm, hip[0], table_id, &lgm->l3_ifaces);
+
+ /* unset default routes */
+ ip4_sw_interface_enable_disable (hi->sw_if_index, 0);
+ ip6_sw_interface_enable_disable (hi->sw_if_index, 0);
+ lisp_gpe_tenant_del_default_routes (table_id);
}
/**
*
* @return number of vectors in frame.
*/
-static int
-lisp_gpe_add_del_l2_iface (lisp_gpe_main_t * lgm,
- vnet_lisp_gpe_add_del_iface_args_t * a)
+u32
+lisp_gpe_add_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id)
{
vnet_main_t *vnm = lgm->vnet_main;
tunnel_lookup_t *l2_ifaces = &lgm->l2_ifaces;
uword *hip, *si;
u16 bd_index;
- bd_index = bd_find_or_add_bd_index (&bd_main, a->bd_id);
+ bd_index = bd_find_or_add_bd_index (&bd_main, bd_id);
hip = hash_get (l2_ifaces->hw_if_index_by_dp_table, bd_index);
- if (a->is_add)
+ if (hip)
{
- if (hip)
- {
- clib_warning ("bridge domain %d already mapped to a vni", a->bd_id);
- return -1;
- }
+ clib_warning ("bridge domain %d already mapped to a vni", bd_id);
+ return ~0;
+ }
- si = hash_get (l2_ifaces->sw_if_index_by_vni, a->vni);
- if (si)
- {
- clib_warning ("Interface for vni %d already exists", a->vni);
- return -1;
- }
+ si = hash_get (l2_ifaces->sw_if_index_by_vni, vni);
+ if (si)
+ {
+ clib_warning ("Interface for vni %d already exists", vni);
+ return ~0;
+ }
- /* create lisp iface and populate tunnel tables */
- hi = create_lisp_gpe_iface (lgm, a->vni, bd_index,
- &l2_lisp_gpe_device_class, &lgm->l2_ifaces);
+ /* create lisp iface and populate tunnel tables */
+ hi = lisp_gpe_create_iface (lgm, vni, bd_index,
+ &l2_lisp_gpe_device_class, &lgm->l2_ifaces);
- /* add iface to l2 bridge domain */
- set_int_l2_mode (lgm->vlib_main, vnm, MODE_L2_BRIDGE, hi->sw_if_index,
- bd_index, 0, 0, 0);
+ /* enable interface */
+ vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
+ VNET_SW_INTERFACE_FLAG_ADMIN_UP);
+ vnet_hw_interface_set_flags (vnm, hi->hw_if_index,
+ VNET_HW_INTERFACE_FLAG_LINK_UP);
- /* set egress arcs */
-#define _(sym,str) vlib_node_add_named_next_with_slot (vnm->vlib_main, \
- hi->tx_node_index, str, L2_LISP_GPE_TX_NEXT_##sym);
- foreach_l2_lisp_gpe_tx_next
-#undef _
- /* enable interface */
- vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
- VNET_SW_INTERFACE_FLAG_ADMIN_UP);
- vnet_hw_interface_set_flags (vnm, hi->hw_if_index,
- VNET_HW_INTERFACE_FLAG_LINK_UP);
- }
- else
- {
- if (hip == 0)
- {
- clib_warning ("The interface for bridge domain %d doesn't exist",
- a->bd_id);
- return -1;
- }
- remove_lisp_gpe_iface (lgm, hip[0], bd_index, &lgm->l2_ifaces);
- }
+ l2_arc_to_lb = vlib_node_add_named_next (vlib_get_main (),
+ hi->tx_node_index,
+ "l2-load-balance");
+
+ /* we're ready. add iface to l2 bridge domain */
+ set_int_l2_mode (lgm->vlib_main, vnm, MODE_L2_BRIDGE, hi->sw_if_index,
+ bd_index, 0, 0, 0);
- return 0;
+ return (hi->sw_if_index);
}
-/** Add/del L2 or L3 LISP-GPE interface. */
-int
-vnet_lisp_gpe_add_del_iface (vnet_lisp_gpe_add_del_iface_args_t * a,
- u32 * hw_if_indexp)
+/**
+ * @brief Add/del LISP-GPE L2 interface.
+ *
+ * Creates LISP-GPE interface, sets it in L2 mode in the appropriate
+ * bridge domain, sets egress arcs and enables it.
+ *
+ * @param[in] lgm Reference to @ref lisp_gpe_main_t.
+ * @param[in] a Parameters to create interface.
+ *
+ * @return number of vectors in frame.
+ */
+void
+lisp_gpe_del_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id)
{
- lisp_gpe_main_t *lgm = &lisp_gpe_main;
+ tunnel_lookup_t *l2_ifaces = &lgm->l2_ifaces;
+ u16 bd_index;
+ uword *hip;
- if (vnet_lisp_gpe_enable_disable_status () == 0)
+ bd_index = bd_find_or_add_bd_index (&bd_main, bd_id);
+ hip = hash_get (l2_ifaces->hw_if_index_by_dp_table, bd_index);
+
+ if (hip == 0)
{
- clib_warning ("LISP is disabled!");
- return VNET_API_ERROR_LISP_DISABLED;
+ clib_warning ("The interface for bridge domain %d doesn't exist",
+ bd_id);
+ return;
}
-
- if (!a->is_l2)
- return lisp_gpe_add_del_l3_iface (lgm, a);
- else
- return lisp_gpe_add_del_l2_iface (lgm, a);
+ lisp_gpe_remove_iface (lgm, hip[0], bd_index, &lgm->l2_ifaces);
}
static clib_error_t *
{
unformat_input_t _line_input, *line_input = &_line_input;
u8 is_add = 1;
- clib_error_t *error = 0;
- int rv = 0;
u32 table_id, vni, bd_id;
u8 vni_is_set = 0, vrf_is_set = 0, bd_index_is_set = 0;
- vnet_lisp_gpe_add_del_iface_args_t _a, *a = &_a;
+ if (vnet_lisp_gpe_enable_disable_status () == 0)
+ {
+ return clib_error_return (0, "LISP is disabled");
+ }
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
if (!vrf_is_set && !bd_index_is_set)
return clib_error_return (0, "vrf or bridge domain index must be set!");
- a->is_add = is_add;
- a->dp_table = vrf_is_set ? table_id : bd_id;
- a->vni = vni;
- a->is_l2 = bd_index_is_set;
-
- rv = vnet_lisp_gpe_add_del_iface (a, 0);
- if (0 != rv)
+ if (bd_index_is_set)
+ {
+ if (is_add)
+ {
+ if (~0 == lisp_gpe_tenant_l2_iface_add_or_lock (vni, bd_id))
+ return clib_error_return (0, "L2 interface not created");
+ }
+ else
+ lisp_gpe_tenant_l2_iface_unlock (vni);
+ }
+ else
{
- error = clib_error_return (0, "failed to %s gpe iface!",
- is_add ? "add" : "delete");
+ if (is_add)
+ {
+ if (~0 == lisp_gpe_tenant_l3_iface_add_or_lock (vni, table_id))
+ return clib_error_return (0, "L3 interface not created");
+ }
+ else
+ lisp_gpe_tenant_l3_iface_unlock (vni);
}
- return error;
+ return (NULL);
}
/* *INDENT-OFF* */