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,
|
||||
&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)
|
||||
{
|
||||
|
@ -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:");
|
||||
|
@ -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}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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");
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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) \
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 """
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user