ipip: Multi-point interface
Type: feature plus fixes for gre Signed-off-by: Neale Ranns <nranns@cisco.com> Change-Id: I0eca5f94b8b8ea0fcfb058162cafea4491708db6
This commit is contained in:
Neale Ranns
committed by
Damjan Marion
parent
59ff918ea5
commit
14053c9dbd
@ -1546,7 +1546,7 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
|
|||||||
rv = ipip_add_tunnel (IPIP_TRANSPORT_IP4, ~0,
|
rv = ipip_add_tunnel (IPIP_TRANSPORT_IP4, ~0,
|
||||||
&a->local_ip, &a->remote_ip, 0,
|
&a->local_ip, &a->remote_ip, 0,
|
||||||
TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
|
TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
|
||||||
&sw_if_index);
|
TUNNEL_MODE_P2P, &sw_if_index);
|
||||||
|
|
||||||
if (rv == VNET_API_ERROR_IF_ALREADY_EXISTS)
|
if (rv == VNET_API_ERROR_IF_ALREADY_EXISTS)
|
||||||
{
|
{
|
||||||
|
@ -182,7 +182,7 @@ format_ip_adjacency (u8 * s, va_list * args)
|
|||||||
s = format (s, "\n flags:%U", format_adj_flags, adj->ia_flags);
|
s = format (s, "\n flags:%U", format_adj_flags, adj->ia_flags);
|
||||||
s = format (s, "\n counts:[%Ld:%Ld]", counts.packets, counts.bytes);
|
s = format (s, "\n counts:[%Ld:%Ld]", counts.packets, counts.bytes);
|
||||||
s = format (s, "\n locks:%d", adj->ia_node.fn_locks);
|
s = format (s, "\n locks:%d", adj->ia_node.fn_locks);
|
||||||
s = format(s, "\n delegates:\n ");
|
s = format(s, "\n delegates:");
|
||||||
s = adj_delegate_format(s, adj);
|
s = adj_delegate_format(s, adj);
|
||||||
|
|
||||||
s = format(s, "\n children:");
|
s = format(s, "\n children:");
|
||||||
|
@ -163,13 +163,13 @@ adj_delegate_format (u8* s, ip_adjacency_t *adj)
|
|||||||
{
|
{
|
||||||
if (ad_vfts[aed->ad_type].adv_format)
|
if (ad_vfts[aed->ad_type].adv_format)
|
||||||
{
|
{
|
||||||
s = format(s, "{");
|
s = format(s, "\n {");
|
||||||
s = ad_vfts[aed->ad_type].adv_format(aed, s);
|
s = ad_vfts[aed->ad_type].adv_format(aed, s);
|
||||||
s = format(s, "}");
|
s = format(s, "}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s = format(s, "{unknown delegate}");
|
s = format(s, "\n {unknown delegate}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,12 +513,11 @@ adj_nbr_midchain_update_rewrite (adj_index_t adj_index,
|
|||||||
* one time only update. since we don't support changing the tunnel
|
* one time only update. since we don't support changing the tunnel
|
||||||
* src,dst, this is all we need.
|
* src,dst, this is all we need.
|
||||||
*/
|
*/
|
||||||
ASSERT((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) ||
|
if (adj->lookup_next_index != IP_LOOKUP_NEXT_MIDCHAIN ||
|
||||||
(adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN) ||
|
adj->lookup_next_index != IP_LOOKUP_NEXT_MCAST_MIDCHAIN)
|
||||||
(adj->lookup_next_index == IP_LOOKUP_NEXT_MCAST) ||
|
{
|
||||||
(adj->lookup_next_index == IP_LOOKUP_NEXT_BCAST));
|
adj_midchain_setup(adj_index, fixup, fixup_data, flags);
|
||||||
|
}
|
||||||
adj_midchain_setup(adj_index, fixup, fixup_data, flags);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* update the rewrite with the workers paused.
|
* update the rewrite with the workers paused.
|
||||||
|
@ -907,15 +907,19 @@ adj_nbr_show (vlib_main_t * vm,
|
|||||||
vlib_cli_command_t * cmd)
|
vlib_cli_command_t * cmd)
|
||||||
{
|
{
|
||||||
adj_index_t ai = ADJ_INDEX_INVALID;
|
adj_index_t ai = ADJ_INDEX_INVALID;
|
||||||
|
ip46_address_t nh = ip46_address_initializer;
|
||||||
u32 sw_if_index = ~0;
|
u32 sw_if_index = ~0;
|
||||||
|
|
||||||
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
|
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
|
||||||
{
|
{
|
||||||
if (unformat (input, "%d", &ai))
|
if (unformat (input, "%U",
|
||||||
|
unformat_vnet_sw_interface, vnet_get_main(),
|
||||||
|
&sw_if_index))
|
||||||
;
|
;
|
||||||
else if (unformat (input, "%U",
|
else if (unformat (input, "%U",
|
||||||
unformat_vnet_sw_interface, vnet_get_main(),
|
unformat_ip46_address, &nh, IP46_TYPE_ANY))
|
||||||
&sw_if_index))
|
;
|
||||||
|
else if (unformat (input, "%d", &ai))
|
||||||
;
|
;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
@ -932,12 +936,24 @@ adj_nbr_show (vlib_main_t * vm,
|
|||||||
{
|
{
|
||||||
fib_protocol_t proto;
|
fib_protocol_t proto;
|
||||||
|
|
||||||
for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
|
if (ip46_address_is_zero(&nh))
|
||||||
{
|
{
|
||||||
adj_nbr_walk(sw_if_index, proto,
|
for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
|
||||||
adj_nbr_show_one,
|
{
|
||||||
vm);
|
adj_nbr_walk(sw_if_index, proto,
|
||||||
}
|
adj_nbr_show_one,
|
||||||
|
vm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
proto = (ip46_address_is_ip4(&nh) ?
|
||||||
|
FIB_PROTOCOL_IP4 :
|
||||||
|
FIB_PROTOCOL_IP6);
|
||||||
|
adj_nbr_walk_nh(sw_if_index, proto, &nh,
|
||||||
|
adj_nbr_show_one,
|
||||||
|
vm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1870,7 +1870,8 @@ fib_path_recursive_loop_detect (fib_node_index_t path_index,
|
|||||||
}
|
}
|
||||||
case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
|
case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
|
||||||
case FIB_PATH_TYPE_ATTACHED:
|
case FIB_PATH_TYPE_ATTACHED:
|
||||||
if (adj_recursive_loop_detect(path->fp_dpo.dpoi_index,
|
if (dpo_is_adj(&path->fp_dpo) &&
|
||||||
|
adj_recursive_loop_detect(path->fp_dpo.dpoi_index,
|
||||||
entry_indicies))
|
entry_indicies))
|
||||||
{
|
{
|
||||||
FIB_PATH_DBG(path, "recursive loop formed");
|
FIB_PATH_DBG(path, "recursive loop formed");
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include <vnet/vnet.h>
|
#include <vnet/vnet.h>
|
||||||
#include <vnet/gre/gre.h>
|
#include <vnet/gre/gre.h>
|
||||||
#include <vnet/adj/adj_midchain.h>
|
#include <vnet/adj/adj_midchain.h>
|
||||||
#include <vnet/nhrp/nhrp.h>
|
|
||||||
|
|
||||||
extern gre_main_t gre_main;
|
extern gre_main_t gre_main;
|
||||||
|
|
||||||
@ -331,10 +330,38 @@ gre_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai)
|
|||||||
gre_tunnel_stack (ai);
|
gre_tunnel_stack (ai);
|
||||||
}
|
}
|
||||||
|
|
||||||
static adj_walk_rc_t
|
adj_walk_rc_t
|
||||||
mgre_mk_complete_walk (adj_index_t ai, void *ctx)
|
mgre_mk_complete_walk (adj_index_t ai, void *data)
|
||||||
{
|
{
|
||||||
nhrp_entry_adj_stack (ctx, ai);
|
mgre_walk_ctx_t *ctx = data;
|
||||||
|
adj_midchain_fixup_t f;
|
||||||
|
|
||||||
|
f = (ctx->t->tunnel_dst.fp_proto == FIB_PROTOCOL_IP4 ?
|
||||||
|
gre4_fixup : gre6_fixup);
|
||||||
|
|
||||||
|
adj_nbr_midchain_update_rewrite
|
||||||
|
(ai, f, NULL, ADJ_FLAG_MIDCHAIN_IP_STACK,
|
||||||
|
gre_build_rewrite (vnet_get_main (),
|
||||||
|
ctx->t->sw_if_index,
|
||||||
|
adj_get_link_type (ai),
|
||||||
|
&nhrp_entry_get_nh (ctx->ne)->fp_addr));
|
||||||
|
|
||||||
|
nhrp_entry_adj_stack (ctx->ne, ai);
|
||||||
|
|
||||||
|
return (ADJ_WALK_RC_CONTINUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
adj_walk_rc_t
|
||||||
|
mgre_mk_incomplete_walk (adj_index_t ai, void *data)
|
||||||
|
{
|
||||||
|
gre_tunnel_t *t = data;
|
||||||
|
adj_midchain_fixup_t f;
|
||||||
|
|
||||||
|
f = (t->tunnel_dst.fp_proto == FIB_PROTOCOL_IP4 ? gre4_fixup : gre6_fixup);
|
||||||
|
|
||||||
|
adj_nbr_midchain_update_rewrite (ai, f, NULL, ADJ_FLAG_NONE, NULL);
|
||||||
|
|
||||||
|
adj_midchain_delegate_unstack (ai);
|
||||||
|
|
||||||
return (ADJ_WALK_RC_CONTINUE);
|
return (ADJ_WALK_RC_CONTINUE);
|
||||||
}
|
}
|
||||||
@ -346,20 +373,11 @@ mgre_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai)
|
|||||||
ip_adjacency_t *adj;
|
ip_adjacency_t *adj;
|
||||||
nhrp_entry_t *ne;
|
nhrp_entry_t *ne;
|
||||||
gre_tunnel_t *t;
|
gre_tunnel_t *t;
|
||||||
adj_flags_t af;
|
|
||||||
u8 is_ipv6;
|
|
||||||
u32 ti;
|
u32 ti;
|
||||||
|
|
||||||
adj = adj_get (ai);
|
adj = adj_get (ai);
|
||||||
ti = gm->tunnel_index_by_sw_if_index[sw_if_index];
|
ti = gm->tunnel_index_by_sw_if_index[sw_if_index];
|
||||||
t = pool_elt_at_index (gm->tunnels, ti);
|
t = pool_elt_at_index (gm->tunnels, ti);
|
||||||
is_ipv6 = t->tunnel_dst.fp_proto == FIB_PROTOCOL_IP6 ? 1 : 0;
|
|
||||||
af = ADJ_FLAG_MIDCHAIN_IP_STACK;
|
|
||||||
|
|
||||||
adj_nbr_midchain_update_rewrite
|
|
||||||
(ai, !is_ipv6 ? gre4_fixup : gre6_fixup, NULL, af,
|
|
||||||
gre_build_rewrite (vnm, sw_if_index, adj_get_link_type (ai),
|
|
||||||
&adj->sub_type.nbr.next_hop));
|
|
||||||
|
|
||||||
ne = nhrp_entry_find (sw_if_index, &adj->sub_type.nbr.next_hop);
|
ne = nhrp_entry_find (sw_if_index, &adj->sub_type.nbr.next_hop);
|
||||||
|
|
||||||
@ -367,8 +385,13 @@ mgre_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai)
|
|||||||
// no NHRP entry to provide the next-hop
|
// no NHRP entry to provide the next-hop
|
||||||
return;
|
return;
|
||||||
|
|
||||||
adj_nbr_walk_nh (sw_if_index, t->tunnel_dst.fp_proto,
|
mgre_walk_ctx_t ctx = {
|
||||||
&adj->sub_type.nbr.next_hop, mgre_mk_complete_walk, ne);
|
.t = t,
|
||||||
|
.ne = ne
|
||||||
|
};
|
||||||
|
adj_nbr_walk_nh (sw_if_index,
|
||||||
|
adj->ia_nh_proto,
|
||||||
|
&adj->sub_type.nbr.next_hop, mgre_mk_complete_walk, &ctx);
|
||||||
}
|
}
|
||||||
#endif /* CLIB_MARCH_VARIANT */
|
#endif /* CLIB_MARCH_VARIANT */
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <vnet/ip/format.h>
|
#include <vnet/ip/format.h>
|
||||||
#include <vnet/adj/adj_types.h>
|
#include <vnet/adj/adj_types.h>
|
||||||
#include <vnet/tunnel/tunnel.h>
|
#include <vnet/tunnel/tunnel.h>
|
||||||
|
#include <vnet/nhrp/nhrp.h>
|
||||||
|
|
||||||
extern vnet_hw_interface_class_t gre_hw_interface_class;
|
extern vnet_hw_interface_class_t gre_hw_interface_class;
|
||||||
extern vnet_hw_interface_class_t mgre_hw_interface_class;
|
extern vnet_hw_interface_class_t mgre_hw_interface_class;
|
||||||
@ -323,6 +324,15 @@ extern void gre_tunnel_stack (adj_index_t ai);
|
|||||||
extern void gre_update_adj (vnet_main_t * vnm,
|
extern void gre_update_adj (vnet_main_t * vnm,
|
||||||
u32 sw_if_index, adj_index_t ai);
|
u32 sw_if_index, adj_index_t ai);
|
||||||
|
|
||||||
|
typedef struct mgre_walk_ctx_t_
|
||||||
|
{
|
||||||
|
const gre_tunnel_t *t;
|
||||||
|
const nhrp_entry_t *ne;
|
||||||
|
} mgre_walk_ctx_t;
|
||||||
|
|
||||||
|
adj_walk_rc_t mgre_mk_complete_walk (adj_index_t ai, void *data);
|
||||||
|
adj_walk_rc_t mgre_mk_incomplete_walk (adj_index_t ai, void *data);
|
||||||
|
|
||||||
format_function_t format_gre_protocol;
|
format_function_t format_gre_protocol;
|
||||||
format_function_t format_gre_header;
|
format_function_t format_gre_header;
|
||||||
format_function_t format_gre_header_with_length;
|
format_function_t format_gre_header_with_length;
|
||||||
|
@ -203,10 +203,14 @@ gre_nhrp_mk_key (const gre_tunnel_t * t,
|
|||||||
t->type, TUNNEL_MODE_P2P, 0, &key->gtk_v6);
|
t->type, TUNNEL_MODE_P2P, 0, &key->gtk_v6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An NHRP entry has been added
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
gre_nhrp_entry_added (const nhrp_entry_t * ne)
|
gre_nhrp_entry_added (const nhrp_entry_t * ne)
|
||||||
{
|
{
|
||||||
gre_main_t *gm = &gre_main;
|
gre_main_t *gm = &gre_main;
|
||||||
|
const ip46_address_t *nh;
|
||||||
gre_tunnel_key_t key;
|
gre_tunnel_key_t key;
|
||||||
gre_tunnel_t *t;
|
gre_tunnel_t *t;
|
||||||
u32 sw_if_index;
|
u32 sw_if_index;
|
||||||
@ -221,16 +225,35 @@ gre_nhrp_entry_added (const nhrp_entry_t * ne)
|
|||||||
if (INDEX_INVALID == t_idx)
|
if (INDEX_INVALID == t_idx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* entry has been added on an interface for which there is a GRE tunnel */
|
||||||
t = pool_elt_at_index (gm->tunnels, t_idx);
|
t = pool_elt_at_index (gm->tunnels, t_idx);
|
||||||
|
|
||||||
|
if (t->mode != TUNNEL_MODE_MP)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* the next-hop (underlay) of the NHRP entry will form part of the key for
|
||||||
|
* ingress lookup to match packets to this interface */
|
||||||
gre_nhrp_mk_key (t, ne, &key);
|
gre_nhrp_mk_key (t, ne, &key);
|
||||||
gre_tunnel_db_add (t, &key);
|
gre_tunnel_db_add (t, &key);
|
||||||
|
|
||||||
|
/* update the rewrites for each of the adjacencies for this peer (overlay)
|
||||||
|
* using the next-hop (underlay) */
|
||||||
|
mgre_walk_ctx_t ctx = {
|
||||||
|
.t = t,
|
||||||
|
.ne = ne
|
||||||
|
};
|
||||||
|
nh = nhrp_entry_get_peer (ne);
|
||||||
|
adj_nbr_walk_nh (nhrp_entry_get_sw_if_index (ne),
|
||||||
|
(ip46_address_is_ip4 (nh) ?
|
||||||
|
FIB_PROTOCOL_IP4 :
|
||||||
|
FIB_PROTOCOL_IP6), nh, mgre_mk_complete_walk, &ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gre_nhrp_entry_deleted (const nhrp_entry_t * ne)
|
gre_nhrp_entry_deleted (const nhrp_entry_t * ne)
|
||||||
{
|
{
|
||||||
gre_main_t *gm = &gre_main;
|
gre_main_t *gm = &gre_main;
|
||||||
|
const ip46_address_t *nh;
|
||||||
gre_tunnel_key_t key;
|
gre_tunnel_key_t key;
|
||||||
gre_tunnel_t *t;
|
gre_tunnel_t *t;
|
||||||
u32 sw_if_index;
|
u32 sw_if_index;
|
||||||
@ -247,8 +270,17 @@ gre_nhrp_entry_deleted (const nhrp_entry_t * ne)
|
|||||||
|
|
||||||
t = pool_elt_at_index (gm->tunnels, t_idx);
|
t = pool_elt_at_index (gm->tunnels, t_idx);
|
||||||
|
|
||||||
|
/* remove the next-hop as an ingress lookup key */
|
||||||
gre_nhrp_mk_key (t, ne, &key);
|
gre_nhrp_mk_key (t, ne, &key);
|
||||||
gre_tunnel_db_remove (t, &key);
|
gre_tunnel_db_remove (t, &key);
|
||||||
|
|
||||||
|
nh = nhrp_entry_get_peer (ne);
|
||||||
|
|
||||||
|
/* make all the adjacencies incomplete */
|
||||||
|
adj_nbr_walk_nh (nhrp_entry_get_sw_if_index (ne),
|
||||||
|
(ip46_address_is_ip4 (nh) ?
|
||||||
|
FIB_PROTOCOL_IP4 :
|
||||||
|
FIB_PROTOCOL_IP6), nh, mgre_mk_incomplete_walk, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static walk_rc_t
|
static walk_rc_t
|
||||||
|
@ -67,6 +67,7 @@ typedef ipip_tunnel
|
|||||||
details/dump */
|
details/dump */
|
||||||
u32 table_id;
|
u32 table_id;
|
||||||
vl_api_tunnel_encap_decap_flags_t flags;
|
vl_api_tunnel_encap_decap_flags_t flags;
|
||||||
|
vl_api_tunnel_mode_t mode;
|
||||||
vl_api_ip_dscp_t dscp; /* DSCP value for the tunnel encap,
|
vl_api_ip_dscp_t dscp; /* DSCP value for the tunnel encap,
|
||||||
ignored if ECNAP_COPY_DSCP flag is set */
|
ignored if ECNAP_COPY_DSCP flag is set */
|
||||||
};
|
};
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -48,21 +48,26 @@ typedef enum
|
|||||||
{
|
{
|
||||||
IPIP_TRANSPORT_IP4,
|
IPIP_TRANSPORT_IP4,
|
||||||
IPIP_TRANSPORT_IP6,
|
IPIP_TRANSPORT_IP6,
|
||||||
} ipip_transport_t;
|
} __clib_packed ipip_transport_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
IPIP_MODE_P2P = 0,
|
||||||
|
IPIP_MODE_P2MP,
|
||||||
|
IPIP_MODE_6RD,
|
||||||
|
} __clib_packed ipip_mode_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ip46_address_t src;
|
ip46_address_t src;
|
||||||
ip46_address_t dst;
|
ip46_address_t dst;
|
||||||
ipip_transport_t transport;
|
|
||||||
u32 fib_index;
|
u32 fib_index;
|
||||||
} __attribute__ ((packed)) ipip_tunnel_key_t;
|
ipip_transport_t transport;
|
||||||
|
ipip_mode_t mode;
|
||||||
|
u16 __pad;
|
||||||
|
} __clib_packed ipip_tunnel_key_t;
|
||||||
|
|
||||||
typedef enum
|
STATIC_ASSERT_SIZEOF (ipip_tunnel_key_t, 5 * sizeof (u64));
|
||||||
{
|
|
||||||
IPIP_MODE_P2P = 0,
|
|
||||||
IPIP_MODE_6RD,
|
|
||||||
} ipip_mode_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A representation of a IPIP tunnel
|
* @brief A representation of a IPIP tunnel
|
||||||
@ -74,7 +79,6 @@ typedef struct
|
|||||||
|
|
||||||
ipip_mode_t mode;
|
ipip_mode_t mode;
|
||||||
ipip_transport_t transport;
|
ipip_transport_t transport;
|
||||||
ipip_tunnel_key_t *key;
|
|
||||||
ip46_address_t tunnel_src;
|
ip46_address_t tunnel_src;
|
||||||
ip46_address_t tunnel_dst;
|
ip46_address_t tunnel_dst;
|
||||||
u32 fib_index;
|
u32 fib_index;
|
||||||
@ -145,7 +149,7 @@ sixrd_get_addr_net (const ipip_tunnel_t * t, u64 dal)
|
|||||||
int ipip_add_tunnel (ipip_transport_t transport, u32 instance,
|
int ipip_add_tunnel (ipip_transport_t transport, u32 instance,
|
||||||
ip46_address_t * src, ip46_address_t * dst,
|
ip46_address_t * src, ip46_address_t * dst,
|
||||||
u32 fib_index, tunnel_encap_decap_flags_t flags,
|
u32 fib_index, tunnel_encap_decap_flags_t flags,
|
||||||
ip_dscp_t dscp, u32 * sw_if_indexp);
|
ip_dscp_t dscp, tunnel_mode_t mode, u32 * sw_if_indexp);
|
||||||
int ipip_del_tunnel (u32 sw_if_index);
|
int ipip_del_tunnel (u32 sw_if_index);
|
||||||
int sixrd_add_tunnel (ip6_address_t * ip6_prefix, u8 ip6_prefix_len,
|
int sixrd_add_tunnel (ip6_address_t * ip6_prefix, u8 ip6_prefix_len,
|
||||||
ip4_address_t * ip4_prefix, u8 ip4_prefix_len,
|
ip4_address_t * ip4_prefix, u8 ip4_prefix_len,
|
||||||
@ -153,10 +157,16 @@ int sixrd_add_tunnel (ip6_address_t * ip6_prefix, u8 ip6_prefix_len,
|
|||||||
u32 ip4_fib_index, u32 ip6_fib_index,
|
u32 ip4_fib_index, u32 ip6_fib_index,
|
||||||
u32 * sw_if_index);
|
u32 * sw_if_index);
|
||||||
int sixrd_del_tunnel (u32 sw_if_index);
|
int sixrd_del_tunnel (u32 sw_if_index);
|
||||||
void ipip_tunnel_db_add (ipip_tunnel_t * t, ipip_tunnel_key_t * key);
|
void ipip_tunnel_db_add (ipip_tunnel_t * t, const ipip_tunnel_key_t * key);
|
||||||
void ipip_tunnel_db_remove (ipip_tunnel_t * t);
|
void ipip_tunnel_db_remove (ipip_tunnel_t * t, const ipip_tunnel_key_t * key);
|
||||||
ipip_tunnel_t *ipip_tunnel_db_find (ipip_tunnel_key_t * key);
|
ipip_tunnel_t *ipip_tunnel_db_find (const ipip_tunnel_key_t * key);
|
||||||
ipip_tunnel_t *ipip_tunnel_db_find_by_sw_if_index (u32 sw_if_index);
|
ipip_tunnel_t *ipip_tunnel_db_find_by_sw_if_index (u32 sw_if_index);
|
||||||
|
void ipip_mk_key (const ipip_tunnel_t * t, ipip_tunnel_key_t * key);
|
||||||
|
void ipip_mk_key_i (ipip_transport_t transport,
|
||||||
|
ipip_mode_t mode,
|
||||||
|
const ip46_address_t * src,
|
||||||
|
const ip46_address_t * dst,
|
||||||
|
u32 fib_index, ipip_tunnel_key_t * key);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ vl_api_ipip_add_tunnel_t_handler (vl_api_ipip_add_tunnel_t * mp)
|
|||||||
tunnel_encap_decap_flags_t flags;
|
tunnel_encap_decap_flags_t flags;
|
||||||
ip46_address_t src, dst;
|
ip46_address_t src, dst;
|
||||||
ip46_type_t itype[2];
|
ip46_type_t itype[2];
|
||||||
|
tunnel_mode_t mode;
|
||||||
|
|
||||||
itype[0] = ip_address_decode (&mp->tunnel.src, &src);
|
itype[0] = ip_address_decode (&mp->tunnel.src, &src);
|
||||||
itype[1] = ip_address_decode (&mp->tunnel.dst, &dst);
|
itype[1] = ip_address_decode (&mp->tunnel.dst, &dst);
|
||||||
@ -58,6 +59,11 @@ vl_api_ipip_add_tunnel_t_handler (vl_api_ipip_add_tunnel_t * mp)
|
|||||||
|
|
||||||
rv = tunnel_encap_decap_flags_decode (mp->tunnel.flags, &flags);
|
rv = tunnel_encap_decap_flags_decode (mp->tunnel.flags, &flags);
|
||||||
|
|
||||||
|
if (rv)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
rv = tunnel_mode_decode (mp->tunnel.mode, &mode);
|
||||||
|
|
||||||
if (rv)
|
if (rv)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -75,7 +81,8 @@ vl_api_ipip_add_tunnel_t_handler (vl_api_ipip_add_tunnel_t * mp)
|
|||||||
IPIP_TRANSPORT_IP4),
|
IPIP_TRANSPORT_IP4),
|
||||||
ntohl (mp->tunnel.instance), &src, &dst,
|
ntohl (mp->tunnel.instance), &src, &dst,
|
||||||
fib_index, flags,
|
fib_index, flags,
|
||||||
ip_dscp_decode (mp->tunnel.dscp), &sw_if_index);
|
ip_dscp_decode (mp->tunnel.dscp), mode,
|
||||||
|
&sw_if_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -31,6 +31,7 @@ static clib_error_t *create_ipip_tunnel_command_fn(vlib_main_t *vm,
|
|||||||
u32 sw_if_index;
|
u32 sw_if_index;
|
||||||
clib_error_t *error = NULL;
|
clib_error_t *error = NULL;
|
||||||
bool ip4_set = false, ip6_set = false;
|
bool ip4_set = false, ip6_set = false;
|
||||||
|
tunnel_mode_t mode = TUNNEL_MODE_P2P;
|
||||||
|
|
||||||
/* Get a line of input. */
|
/* Get a line of input. */
|
||||||
if (!unformat_user(input, unformat_line_input, line_input))
|
if (!unformat_user(input, unformat_line_input, line_input))
|
||||||
@ -51,6 +52,8 @@ static clib_error_t *create_ipip_tunnel_command_fn(vlib_main_t *vm,
|
|||||||
} else if (unformat(line_input, "dst %U", unformat_ip6_address, &dst.ip6)) {
|
} else if (unformat(line_input, "dst %U", unformat_ip6_address, &dst.ip6)) {
|
||||||
num_m_args++;
|
num_m_args++;
|
||||||
ip6_set = true;
|
ip6_set = true;
|
||||||
|
} else if (unformat(line_input, "%U", unformat_tunnel_mode, &mode)) {
|
||||||
|
num_m_args++;
|
||||||
} else if (unformat(line_input, "outer-table-id %d", &table_id))
|
} else if (unformat(line_input, "outer-table-id %d", &table_id))
|
||||||
;
|
;
|
||||||
else {
|
else {
|
||||||
@ -84,6 +87,7 @@ static clib_error_t *create_ipip_tunnel_command_fn(vlib_main_t *vm,
|
|||||||
fib_index,
|
fib_index,
|
||||||
TUNNEL_ENCAP_DECAP_FLAG_NONE,
|
TUNNEL_ENCAP_DECAP_FLAG_NONE,
|
||||||
IP_DSCP_CS0,
|
IP_DSCP_CS0,
|
||||||
|
mode,
|
||||||
&sw_if_index);
|
&sw_if_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +108,9 @@ static clib_error_t *create_ipip_tunnel_command_fn(vlib_main_t *vm,
|
|||||||
case VNET_API_ERROR_INSTANCE_IN_USE:
|
case VNET_API_ERROR_INSTANCE_IN_USE:
|
||||||
error = clib_error_return(0, "Instance is in use");
|
error = clib_error_return(0, "Instance is in use");
|
||||||
goto done;
|
goto done;
|
||||||
|
case VNET_API_ERROR_INVALID_DST_ADDRESS:
|
||||||
|
error = clib_error_return(0, "destination IP address when mode is multi-point");
|
||||||
|
goto done;
|
||||||
default:
|
default:
|
||||||
error = clib_error_return(0, "vnet_ipip_add_del_tunnel returned %d", rv);
|
error = clib_error_return(0, "vnet_ipip_add_del_tunnel returned %d", rv);
|
||||||
goto done;
|
goto done;
|
||||||
@ -182,12 +189,16 @@ static u8 *format_ipip_tunnel(u8 *s, va_list *args) {
|
|||||||
format_ip6_address, &t->sixrd.ip6_prefix, t->sixrd.ip6_prefix_len);
|
format_ip6_address, &t->sixrd.ip6_prefix, t->sixrd.ip6_prefix_len);
|
||||||
break;
|
break;
|
||||||
case IPIP_MODE_P2P:
|
case IPIP_MODE_P2P:
|
||||||
default:
|
|
||||||
s = format(s, "[%d] instance %d src %U dst %U ",
|
s = format(s, "[%d] instance %d src %U dst %U ",
|
||||||
t->dev_instance, t->user_instance,
|
t->dev_instance, t->user_instance,
|
||||||
format_ip46_address, &t->tunnel_src, type,
|
format_ip46_address, &t->tunnel_src, type,
|
||||||
format_ip46_address, &t->tunnel_dst, type);
|
format_ip46_address, &t->tunnel_dst, type);
|
||||||
break;
|
break;
|
||||||
|
case IPIP_MODE_P2MP:
|
||||||
|
s = format(s, "[%d] instance %d p2mp src %U ",
|
||||||
|
t->dev_instance, t->user_instance,
|
||||||
|
format_ip46_address, &t->tunnel_src, type);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
s = format(s, "table-ID %d sw-if-idx %d flags [%U] dscp %U",
|
s = format(s, "table-ID %d sw-if-idx %d flags [%U] dscp %U",
|
||||||
@ -235,6 +246,50 @@ VLIB_CLI_COMMAND(show_ipip_tunnel_command, static) = {
|
|||||||
};
|
};
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
static u8 *
|
||||||
|
format_ipip_tunnel_key (u8 *s, va_list *args)
|
||||||
|
{
|
||||||
|
ipip_tunnel_key_t *t = va_arg(*args, ipip_tunnel_key_t *);
|
||||||
|
|
||||||
|
s = format (s, "src:%U dst:%U fib:%d transport:%d mode:%d",
|
||||||
|
format_ip46_address, &t->src, IP46_TYPE_ANY,
|
||||||
|
format_ip46_address, &t->dst, IP46_TYPE_ANY,
|
||||||
|
t->fib_index, t->transport, t->mode);
|
||||||
|
|
||||||
|
return (s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static clib_error_t *
|
||||||
|
ipip_tunnel_hash_show (vlib_main_t * vm,
|
||||||
|
unformat_input_t * input,
|
||||||
|
vlib_cli_command_t * cmd)
|
||||||
|
{
|
||||||
|
ipip_main_t *im = &ipip_main;
|
||||||
|
ipip_tunnel_key_t *key;
|
||||||
|
u32 index;
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
hash_foreach(key, index, im->tunnel_by_key,
|
||||||
|
({
|
||||||
|
vlib_cli_output (vm, " %U -> %d", format_ipip_tunnel_key, key, index);
|
||||||
|
}));
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* show IPSEC tunnel protection hash tables
|
||||||
|
*/
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
VLIB_CLI_COMMAND (ipip_tunnel_hash_show_node, static) =
|
||||||
|
{
|
||||||
|
.path = "show ipip tunnel-hash",
|
||||||
|
.function = ipip_tunnel_hash_show,
|
||||||
|
.short_help = "show ipip tunnel-hash",
|
||||||
|
};
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
static clib_error_t *create_sixrd_tunnel_command_fn(vlib_main_t *vm,
|
static clib_error_t *create_sixrd_tunnel_command_fn(vlib_main_t *vm,
|
||||||
unformat_input_t *input,
|
unformat_input_t *input,
|
||||||
vlib_cli_command_t *cmd) {
|
vlib_cli_command_t *cmd) {
|
||||||
|
@ -83,9 +83,6 @@ ipip_input (vlib_main_t * vm, vlib_node_runtime_t * node,
|
|||||||
ip4_header_t *ip40;
|
ip4_header_t *ip40;
|
||||||
ip6_header_t *ip60;
|
ip6_header_t *ip60;
|
||||||
u32 next0 = IPIP_INPUT_NEXT_DROP;
|
u32 next0 = IPIP_INPUT_NEXT_DROP;
|
||||||
ip46_address_t src0 = ip46_address_initializer, dst0 =
|
|
||||||
ip46_address_initializer;
|
|
||||||
ipip_transport_t transport0;
|
|
||||||
u8 inner_protocol0;
|
u8 inner_protocol0;
|
||||||
|
|
||||||
bi0 = to_next[0] = from[0];
|
bi0 = to_next[0] = from[0];
|
||||||
@ -96,6 +93,11 @@ ipip_input (vlib_main_t * vm, vlib_node_runtime_t * node,
|
|||||||
|
|
||||||
b0 = vlib_get_buffer (vm, bi0);
|
b0 = vlib_get_buffer (vm, bi0);
|
||||||
|
|
||||||
|
ipip_tunnel_key_t key0 = {
|
||||||
|
.fib_index = vnet_buffer (b0)->ip.fib_index,
|
||||||
|
.mode = IPIP_MODE_P2P,
|
||||||
|
};
|
||||||
|
|
||||||
if (is_ipv6)
|
if (is_ipv6)
|
||||||
{
|
{
|
||||||
ip60 = vlib_buffer_get_current (b0);
|
ip60 = vlib_buffer_get_current (b0);
|
||||||
@ -108,10 +110,10 @@ ipip_input (vlib_main_t * vm, vlib_node_runtime_t * node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
vlib_buffer_advance (b0, sizeof (*ip60));
|
vlib_buffer_advance (b0, sizeof (*ip60));
|
||||||
ip_set (&src0, &ip60->src_address, false);
|
ip_set (&key0.dst, &ip60->src_address, false);
|
||||||
ip_set (&dst0, &ip60->dst_address, false);
|
ip_set (&key0.src, &ip60->dst_address, false);
|
||||||
inner_protocol0 = ip60->protocol;
|
inner_protocol0 = ip60->protocol;
|
||||||
transport0 = IPIP_TRANSPORT_IP6;
|
key0.transport = IPIP_TRANSPORT_IP6;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -125,25 +127,21 @@ ipip_input (vlib_main_t * vm, vlib_node_runtime_t * node,
|
|||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
vlib_buffer_advance (b0, sizeof (*ip40));
|
vlib_buffer_advance (b0, sizeof (*ip40));
|
||||||
ip_set (&src0, &ip40->src_address, true);
|
ip_set (&key0.dst, &ip40->src_address, true);
|
||||||
ip_set (&dst0, &ip40->dst_address, true);
|
ip_set (&key0.src, &ip40->dst_address, true);
|
||||||
inner_protocol0 = ip40->protocol;
|
inner_protocol0 = ip40->protocol;
|
||||||
transport0 = IPIP_TRANSPORT_IP4;
|
key0.transport = IPIP_TRANSPORT_IP4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find tunnel. First a lookup for P2P tunnels, then a lookup
|
* Find tunnel. First a lookup for P2P tunnels, then a lookup
|
||||||
* for multipoint tunnels
|
* for multipoint tunnels
|
||||||
*/
|
*/
|
||||||
ipip_tunnel_key_t key0 = {.transport = transport0,
|
|
||||||
.fib_index = vnet_buffer (b0)->ip.fib_index,
|
|
||||||
.src = dst0,
|
|
||||||
.dst = src0
|
|
||||||
};
|
|
||||||
ipip_tunnel_t *t0 = ipip_tunnel_db_find (&key0);
|
ipip_tunnel_t *t0 = ipip_tunnel_db_find (&key0);
|
||||||
if (!t0)
|
if (!t0)
|
||||||
{
|
{
|
||||||
ip46_address_reset (&key0.dst);
|
ip46_address_reset (&key0.dst);
|
||||||
|
key0.mode = IPIP_MODE_6RD;
|
||||||
t0 = ipip_tunnel_db_find (&key0);
|
t0 = ipip_tunnel_db_find (&key0);
|
||||||
if (!t0)
|
if (!t0)
|
||||||
{
|
{
|
||||||
|
@ -283,12 +283,10 @@ sixrd_add_tunnel (ip6_address_t * ip6_prefix, u8 ip6_prefix_len,
|
|||||||
ip46_address_t src = ip46_address_initializer, dst =
|
ip46_address_t src = ip46_address_initializer, dst =
|
||||||
ip46_address_initializer;
|
ip46_address_initializer;
|
||||||
ip_set (&src, ip4_src, true);
|
ip_set (&src, ip4_src, true);
|
||||||
ipip_tunnel_key_t key = {
|
ipip_tunnel_key_t key;
|
||||||
.transport = IPIP_TRANSPORT_IP4,
|
|
||||||
.fib_index = ip4_fib_index,
|
ipip_mk_key_i (IPIP_TRANSPORT_IP4, IPIP_MODE_6RD, &src, &dst, ip4_fib_index,
|
||||||
.src = src,
|
&key);
|
||||||
.dst = dst
|
|
||||||
};
|
|
||||||
|
|
||||||
t = ipip_tunnel_db_find (&key);
|
t = ipip_tunnel_db_find (&key);
|
||||||
if (t)
|
if (t)
|
||||||
@ -377,6 +375,7 @@ sixrd_del_tunnel (u32 sw_if_index)
|
|||||||
{
|
{
|
||||||
ipip_main_t *gm = &ipip_main;
|
ipip_main_t *gm = &ipip_main;
|
||||||
ipip_tunnel_t *t = ipip_tunnel_db_find_by_sw_if_index (sw_if_index);
|
ipip_tunnel_t *t = ipip_tunnel_db_find_by_sw_if_index (sw_if_index);
|
||||||
|
ipip_tunnel_key_t key;
|
||||||
|
|
||||||
if (!t)
|
if (!t)
|
||||||
{
|
{
|
||||||
@ -408,7 +407,8 @@ sixrd_del_tunnel (u32 sw_if_index)
|
|||||||
gm->tunnel_index_by_sw_if_index[t->sw_if_index] = ~0;
|
gm->tunnel_index_by_sw_if_index[t->sw_if_index] = ~0;
|
||||||
|
|
||||||
vnet_delete_hw_interface (vnet_get_main (), t->hw_if_index);
|
vnet_delete_hw_interface (vnet_get_main (), t->hw_if_index);
|
||||||
ipip_tunnel_db_remove (t);
|
ipip_mk_key (t, &key);
|
||||||
|
ipip_tunnel_db_remove (t, &key);
|
||||||
pool_put (gm->tunnels, t);
|
pool_put (gm->tunnels, t);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -647,7 +647,7 @@ vl_api_ipsec_tunnel_if_add_del_t_handler (vl_api_ipsec_tunnel_if_add_del_t *
|
|||||||
&local_ip,
|
&local_ip,
|
||||||
&remote_ip, fib_index,
|
&remote_ip, fib_index,
|
||||||
TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
|
TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
|
||||||
&sw_if_index);
|
TUNNEL_MODE_P2P, &sw_if_index);
|
||||||
|
|
||||||
if (rv)
|
if (rv)
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -843,7 +843,7 @@ create_ipsec_tunnel_command_fn (vlib_main_t * vm,
|
|||||||
ipip_add_tunnel (ipv6_set ? IPIP_TRANSPORT_IP6 : IPIP_TRANSPORT_IP4,
|
ipip_add_tunnel (ipv6_set ? IPIP_TRANSPORT_IP6 : IPIP_TRANSPORT_IP4,
|
||||||
instance, &local_ip, &remote_ip, fib_index,
|
instance, &local_ip, &remote_ip, fib_index,
|
||||||
TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
|
TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
|
||||||
&sw_if_index);
|
TUNNEL_MODE_P2P, &sw_if_index);
|
||||||
rv |=
|
rv |=
|
||||||
ipsec_sa_add_and_lock (ipsec_tun_mk_local_sa_id (sw_if_index),
|
ipsec_sa_add_and_lock (ipsec_tun_mk_local_sa_id (sw_if_index),
|
||||||
local_spi, IPSEC_PROTOCOL_ESP, crypto_alg,
|
local_spi, IPSEC_PROTOCOL_ESP, crypto_alg,
|
||||||
|
@ -76,22 +76,6 @@ nhrp_entry_adj_stack (const nhrp_entry_t * ne, adj_index_t ai)
|
|||||||
adj_midchain_delegate_stack (ai, ne->ne_fib_index, &ne->ne_nh);
|
adj_midchain_delegate_stack (ai, ne->ne_fib_index, &ne->ne_nh);
|
||||||
}
|
}
|
||||||
|
|
||||||
static adj_walk_rc_t
|
|
||||||
nhrp_entry_add_adj_walk (adj_index_t ai, void *ctx)
|
|
||||||
{
|
|
||||||
nhrp_entry_adj_stack (ctx, ai);
|
|
||||||
|
|
||||||
return (ADJ_WALK_RC_CONTINUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static adj_walk_rc_t
|
|
||||||
nhrp_entry_del_adj_walk (adj_index_t ai, void *ctx)
|
|
||||||
{
|
|
||||||
adj_midchain_delegate_unstack (ai);
|
|
||||||
|
|
||||||
return (ADJ_WALK_RC_CONTINUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
nhrp_entry_t *
|
nhrp_entry_t *
|
||||||
nhrp_entry_get (index_t nei)
|
nhrp_entry_get (index_t nei)
|
||||||
{
|
{
|
||||||
@ -157,10 +141,6 @@ nhrp_entry_add (u32 sw_if_index,
|
|||||||
|
|
||||||
hash_set_mem (nhrp_db, ne->ne_key, nei);
|
hash_set_mem (nhrp_db, ne->ne_key, nei);
|
||||||
|
|
||||||
adj_nbr_walk_nh (sw_if_index,
|
|
||||||
ne->ne_nh.fp_proto,
|
|
||||||
&ne->ne_key->nk_peer, nhrp_entry_add_adj_walk, ne);
|
|
||||||
|
|
||||||
NHRP_NOTIFY (ne, nv_added);
|
NHRP_NOTIFY (ne, nv_added);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -180,10 +160,6 @@ nhrp_entry_del (u32 sw_if_index, const ip46_address_t * peer)
|
|||||||
{
|
{
|
||||||
hash_unset_mem (nhrp_db, ne->ne_key);
|
hash_unset_mem (nhrp_db, ne->ne_key);
|
||||||
|
|
||||||
adj_nbr_walk_nh (sw_if_index,
|
|
||||||
ne->ne_nh.fp_proto,
|
|
||||||
&ne->ne_key->nk_peer, nhrp_entry_del_adj_walk, ne);
|
|
||||||
|
|
||||||
NHRP_NOTIFY (ne, nv_deleted);
|
NHRP_NOTIFY (ne, nv_deleted);
|
||||||
|
|
||||||
clib_mem_free (ne->ne_key);
|
clib_mem_free (ne->ne_key);
|
||||||
|
@ -34,6 +34,20 @@ format_tunnel_mode (u8 * s, va_list * args)
|
|||||||
return (s);
|
return (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uword
|
||||||
|
unformat_tunnel_mode (unformat_input_t * input, va_list * args)
|
||||||
|
{
|
||||||
|
tunnel_mode_t *m = va_arg (*args, tunnel_mode_t *);
|
||||||
|
|
||||||
|
if (unformat (input, "p2p"))
|
||||||
|
*m = TUNNEL_MODE_P2P;
|
||||||
|
else if (unformat (input, "p2mp") || unformat (input, "mp"))
|
||||||
|
*m = TUNNEL_MODE_MP;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
u8 *
|
u8 *
|
||||||
format_tunnel_encap_decap_flags (u8 * s, va_list * args)
|
format_tunnel_encap_decap_flags (u8 * s, va_list * args)
|
||||||
{
|
{
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include <vlib/vlib.h>
|
#include <vlib/vlib.h>
|
||||||
|
|
||||||
#define foreach_tunnel_mode \
|
#define foreach_tunnel_mode \
|
||||||
_(P2P, "point-to-point") \
|
_(P2P, "point-to-point") \
|
||||||
_(MP, "multi-point") \
|
_(MP, "multi-point") \
|
||||||
|
|
||||||
@ -32,11 +32,12 @@ typedef enum tunnel_mode_t_
|
|||||||
} __clib_packed tunnel_mode_t;
|
} __clib_packed tunnel_mode_t;
|
||||||
|
|
||||||
extern u8 *format_tunnel_mode (u8 * s, va_list * args);
|
extern u8 *format_tunnel_mode (u8 * s, va_list * args);
|
||||||
|
extern uword unformat_tunnel_mode (unformat_input_t * input, va_list * args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keep these idenitical to those in ipip.api
|
* Keep these idenitical to those in ipip.api
|
||||||
*/
|
*/
|
||||||
#define forech_tunnel_encap_decap_flag \
|
#define forech_tunnel_encap_decap_flag \
|
||||||
_(NONE, "none", 0x0) \
|
_(NONE, "none", 0x0) \
|
||||||
_(ENCAP_COPY_DF, "encap-copy-df", 0x1) \
|
_(ENCAP_COPY_DF, "encap-copy-df", 0x1) \
|
||||||
_(ENCAP_SET_DF, "encap-set-df", 0x2) \
|
_(ENCAP_SET_DF, "encap-set-df", 0x2) \
|
||||||
|
@ -38,7 +38,7 @@ enum tunnel_encap_decap_flags : u8
|
|||||||
enum tunnel_mode : u8
|
enum tunnel_mode : u8
|
||||||
{
|
{
|
||||||
/** point-to-point */
|
/** point-to-point */
|
||||||
TUNNEL_API_MODE_P2P,
|
TUNNEL_API_MODE_P2P = 0,
|
||||||
/** multi-point */
|
/** multi-point */
|
||||||
TUNNEL_API_MODE_MP,
|
TUNNEL_API_MODE_MP,
|
||||||
};
|
};
|
||||||
|
@ -1066,7 +1066,7 @@ class TestGRE(VppTestCase):
|
|||||||
rx = self.send_and_expect(self.pg0, tx_e, itf)
|
rx = self.send_and_expect(self.pg0, tx_e, itf)
|
||||||
self.verify_tunneled_4o4(self.pg0, rx, tx_e,
|
self.verify_tunneled_4o4(self.pg0, rx, tx_e,
|
||||||
itf.local_ip4,
|
itf.local_ip4,
|
||||||
gre_if._remote_hosts[ii].ip4)
|
itf._remote_hosts[ii].ip4)
|
||||||
|
|
||||||
tx_i = self.create_tunnel_stream_4o4(self.pg0,
|
tx_i = self.create_tunnel_stream_4o4(self.pg0,
|
||||||
itf._remote_hosts[ii].ip4,
|
itf._remote_hosts[ii].ip4,
|
||||||
@ -1087,7 +1087,7 @@ class TestGRE(VppTestCase):
|
|||||||
rx = self.send_and_expect(self.pg0, tx_e, itf)
|
rx = self.send_and_expect(self.pg0, tx_e, itf)
|
||||||
self.verify_tunneled_4o4(self.pg0, rx, tx_e,
|
self.verify_tunneled_4o4(self.pg0, rx, tx_e,
|
||||||
itf.local_ip4,
|
itf.local_ip4,
|
||||||
gre_if._remote_hosts[ii].ip4)
|
itf._remote_hosts[ii].ip4)
|
||||||
rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
|
rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
|
||||||
self.verify_decapped_4o4(self.pg0, rx, tx_i)
|
self.verify_decapped_4o4(self.pg0, rx, tx_i)
|
||||||
|
|
||||||
@ -1130,6 +1130,14 @@ class TestGRE(VppTestCase):
|
|||||||
for ii in range(1, 4):
|
for ii in range(1, 4):
|
||||||
route_addr = "4::%d" % ii
|
route_addr = "4::%d" % ii
|
||||||
|
|
||||||
|
#
|
||||||
|
# Add a NHRP entry resolves the peer
|
||||||
|
#
|
||||||
|
nhrp = VppNhrp(self, gre_if,
|
||||||
|
gre_if._remote_hosts[ii].ip6,
|
||||||
|
itf._remote_hosts[ii].ip6)
|
||||||
|
nhrp.add_vpp_config()
|
||||||
|
|
||||||
#
|
#
|
||||||
# route traffic via the peer
|
# route traffic via the peer
|
||||||
#
|
#
|
||||||
@ -1139,14 +1147,6 @@ class TestGRE(VppTestCase):
|
|||||||
gre_if.sw_if_index)])
|
gre_if.sw_if_index)])
|
||||||
route_via_tun.add_vpp_config()
|
route_via_tun.add_vpp_config()
|
||||||
|
|
||||||
#
|
|
||||||
# Add a NHRP entry resolves the peer
|
|
||||||
#
|
|
||||||
nhrp = VppNhrp(self, gre_if,
|
|
||||||
gre_if._remote_hosts[ii].ip6,
|
|
||||||
itf._remote_hosts[ii].ip6)
|
|
||||||
nhrp.add_vpp_config()
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Send a packet stream that is routed into the tunnel
|
# Send a packet stream that is routed into the tunnel
|
||||||
# - packets are GRE encapped
|
# - packets are GRE encapped
|
||||||
@ -1155,7 +1155,7 @@ class TestGRE(VppTestCase):
|
|||||||
rx = self.send_and_expect(self.pg0, tx_e, itf)
|
rx = self.send_and_expect(self.pg0, tx_e, itf)
|
||||||
self.verify_tunneled_6o6(self.pg0, rx, tx_e,
|
self.verify_tunneled_6o6(self.pg0, rx, tx_e,
|
||||||
itf.local_ip6,
|
itf.local_ip6,
|
||||||
gre_if._remote_hosts[ii].ip6)
|
itf._remote_hosts[ii].ip6)
|
||||||
tx_i = self.create_tunnel_stream_6o6(self.pg0,
|
tx_i = self.create_tunnel_stream_6o6(self.pg0,
|
||||||
itf._remote_hosts[ii].ip6,
|
itf._remote_hosts[ii].ip6,
|
||||||
itf.local_ip6,
|
itf.local_ip6,
|
||||||
@ -1174,7 +1174,7 @@ class TestGRE(VppTestCase):
|
|||||||
rx = self.send_and_expect(self.pg0, tx_e, itf)
|
rx = self.send_and_expect(self.pg0, tx_e, itf)
|
||||||
self.verify_tunneled_6o6(self.pg0, rx, tx_e,
|
self.verify_tunneled_6o6(self.pg0, rx, tx_e,
|
||||||
itf.local_ip6,
|
itf.local_ip6,
|
||||||
gre_if._remote_hosts[ii].ip6)
|
itf._remote_hosts[ii].ip6)
|
||||||
rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
|
rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
|
||||||
self.verify_decapped_6o6(self.pg0, rx, tx_i)
|
self.verify_decapped_6o6(self.pg0, rx, tx_i)
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ from framework import VppTestCase, VppTestRunner
|
|||||||
from vpp_ip import DpoProto
|
from vpp_ip import DpoProto
|
||||||
from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, FibPathProto
|
from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, FibPathProto
|
||||||
from vpp_ipip_tun_interface import VppIpIpTunInterface
|
from vpp_ipip_tun_interface import VppIpIpTunInterface
|
||||||
|
from vpp_nhrp import VppNhrp
|
||||||
from vpp_papi import VppEnum
|
from vpp_papi import VppEnum
|
||||||
from socket import AF_INET, AF_INET6, inet_pton
|
from socket import AF_INET, AF_INET6, inet_pton
|
||||||
from util import reassemble4
|
from util import reassemble4
|
||||||
@ -471,6 +472,116 @@ class TestIPIP(VppTestCase):
|
|||||||
def payload(self, len):
|
def payload(self, len):
|
||||||
return 'x' * len
|
return 'x' * len
|
||||||
|
|
||||||
|
def test_mipip4(self):
|
||||||
|
""" p2mp IPv4 tunnel Tests """
|
||||||
|
|
||||||
|
for itf in self.pg_interfaces:
|
||||||
|
#
|
||||||
|
# one underlay nh for each overlay/tunnel peer
|
||||||
|
#
|
||||||
|
itf.generate_remote_hosts(4)
|
||||||
|
itf.configure_ipv4_neighbors()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Create an p2mo IPIP tunnel.
|
||||||
|
# - set it admin up
|
||||||
|
# - assign an IP Addres
|
||||||
|
# - Add a route via the tunnel
|
||||||
|
#
|
||||||
|
ipip_if = VppIpIpTunInterface(self, itf,
|
||||||
|
itf.local_ip4,
|
||||||
|
"0.0.0.0",
|
||||||
|
mode=(VppEnum.vl_api_tunnel_mode_t.
|
||||||
|
TUNNEL_API_MODE_MP))
|
||||||
|
ipip_if.add_vpp_config()
|
||||||
|
ipip_if.admin_up()
|
||||||
|
ipip_if.config_ip4()
|
||||||
|
ipip_if.generate_remote_hosts(4)
|
||||||
|
|
||||||
|
self.logger.info(self.vapi.cli("sh adj"))
|
||||||
|
self.logger.info(self.vapi.cli("sh ip fib"))
|
||||||
|
|
||||||
|
#
|
||||||
|
# ensure we don't match to the tunnel if the source address
|
||||||
|
# is all zeros
|
||||||
|
#
|
||||||
|
# tx = self.create_tunnel_stream_4o4(self.pg0,
|
||||||
|
# "0.0.0.0",
|
||||||
|
# itf.local_ip4,
|
||||||
|
# self.pg0.local_ip4,
|
||||||
|
# self.pg0.remote_ip4)
|
||||||
|
# self.send_and_assert_no_replies(self.pg0, tx)
|
||||||
|
|
||||||
|
#
|
||||||
|
# for-each peer
|
||||||
|
#
|
||||||
|
for ii in range(1, 4):
|
||||||
|
route_addr = "4.4.4.%d" % ii
|
||||||
|
|
||||||
|
#
|
||||||
|
# route traffic via the peer
|
||||||
|
#
|
||||||
|
route_via_tun = VppIpRoute(
|
||||||
|
self, route_addr, 32,
|
||||||
|
[VppRoutePath(ipip_if._remote_hosts[ii].ip4,
|
||||||
|
ipip_if.sw_if_index)])
|
||||||
|
route_via_tun.add_vpp_config()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Add a NHRP entry resolves the peer
|
||||||
|
#
|
||||||
|
nhrp = VppNhrp(self, ipip_if,
|
||||||
|
ipip_if._remote_hosts[ii].ip4,
|
||||||
|
itf._remote_hosts[ii].ip4)
|
||||||
|
nhrp.add_vpp_config()
|
||||||
|
self.logger.info(self.vapi.cli("sh adj nbr ipip0 %s" %
|
||||||
|
ipip_if._remote_hosts[ii].ip4))
|
||||||
|
|
||||||
|
#
|
||||||
|
# Send a packet stream that is routed into the tunnel
|
||||||
|
# - packets are IPIP encapped
|
||||||
|
#
|
||||||
|
inner = (IP(dst=route_addr, src="5.5.5.5") /
|
||||||
|
UDP(sport=1234, dport=1234) /
|
||||||
|
Raw(b'0x44' * 100))
|
||||||
|
tx_e = [(Ether(dst=self.pg0.local_mac,
|
||||||
|
src=self.pg0.remote_mac) /
|
||||||
|
inner) for x in range(63)]
|
||||||
|
|
||||||
|
rxs = self.send_and_expect(self.pg0, tx_e, itf)
|
||||||
|
|
||||||
|
for rx in rxs:
|
||||||
|
self.assertEqual(rx[IP].src, itf.local_ip4)
|
||||||
|
self.assertEqual(rx[IP].dst, itf._remote_hosts[ii].ip4)
|
||||||
|
|
||||||
|
tx_i = [(Ether(dst=self.pg0.local_mac,
|
||||||
|
src=self.pg0.remote_mac) /
|
||||||
|
IP(src=itf._remote_hosts[ii].ip4,
|
||||||
|
dst=itf.local_ip4) /
|
||||||
|
IP(src=self.pg0.local_ip4, dst=self.pg0.remote_ip4) /
|
||||||
|
UDP(sport=1234, dport=1234) /
|
||||||
|
Raw(b'0x44' * 100)) for x in range(63)]
|
||||||
|
|
||||||
|
self.logger.info(self.vapi.cli("sh ipip tunnel-hash"))
|
||||||
|
rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
|
||||||
|
|
||||||
|
#
|
||||||
|
# delete and re-add the NHRP
|
||||||
|
#
|
||||||
|
nhrp.remove_vpp_config()
|
||||||
|
self.send_and_assert_no_replies(self.pg0, tx_e)
|
||||||
|
self.send_and_assert_no_replies(self.pg0, tx_i)
|
||||||
|
|
||||||
|
nhrp.add_vpp_config()
|
||||||
|
rx = self.send_and_expect(self.pg0, tx_e, itf)
|
||||||
|
for rx in rxs:
|
||||||
|
self.assertEqual(rx[IP].src, itf.local_ip4)
|
||||||
|
self.assertEqual(rx[IP].dst, itf._remote_hosts[ii].ip4)
|
||||||
|
rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
|
||||||
|
|
||||||
|
ipip_if.admin_down()
|
||||||
|
ipip_if.unconfig_ip4()
|
||||||
|
|
||||||
|
|
||||||
class TestIPIP6(VppTestCase):
|
class TestIPIP6(VppTestCase):
|
||||||
""" IPIP6 Test Case """
|
""" IPIP6 Test Case """
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from vpp_tunnel_interface import VppTunnelInterface
|
from vpp_tunnel_interface import VppTunnelInterface
|
||||||
from ipaddress import ip_address
|
from ipaddress import ip_address
|
||||||
|
from vpp_papi import VppEnum
|
||||||
|
|
||||||
|
|
||||||
class VppIpIpTunInterface(VppTunnelInterface):
|
class VppIpIpTunInterface(VppTunnelInterface):
|
||||||
@ -9,13 +10,17 @@ class VppIpIpTunInterface(VppTunnelInterface):
|
|||||||
|
|
||||||
def __init__(self, test, parent_if, src, dst,
|
def __init__(self, test, parent_if, src, dst,
|
||||||
table_id=0, dscp=0x0,
|
table_id=0, dscp=0x0,
|
||||||
flags=0):
|
flags=0, mode=None):
|
||||||
super(VppIpIpTunInterface, self).__init__(test, parent_if)
|
super(VppIpIpTunInterface, self).__init__(test, parent_if)
|
||||||
self.src = src
|
self.src = src
|
||||||
self.dst = dst
|
self.dst = dst
|
||||||
self.table_id = table_id
|
self.table_id = table_id
|
||||||
self.dscp = dscp
|
self.dscp = dscp
|
||||||
self.flags = flags
|
self.flags = flags
|
||||||
|
self.mode = mode
|
||||||
|
if not self.mode:
|
||||||
|
self.mode = (VppEnum.vl_api_tunnel_mode_t.
|
||||||
|
TUNNEL_API_MODE_P2P)
|
||||||
|
|
||||||
def add_vpp_config(self):
|
def add_vpp_config(self):
|
||||||
r = self.test.vapi.ipip_add_tunnel(
|
r = self.test.vapi.ipip_add_tunnel(
|
||||||
@ -26,6 +31,7 @@ class VppIpIpTunInterface(VppTunnelInterface):
|
|||||||
'flags': self.flags,
|
'flags': self.flags,
|
||||||
'dscp': self.dscp,
|
'dscp': self.dscp,
|
||||||
'instance': 0xffffffff,
|
'instance': 0xffffffff,
|
||||||
|
'mode': self.mode,
|
||||||
})
|
})
|
||||||
self.set_sw_if_index(r.sw_if_index)
|
self.set_sw_if_index(r.sw_if_index)
|
||||||
self.test.registry.register(self, self.test.logger)
|
self.test.registry.register(self, self.test.logger)
|
||||||
|
Reference in New Issue
Block a user