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
2019-12-29 23:55:18 +00:00
committed by Damjan Marion
parent 59ff918ea5
commit 14053c9dbd
25 changed files with 652 additions and 156 deletions

View File

@ -1546,7 +1546,7 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
rv = ipip_add_tunnel (IPIP_TRANSPORT_IP4, ~0,
&a->local_ip, &a->remote_ip, 0,
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)
{

View File

@ -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 counts:[%Ld:%Ld]", counts.packets, counts.bytes);
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 = format(s, "\n children:");

View File

@ -163,13 +163,13 @@ adj_delegate_format (u8* s, ip_adjacency_t *adj)
{
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 = format(s, "}");
}
else
{
s = format(s, "{unknown delegate}");
s = format(s, "\n {unknown delegate}");
}
}

View File

@ -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
* src,dst, this is all we need.
*/
ASSERT((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) ||
(adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN) ||
(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);
if (adj->lookup_next_index != IP_LOOKUP_NEXT_MIDCHAIN ||
adj->lookup_next_index != IP_LOOKUP_NEXT_MCAST_MIDCHAIN)
{
adj_midchain_setup(adj_index, fixup, fixup_data, flags);
}
/*
* update the rewrite with the workers paused.

View File

@ -907,15 +907,19 @@ adj_nbr_show (vlib_main_t * vm,
vlib_cli_command_t * cmd)
{
adj_index_t ai = ADJ_INDEX_INVALID;
ip46_address_t nh = ip46_address_initializer;
u32 sw_if_index = ~0;
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",
unformat_vnet_sw_interface, vnet_get_main(),
&sw_if_index))
unformat_ip46_address, &nh, IP46_TYPE_ANY))
;
else if (unformat (input, "%d", &ai))
;
else
break;
@ -932,12 +936,24 @@ adj_nbr_show (vlib_main_t * vm,
{
fib_protocol_t proto;
for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
{
adj_nbr_walk(sw_if_index, proto,
adj_nbr_show_one,
vm);
}
if (ip46_address_is_zero(&nh))
{
for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
{
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
{

View File

@ -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:
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))
{
FIB_PATH_DBG(path, "recursive loop formed");

View File

@ -18,7 +18,6 @@
#include <vnet/vnet.h>
#include <vnet/gre/gre.h>
#include <vnet/adj/adj_midchain.h>
#include <vnet/nhrp/nhrp.h>
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);
}
static adj_walk_rc_t
mgre_mk_complete_walk (adj_index_t ai, void *ctx)
adj_walk_rc_t
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);
}
@ -346,20 +373,11 @@ mgre_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai)
ip_adjacency_t *adj;
nhrp_entry_t *ne;
gre_tunnel_t *t;
adj_flags_t af;
u8 is_ipv6;
u32 ti;
adj = adj_get (ai);
ti = gm->tunnel_index_by_sw_if_index[sw_if_index];
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);
@ -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
return;
adj_nbr_walk_nh (sw_if_index, t->tunnel_dst.fp_proto,
&adj->sub_type.nbr.next_hop, mgre_mk_complete_walk, ne);
mgre_walk_ctx_t ctx = {
.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 */

View File

@ -25,6 +25,7 @@
#include <vnet/ip/format.h>
#include <vnet/adj/adj_types.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 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,
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_header;
format_function_t format_gre_header_with_length;

View File

@ -203,10 +203,14 @@ gre_nhrp_mk_key (const gre_tunnel_t * t,
t->type, TUNNEL_MODE_P2P, 0, &key->gtk_v6);
}
/**
* An NHRP entry has been added
*/
static void
gre_nhrp_entry_added (const nhrp_entry_t * ne)
{
gre_main_t *gm = &gre_main;
const ip46_address_t *nh;
gre_tunnel_key_t key;
gre_tunnel_t *t;
u32 sw_if_index;
@ -221,16 +225,35 @@ gre_nhrp_entry_added (const nhrp_entry_t * ne)
if (INDEX_INVALID == t_idx)
return;
/* entry has been added on an interface for which there is a GRE tunnel */
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_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
gre_nhrp_entry_deleted (const nhrp_entry_t * ne)
{
gre_main_t *gm = &gre_main;
const ip46_address_t *nh;
gre_tunnel_key_t key;
gre_tunnel_t *t;
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);
/* remove the next-hop as an ingress lookup key */
gre_nhrp_mk_key (t, ne, &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

View File

@ -67,6 +67,7 @@ typedef ipip_tunnel
details/dump */
u32 table_id;
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,
ignored if ECNAP_COPY_DSCP flag is set */
};

File diff suppressed because it is too large Load Diff

View File

@ -48,21 +48,26 @@ typedef enum
{
IPIP_TRANSPORT_IP4,
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
{
ip46_address_t src;
ip46_address_t dst;
ipip_transport_t transport;
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
{
IPIP_MODE_P2P = 0,
IPIP_MODE_6RD,
} ipip_mode_t;
STATIC_ASSERT_SIZEOF (ipip_tunnel_key_t, 5 * sizeof (u64));
/**
* @brief A representation of a IPIP tunnel
@ -74,7 +79,6 @@ typedef struct
ipip_mode_t mode;
ipip_transport_t transport;
ipip_tunnel_key_t *key;
ip46_address_t tunnel_src;
ip46_address_t tunnel_dst;
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,
ip46_address_t * src, ip46_address_t * dst,
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 sixrd_add_tunnel (ip6_address_t * ip6_prefix, u8 ip6_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 * 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_remove (ipip_tunnel_t * t);
ipip_tunnel_t *ipip_tunnel_db_find (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, const 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);
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

View File

@ -40,6 +40,7 @@ vl_api_ipip_add_tunnel_t_handler (vl_api_ipip_add_tunnel_t * mp)
tunnel_encap_decap_flags_t flags;
ip46_address_t src, dst;
ip46_type_t itype[2];
tunnel_mode_t mode;
itype[0] = ip_address_decode (&mp->tunnel.src, &src);
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);
if (rv)
goto out;
rv = tunnel_mode_decode (mp->tunnel.mode, &mode);
if (rv)
goto out;
@ -75,7 +81,8 @@ vl_api_ipip_add_tunnel_t_handler (vl_api_ipip_add_tunnel_t * mp)
IPIP_TRANSPORT_IP4),
ntohl (mp->tunnel.instance), &src, &dst,
fib_index, flags,
ip_dscp_decode (mp->tunnel.dscp), &sw_if_index);
ip_dscp_decode (mp->tunnel.dscp), mode,
&sw_if_index);
}
out:

View File

@ -31,6 +31,7 @@ static clib_error_t *create_ipip_tunnel_command_fn(vlib_main_t *vm,
u32 sw_if_index;
clib_error_t *error = NULL;
bool ip4_set = false, ip6_set = false;
tunnel_mode_t mode = TUNNEL_MODE_P2P;
/* Get a line of 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)) {
num_m_args++;
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 {
@ -84,6 +87,7 @@ static clib_error_t *create_ipip_tunnel_command_fn(vlib_main_t *vm,
fib_index,
TUNNEL_ENCAP_DECAP_FLAG_NONE,
IP_DSCP_CS0,
mode,
&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:
error = clib_error_return(0, "Instance is in use");
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:
error = clib_error_return(0, "vnet_ipip_add_del_tunnel returned %d", rv);
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);
break;
case IPIP_MODE_P2P:
default:
s = format(s, "[%d] instance %d src %U dst %U ",
t->dev_instance, t->user_instance,
format_ip46_address, &t->tunnel_src, type,
format_ip46_address, &t->tunnel_dst, type);
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",
@ -235,6 +246,50 @@ VLIB_CLI_COMMAND(show_ipip_tunnel_command, static) = {
};
/* *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,
unformat_input_t *input,
vlib_cli_command_t *cmd) {

View File

@ -83,9 +83,6 @@ ipip_input (vlib_main_t * vm, vlib_node_runtime_t * node,
ip4_header_t *ip40;
ip6_header_t *ip60;
u32 next0 = IPIP_INPUT_NEXT_DROP;
ip46_address_t src0 = ip46_address_initializer, dst0 =
ip46_address_initializer;
ipip_transport_t transport0;
u8 inner_protocol0;
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);
ipip_tunnel_key_t key0 = {
.fib_index = vnet_buffer (b0)->ip.fib_index,
.mode = IPIP_MODE_P2P,
};
if (is_ipv6)
{
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));
ip_set (&src0, &ip60->src_address, false);
ip_set (&dst0, &ip60->dst_address, false);
ip_set (&key0.dst, &ip60->src_address, false);
ip_set (&key0.src, &ip60->dst_address, false);
inner_protocol0 = ip60->protocol;
transport0 = IPIP_TRANSPORT_IP6;
key0.transport = IPIP_TRANSPORT_IP6;
}
else
{
@ -125,25 +127,21 @@ ipip_input (vlib_main_t * vm, vlib_node_runtime_t * node,
goto drop;
}
vlib_buffer_advance (b0, sizeof (*ip40));
ip_set (&src0, &ip40->src_address, true);
ip_set (&dst0, &ip40->dst_address, true);
ip_set (&key0.dst, &ip40->src_address, true);
ip_set (&key0.src, &ip40->dst_address, true);
inner_protocol0 = ip40->protocol;
transport0 = IPIP_TRANSPORT_IP4;
key0.transport = IPIP_TRANSPORT_IP4;
}
/*
* Find tunnel. First a lookup for P2P tunnels, then a lookup
* 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);
if (!t0)
{
ip46_address_reset (&key0.dst);
key0.mode = IPIP_MODE_6RD;
t0 = ipip_tunnel_db_find (&key0);
if (!t0)
{

View File

@ -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_initializer;
ip_set (&src, ip4_src, true);
ipip_tunnel_key_t key = {
.transport = IPIP_TRANSPORT_IP4,
.fib_index = ip4_fib_index,
.src = src,
.dst = dst
};
ipip_tunnel_key_t key;
ipip_mk_key_i (IPIP_TRANSPORT_IP4, IPIP_MODE_6RD, &src, &dst, ip4_fib_index,
&key);
t = ipip_tunnel_db_find (&key);
if (t)
@ -377,6 +375,7 @@ sixrd_del_tunnel (u32 sw_if_index)
{
ipip_main_t *gm = &ipip_main;
ipip_tunnel_t *t = ipip_tunnel_db_find_by_sw_if_index (sw_if_index);
ipip_tunnel_key_t key;
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;
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);
return 0;

View File

@ -647,7 +647,7 @@ vl_api_ipsec_tunnel_if_add_del_t_handler (vl_api_ipsec_tunnel_if_add_del_t *
&local_ip,
&remote_ip, fib_index,
TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
&sw_if_index);
TUNNEL_MODE_P2P, &sw_if_index);
if (rv)
goto done;

View File

@ -843,7 +843,7 @@ create_ipsec_tunnel_command_fn (vlib_main_t * vm,
ipip_add_tunnel (ipv6_set ? IPIP_TRANSPORT_IP6 : IPIP_TRANSPORT_IP4,
instance, &local_ip, &remote_ip, fib_index,
TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
&sw_if_index);
TUNNEL_MODE_P2P, &sw_if_index);
rv |=
ipsec_sa_add_and_lock (ipsec_tun_mk_local_sa_id (sw_if_index),
local_spi, IPSEC_PROTOCOL_ESP, crypto_alg,

View File

@ -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);
}
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_get (index_t nei)
{
@ -157,10 +141,6 @@ nhrp_entry_add (u32 sw_if_index,
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);
}
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);
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);
clib_mem_free (ne->ne_key);

View File

@ -34,6 +34,20 @@ format_tunnel_mode (u8 * s, va_list * args)
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 *
format_tunnel_encap_decap_flags (u8 * s, va_list * args)
{

View File

@ -20,7 +20,7 @@
#include <vlib/vlib.h>
#define foreach_tunnel_mode \
#define foreach_tunnel_mode \
_(P2P, "point-to-point") \
_(MP, "multi-point") \
@ -32,11 +32,12 @@ typedef enum tunnel_mode_t_
} __clib_packed tunnel_mode_t;
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
*/
#define forech_tunnel_encap_decap_flag \
#define forech_tunnel_encap_decap_flag \
_(NONE, "none", 0x0) \
_(ENCAP_COPY_DF, "encap-copy-df", 0x1) \
_(ENCAP_SET_DF, "encap-set-df", 0x2) \

View File

@ -38,7 +38,7 @@ enum tunnel_encap_decap_flags : u8
enum tunnel_mode : u8
{
/** point-to-point */
TUNNEL_API_MODE_P2P,
TUNNEL_API_MODE_P2P = 0,
/** multi-point */
TUNNEL_API_MODE_MP,
};

View File

@ -1066,7 +1066,7 @@ class TestGRE(VppTestCase):
rx = self.send_and_expect(self.pg0, tx_e, itf)
self.verify_tunneled_4o4(self.pg0, rx, tx_e,
itf.local_ip4,
gre_if._remote_hosts[ii].ip4)
itf._remote_hosts[ii].ip4)
tx_i = self.create_tunnel_stream_4o4(self.pg0,
itf._remote_hosts[ii].ip4,
@ -1087,7 +1087,7 @@ class TestGRE(VppTestCase):
rx = self.send_and_expect(self.pg0, tx_e, itf)
self.verify_tunneled_4o4(self.pg0, rx, tx_e,
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)
self.verify_decapped_4o4(self.pg0, rx, tx_i)
@ -1130,6 +1130,14 @@ class TestGRE(VppTestCase):
for ii in range(1, 4):
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
#
@ -1139,14 +1147,6 @@ class TestGRE(VppTestCase):
gre_if.sw_if_index)])
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
# - packets are GRE encapped
@ -1155,7 +1155,7 @@ class TestGRE(VppTestCase):
rx = self.send_and_expect(self.pg0, tx_e, itf)
self.verify_tunneled_6o6(self.pg0, rx, tx_e,
itf.local_ip6,
gre_if._remote_hosts[ii].ip6)
itf._remote_hosts[ii].ip6)
tx_i = self.create_tunnel_stream_6o6(self.pg0,
itf._remote_hosts[ii].ip6,
itf.local_ip6,
@ -1174,7 +1174,7 @@ class TestGRE(VppTestCase):
rx = self.send_and_expect(self.pg0, tx_e, itf)
self.verify_tunneled_6o6(self.pg0, rx, tx_e,
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)
self.verify_decapped_6o6(self.pg0, rx, tx_i)

View File

@ -8,6 +8,7 @@ from framework import VppTestCase, VppTestRunner
from vpp_ip import DpoProto
from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, FibPathProto
from vpp_ipip_tun_interface import VppIpIpTunInterface
from vpp_nhrp import VppNhrp
from vpp_papi import VppEnum
from socket import AF_INET, AF_INET6, inet_pton
from util import reassemble4
@ -471,6 +472,116 @@ class TestIPIP(VppTestCase):
def payload(self, 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):
""" IPIP6 Test Case """

View File

@ -1,5 +1,6 @@
from vpp_tunnel_interface import VppTunnelInterface
from ipaddress import ip_address
from vpp_papi import VppEnum
class VppIpIpTunInterface(VppTunnelInterface):
@ -9,13 +10,17 @@ class VppIpIpTunInterface(VppTunnelInterface):
def __init__(self, test, parent_if, src, dst,
table_id=0, dscp=0x0,
flags=0):
flags=0, mode=None):
super(VppIpIpTunInterface, self).__init__(test, parent_if)
self.src = src
self.dst = dst
self.table_id = table_id
self.dscp = dscp
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):
r = self.test.vapi.ipip_add_tunnel(
@ -26,6 +31,7 @@ class VppIpIpTunInterface(VppTunnelInterface):
'flags': self.flags,
'dscp': self.dscp,
'instance': 0xffffffff,
'mode': self.mode,
})
self.set_sw_if_index(r.sw_if_index)
self.test.registry.register(self, self.test.logger)