#define foreach_lisp_gpe_tx_next \
_(DROP, "error-drop") \
- _(IP4_LOOKUP, "ip4-lookup")
+ _(IP4_LOOKUP, "ip4-lookup") \
+ _(IP6_LOOKUP, "ip6-lookup")
typedef enum
{
return s;
}
+always_inline void
+get_one_tunnel_inline (lisp_gpe_main_t * lgm, vlib_buffer_t * b0,
+ lisp_gpe_tunnel_t ** t0, u8 is_v4)
+{
+ u32 adj_index0, tunnel_index0;
+ ip_adjacency_t * adj0;
+
+ /* Get adjacency and from it the tunnel_index */
+ adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
+
+ if (is_v4)
+ adj0 = ip_get_adjacency (lgm->lm4, adj_index0);
+ else
+ adj0 = ip_get_adjacency (lgm->lm6, adj_index0);
+
+ tunnel_index0 = adj0->rewrite_header.node_index;
+ t0[0] = pool_elt_at_index(lgm->tunnels, tunnel_index0);
+
+ ASSERT(t0[0] != 0);
+}
+
+always_inline void
+encap_one_inline (lisp_gpe_main_t * lgm, vlib_buffer_t * b0,
+ lisp_gpe_tunnel_t * t0, u32 * next0, u8 is_v4)
+{
+ ASSERT(sizeof(ip4_udp_lisp_gpe_header_t) == 36);
+ ASSERT(sizeof(ip6_udp_lisp_gpe_header_t) == 56);
+
+ if (is_v4)
+ {
+ ip_udp_encap_one (lgm->vlib_main, b0, t0->rewrite, 36, 1);
+ next0[0] = LISP_GPE_TX_NEXT_IP4_LOOKUP;
+
+ }
+ else
+ {
+ ip_udp_encap_one (lgm->vlib_main, b0, t0->rewrite, 56, 0);
+ next0[0] = LISP_GPE_TX_NEXT_IP6_LOOKUP;
+ }
+}
+
+always_inline void
+get_two_tunnels_inline (lisp_gpe_main_t * lgm, vlib_buffer_t * b0,
+ vlib_buffer_t * b1, lisp_gpe_tunnel_t ** t0,
+ lisp_gpe_tunnel_t ** t1, u8 is_v4)
+{
+ u32 adj_index0, adj_index1, tunnel_index0, tunnel_index1;
+ ip_adjacency_t * adj0, * adj1;
+
+ /* Get adjacency and from it the tunnel_index */
+ adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
+ adj_index1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
+
+ if (is_v4)
+ {
+ adj0 = ip_get_adjacency (lgm->lm4, adj_index0);
+ adj1 = ip_get_adjacency (lgm->lm4, adj_index1);
+ }
+ else
+ {
+ adj0 = ip_get_adjacency (lgm->lm6, adj_index0);
+ adj1 = ip_get_adjacency (lgm->lm6, adj_index1);
+ }
+
+ tunnel_index0 = adj0->rewrite_header.node_index;
+ tunnel_index1 = adj1->rewrite_header.node_index;
+
+ t0[0] = pool_elt_at_index(lgm->tunnels, tunnel_index0);
+ t1[0] = pool_elt_at_index(lgm->tunnels, tunnel_index1);
+
+ ASSERT(t0[0] != 0);
+ ASSERT(t1[0] != 0);
+}
+
+always_inline void
+encap_two_inline (lisp_gpe_main_t * lgm, vlib_buffer_t * b0, vlib_buffer_t * b1,
+ lisp_gpe_tunnel_t * t0, lisp_gpe_tunnel_t * t1, u32 * next0,
+ u32 * next1, u8 is_v4)
+{
+ ASSERT(sizeof(ip4_udp_lisp_gpe_header_t) == 36);
+ ASSERT(sizeof(ip6_udp_lisp_gpe_header_t) == 56);
+
+ if (is_v4)
+ {
+ ip_udp_encap_one (lgm->vlib_main, b0, t0->rewrite, 36, 1);
+ ip_udp_encap_one (lgm->vlib_main, b1, t1->rewrite, 36, 1);
+ next0[0] = next1[0] = LISP_GPE_TX_NEXT_IP4_LOOKUP;
+ }
+ else
+ {
+ ip_udp_encap_one (lgm->vlib_main, b0, t0->rewrite, 56, 0);
+ ip_udp_encap_one (lgm->vlib_main, b1, t1->rewrite, 56, 0);
+ next0[0] = next1[0] = LISP_GPE_TX_NEXT_IP6_LOOKUP;
+ }
+}
+
+#define is_v4_packet(_h) ((*(u8*) _h) & 0xF0) == 0x40
+
static uword
lisp_gpe_interface_tx (vlib_main_t * vm, vlib_node_runtime_t * node,
vlib_frame_t * from_frame)
u32 bi0, bi1;
vlib_buffer_t * b0, * b1;
u32 next0, next1;
- u32 adj_index0, adj_index1, tunnel_index0, tunnel_index1;
- ip_adjacency_t * adj0, * adj1;
- lisp_gpe_tunnel_t * t0, * t1;
+ lisp_gpe_tunnel_t * t0 = 0, * t1 = 0;
+ u8 is_v4_eid0, is_v4_eid1;
next0 = next1 = LISP_GPE_TX_NEXT_IP4_LOOKUP;
b0 = vlib_get_buffer (vm, bi0);
b1 = vlib_get_buffer (vm, bi1);
- /* Get adjacency and from it the tunnel_index */
- adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
- adj_index1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
+ is_v4_eid0 = is_v4_packet(vlib_buffer_get_current (b0));
+ is_v4_eid1 = is_v4_packet(vlib_buffer_get_current (b1));
- adj0 = ip_get_adjacency (lgm->lookup_main, adj_index0);
- adj1 = ip_get_adjacency (lgm->lookup_main, adj_index1);
-
- tunnel_index0 = adj0->rewrite_header.node_index;
- tunnel_index1 = adj1->rewrite_header.node_index;
-
- t0 = pool_elt_at_index (lgm->tunnels, tunnel_index0);
- t1 = pool_elt_at_index (lgm->tunnels, tunnel_index1);
-
- ASSERT(t0 != 0);
- ASSERT(t1 != 0);
+ if (PREDICT_TRUE(is_v4_eid0 == is_v4_eid1))
+ {
+ get_two_tunnels_inline (lgm, b0, b1, &t0, &t1,
+ is_v4_eid0 ? 1 : 0);
+ }
+ else
+ {
+ get_one_tunnel_inline (lgm, b0, &t0, is_v4_eid0 ? 1 : 0);
+ get_one_tunnel_inline (lgm, b1, &t1, is_v4_eid1 ? 1 : 0);
+ }
- ASSERT (sizeof(ip4_udp_lisp_gpe_header_t) == 36);
- ip4_udp_encap_two (vm, b0, b1, t0->rewrite, t1->rewrite, 36);
+ if (PREDICT_TRUE(
+ ip_addr_version(&t0->dst) == ip_addr_version(&t1->dst)))
+ {
+ encap_two_inline (lgm, b0, b1, t0, t1, &next0, &next1,
+ ip_addr_version(&t0->dst) == IP4 ? 1 : 0);
+ }
+ else
+ {
+ encap_one_inline (lgm, b0, t0, &next0,
+ ip_addr_version(&t0->dst) == IP4 ? 1 : 0);
+ encap_one_inline (lgm, b1, t1, &next1,
+ ip_addr_version(&t1->dst) == IP4 ? 1 : 0);
+ }
/* Reset to look up tunnel partner in the configured FIB */
vnet_buffer(b0)->sw_if_index[VLIB_TX] = t0->encap_fib_index;
while (n_left_from > 0 && n_left_to_next > 0)
{
vlib_buffer_t * b0;
- u32 bi0, adj_index0, tunnel_index0;
- u32 next0 = LISP_GPE_TX_NEXT_IP4_LOOKUP;
+ u32 bi0, next0 = LISP_GPE_TX_NEXT_IP4_LOOKUP;
lisp_gpe_tunnel_t * t0 = 0;
- ip_adjacency_t * adj0;
+ u8 is_v4_0;
bi0 = from[0];
to_next[0] = bi0;
b0 = vlib_get_buffer (vm, bi0);
- /* Get adjacency and from it the tunnel_index */
- adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
- adj0 = ip_get_adjacency (lgm->lookup_main, adj_index0);
-
- tunnel_index0 = adj0->rewrite_header.node_index;
- t0 = pool_elt_at_index (lgm->tunnels, tunnel_index0);
+ is_v4_0 = is_v4_packet(vlib_buffer_get_current (b0));
+ get_one_tunnel_inline (lgm, b0, &t0, is_v4_0 ? 1 : 0);
- ASSERT(t0 != 0);
-
- ASSERT (sizeof(ip4_udp_lisp_gpe_header_t) == 36);
- ip4_udp_encap_one (vm, b0, t0->rewrite, 36);
+ encap_one_inline (lgm, b0, t0, &next0,
+ ip_addr_version(&t0->dst) == IP4 ? 1 : 0);
/* Reset to look up tunnel partner in the configured FIB */
vnet_buffer(b0)->sw_if_index[VLIB_TX] = t0->encap_fib_index;
a.dst_address = addr;
a.flags |= is_add ? IP4_ROUTE_FLAG_ADD : IP4_ROUTE_FLAG_DEL;
a.add_adj = add_adj;
- a.n_add_adj = 1;
+ a.n_add_adj = is_add ? 1 : 0;
+
ip4_add_del_route (im4, &a);
if (is_add)
a.dst_address = addr;
a.flags |= is_add ? IP6_ROUTE_FLAG_ADD : IP6_ROUTE_FLAG_DEL;
a.add_adj = add_adj;
- a.n_add_adj = 1;
+ a.n_add_adj = is_add ? 1 : 0;
ip6_add_del_route (im6, &a);
adj.n_adj = 1;
adj.explicit_fib_index = ~0;
- adj.lookup_next_index = lgm->ip4_lookup_next_lgpe_ip4_lookup;
+ adj.lookup_next_index = is_v4 ? lgm->ip4_lookup_next_lgpe_ip4_lookup :
+ lgm->ip6_lookup_next_lgpe_ip6_lookup;
/* default route has tunnel_index ~0 */
adj.rewrite_header.sw_if_index = ~0;
}
}
-void
+int
vnet_lisp_gpe_add_del_iface (vnet_lisp_gpe_add_del_iface_args_t * a,
u32 * hw_if_indexp)
{
lisp_gpe_main_t * lgm = &lisp_gpe_main;
vnet_main_t * vnm = lgm->vnet_main;
vnet_hw_interface_t * hi;
- u32 hw_if_index = ~0, lookup_next_index, flen;
+ u32 hw_if_index = ~0, lookup_next_index4, lookup_next_index6, flen;
uword * hip, * vni;
+ if (vnet_lisp_gpe_enable_disable_status() == 0)
+ {
+ clib_warning ("LISP is disabled!");
+ return VNET_API_ERROR_LISP_DISABLED;
+ }
+
hip = hash_get(lgm->lisp_gpe_hw_if_index_by_table_id, a->table_id);
if (a->is_add)
if (hip)
{
clib_warning ("Interface for vrf %d already exists", a->table_id);
- return;
+ return -1;
}
/* create hw lisp_gpeX iface if needed, otherwise reuse existing */
hash_set(lgm->tunnel_term_sw_if_index_by_vni, a->vni, hi->sw_if_index);
hash_set(lgm->vni_by_tunnel_term_sw_if_index, hi->sw_if_index, a->vni);
- /* set ingress arc from lgpe_ip4_lookup */
- lookup_next_index = vlib_node_add_next (lgm->vlib_main,
- lgpe_ip4_lookup_node.index,
- hi->output_node_index);
+ /* set ingress arc from lgpe_ipX_lookup */
+ lookup_next_index4 = vlib_node_add_next (lgm->vlib_main,
+ lgpe_ip4_lookup_node.index,
+ hi->output_node_index);
+ lookup_next_index6 = vlib_node_add_next (lgm->vlib_main,
+ lgpe_ip6_lookup_node.index,
+ hi->output_node_index);
hash_set(lgm->lgpe_ip4_lookup_next_index_by_table_id, a->table_id,
- lookup_next_index);
+ lookup_next_index4);
+ hash_set(lgm->lgpe_ip6_lookup_next_index_by_table_id, a->table_id,
+ lookup_next_index6);
/* insert default routes that point to lgpe-ipx-lookup */
add_del_lisp_gpe_default_route (a->table_id, /* is_v4 */1, 1);
if (hip == 0)
{
clib_warning("The interface for vrf %d doesn't exist", a->table_id);
- return;
+ return -1;
}
hi = vnet_get_hw_interface (vnm, hip[0]);
add_del_lisp_gpe_default_route (a->table_id, /* is_v4 */1, 0);
add_del_lisp_gpe_default_route (a->table_id, /* is_v4 */0, 0);
}
+
+ return 0;
}
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;
vnet_lisp_gpe_add_del_iface_args_t _a, * a = &_a;
a->is_add = is_add;
a->table_id = table_id;
- vnet_lisp_gpe_add_del_iface (a, 0);
- return 0;
+ rv = vnet_lisp_gpe_add_del_iface (a, 0);
+ if (0 != rv)
+ {
+ error = clib_error_return(0, "failed to %s gpe iface!",
+ is_add ? "add" : "delete");
+ }
+
+ return error;
}
VLIB_CLI_COMMAND (add_del_lisp_gpe_iface_command, static) = {