GRE over IPv6

Refactors the GRE node to work with both IPv4 and IPv6 transports.

Note that this changes the binary configuration API to support both
address families; each address uses the same memory for either
address type and a flag to indicate which is in use.

The CLI and VAT syntax remains unchanged; the code detects whether
an IPv4 or an IPv6 address was given.

Configuration examples:

IPv4 CLI: create gre tunnel src 192.168.1.1 dst 192.168.1.2
IPv6 CLI: create gre tunnel src 2620:124:9000::1 dst 2620:124:9000::2

IPv4 VAT: gre_add_del_tunnel src 192.168.1.1 dst 192.168.1.2
IPv6 VAT: gre_add_del_tunnel src 2620:124:9000::1 dst 2620:124:9000::2

Change-Id: Ica8ee775dc101047fb8cd41617ddc8fafc2741b0
Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
This commit is contained in:
Ciara Loftus
2016-09-30 15:47:03 +01:00
parent 63d5bae640
commit 7eac916e1b
9 changed files with 783 additions and 193 deletions
+65 -13
View File
@@ -11018,21 +11018,45 @@ api_gre_add_del_tunnel (vat_main_t * vam)
unformat_input_t *line_input = vam->input;
vl_api_gre_add_del_tunnel_t *mp;
ip4_address_t src4, dst4;
ip6_address_t src6, dst6;
u8 is_add = 1;
u8 ipv4_set = 0;
u8 ipv6_set = 0;
u8 teb = 0;
u8 src_set = 0;
u8 dst_set = 0;
u32 outer_fib_id = 0;
int ret;
memset (&src4, 0, sizeof src4);
memset (&dst4, 0, sizeof dst4);
memset (&src6, 0, sizeof src6);
memset (&dst6, 0, sizeof dst6);
while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (line_input, "del"))
is_add = 0;
else if (unformat (line_input, "src %U", unformat_ip4_address, &src4))
src_set = 1;
{
src_set = 1;
ipv4_set = 1;
}
else if (unformat (line_input, "dst %U", unformat_ip4_address, &dst4))
dst_set = 1;
{
dst_set = 1;
ipv4_set = 1;
}
else if (unformat (line_input, "src %U", unformat_ip6_address, &src6))
{
src_set = 1;
ipv6_set = 1;
}
else if (unformat (line_input, "dst %U", unformat_ip6_address, &dst6))
{
dst_set = 1;
ipv6_set = 1;
}
else if (unformat (line_input, "outer-fib-id %d", &outer_fib_id))
;
else if (unformat (line_input, "teb"))
@@ -11054,15 +11078,29 @@ api_gre_add_del_tunnel (vat_main_t * vam)
errmsg ("tunnel dst address not specified");
return -99;
}
if (ipv4_set && ipv6_set)
{
errmsg ("both IPv4 and IPv6 addresses specified");
return -99;
}
M (GRE_ADD_DEL_TUNNEL, mp);
clib_memcpy (&mp->src_address, &src4, sizeof (src4));
clib_memcpy (&mp->dst_address, &dst4, sizeof (dst4));
if (ipv4_set)
{
clib_memcpy (&mp->src_address, &src4, 4);
clib_memcpy (&mp->dst_address, &dst4, 4);
}
else
{
clib_memcpy (&mp->src_address, &src6, 16);
clib_memcpy (&mp->dst_address, &dst6, 16);
}
mp->outer_fib_id = ntohl (outer_fib_id);
mp->is_add = is_add;
mp->teb = teb;
mp->is_ipv6 = ipv6_set;
S (mp);
W (ret);
@@ -11073,11 +11111,13 @@ static void vl_api_gre_tunnel_details_t_handler
(vl_api_gre_tunnel_details_t * mp)
{
vat_main_t *vam = &vat_main;
ip46_address_t src = to_ip46 (mp->is_ipv6, mp->src_address);
ip46_address_t dst = to_ip46 (mp->is_ipv6, mp->dst_address);
print (vam->ofp, "%11d%15U%15U%6d%14d",
print (vam->ofp, "%11d%24U%24U%6d%14d",
ntohl (mp->sw_if_index),
format_ip4_address, &mp->src_address,
format_ip4_address, &mp->dst_address,
format_ip46_address, &src, IP46_TYPE_ANY,
format_ip46_address, &dst, IP46_TYPE_ANY,
mp->teb, ntohl (mp->outer_fib_id));
}
@@ -11087,6 +11127,7 @@ static void vl_api_gre_tunnel_details_t_handler_json
vat_main_t *vam = &vat_main;
vat_json_node_t *node = NULL;
struct in_addr ip4;
struct in6_addr ip6;
if (VAT_JSON_ARRAY != vam->json_tree.type)
{
@@ -11097,12 +11138,23 @@ static void vl_api_gre_tunnel_details_t_handler_json
vat_json_init_object (node);
vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
clib_memcpy (&ip4, &mp->src_address, sizeof (ip4));
vat_json_object_add_ip4 (node, "src_address", ip4);
clib_memcpy (&ip4, &mp->dst_address, sizeof (ip4));
vat_json_object_add_ip4 (node, "dst_address", ip4);
if (!mp->is_ipv6)
{
clib_memcpy (&ip4, &mp->src_address, sizeof (ip4));
vat_json_object_add_ip4 (node, "src_address", ip4);
clib_memcpy (&ip4, &mp->dst_address, sizeof (ip4));
vat_json_object_add_ip4 (node, "dst_address", ip4);
}
else
{
clib_memcpy (&ip6, &mp->src_address, sizeof (ip6));
vat_json_object_add_ip6 (node, "src_address", ip6);
clib_memcpy (&ip6, &mp->dst_address, sizeof (ip6));
vat_json_object_add_ip6 (node, "dst_address", ip6);
}
vat_json_object_add_uint (node, "teb", mp->teb);
vat_json_object_add_uint (node, "outer_fib_id", ntohl (mp->outer_fib_id));
vat_json_object_add_uint (node, "is_ipv6", mp->is_ipv6);
}
static int
@@ -11131,7 +11183,7 @@ api_gre_tunnel_dump (vat_main_t * vam)
if (!vam->json_output)
{
print (vam->ofp, "%11s%15s%15s%6s%14s",
print (vam->ofp, "%11s%24s%24s%6s%14s",
"sw_if_index", "src_address", "dst_address", "teb",
"outer_fib_id");
}
@@ -18612,7 +18664,7 @@ _(vxlan_add_del_tunnel, \
"vni <vni> [encap-vrf-id <nn>] [decap-next <l2|nn>] [del]") \
_(vxlan_tunnel_dump, "[<intfc> | sw_if_index <nn>]") \
_(gre_add_del_tunnel, \
"src <ip4-addr> dst <ip4-addr> [outer-fib-id <nn>] [teb] [del]\n") \
"src <ip-addr> dst <ip-addr> [outer-fib-id <nn>] [teb] [del]\n") \
_(gre_tunnel_dump, "[<intfc> | sw_if_index <nn>]") \
_(l2_fib_clear_table, "") \
_(l2_interface_efp_filter, "sw_if_index <nn> enable | disable") \
+86 -24
View File
@@ -28,6 +28,13 @@ typedef struct {
};
} ip4_and_gre_union_t;
typedef struct {
union {
ip6_and_gre_header_t ip6_and_gre;
u64 as_u64[3];
};
} ip6_and_gre_union_t;
/* Packet trace structure */
typedef struct {
@@ -37,9 +44,9 @@ typedef struct {
/* pkt length */
u32 length;
/* tunnel ip4 addresses */
ip4_address_t src;
ip4_address_t dst;
/* tunnel ip addresses */
ip46_address_t src;
ip46_address_t dst;
} gre_tx_trace_t;
u8 * format_gre_tx_trace (u8 * s, va_list * args)
@@ -50,8 +57,8 @@ u8 * format_gre_tx_trace (u8 * s, va_list * args)
s = format (s, "GRE: tunnel %d len %d src %U dst %U",
t->tunnel_id, clib_net_to_host_u16 (t->length),
format_ip4_address, &t->src.as_u8,
format_ip4_address, &t->dst.as_u8);
format_ip46_address, &t->src, IP46_TYPE_ANY,
format_ip46_address, &t->dst, IP46_TYPE_ANY);
return s;
}
@@ -192,10 +199,12 @@ gre_build_rewrite (vnet_main_t * vnm,
const void *dst_address)
{
gre_main_t * gm = &gre_main;
ip4_and_gre_header_t * h;
ip4_and_gre_header_t * h4;
ip6_and_gre_header_t * h6;
u8* rewrite = NULL;
gre_tunnel_t *t;
u32 ti;
u8 is_ipv6;
ti = gm->tunnel_index_by_sw_if_index[sw_if_index];
@@ -205,23 +214,45 @@ gre_build_rewrite (vnet_main_t * vnm,
t = pool_elt_at_index(gm->tunnels, ti);
vec_validate(rewrite, sizeof(*h)-1);
h = (ip4_and_gre_header_t*)rewrite;
h->gre.protocol = clib_host_to_net_u16(gre_proto_from_vnet_link(link_type));
is_ipv6 = t->tunnel_dst.fp_proto == FIB_PROTOCOL_IP6 ? 1 : 0;
h->ip4.ip_version_and_header_length = 0x45;
h->ip4.ttl = 254;
h->ip4.protocol = IP_PROTOCOL_GRE;
/* fixup ip4 header length and checksum after-the-fact */
h->ip4.src_address.as_u32 = t->tunnel_src.as_u32;
h->ip4.dst_address.as_u32 = t->tunnel_dst.as_u32;
h->ip4.checksum = ip4_header_checksum (&h->ip4);
if (!is_ipv6)
{
vec_validate(rewrite, sizeof(*h4)-1);
h4 = (ip4_and_gre_header_t*)rewrite;
h4->gre.protocol = clib_host_to_net_u16(gre_proto_from_vnet_link(link_type));
h4->ip4.ip_version_and_header_length = 0x45;
h4->ip4.ttl = 254;
h4->ip4.protocol = IP_PROTOCOL_GRE;
/* fixup ip4 header length and checksum after-the-fact */
h4->ip4.src_address.as_u32 = t->tunnel_src.ip4.as_u32;
h4->ip4.dst_address.as_u32 = t->tunnel_dst.fp_addr.ip4.as_u32;
h4->ip4.checksum = ip4_header_checksum (&h4->ip4);
}
else
{
vec_validate(rewrite, sizeof(*h6)-1);
h6 = (ip6_and_gre_header_t*)rewrite;
h6->gre.protocol = clib_host_to_net_u16(gre_proto_from_vnet_link(link_type));
h6->ip6.ip_version_traffic_class_and_flow_label = clib_host_to_net_u32(6 << 28);
h6->ip6.hop_limit = 255;
h6->ip6.protocol = IP_PROTOCOL_GRE;
/* fixup ip6 header length and checksum after-the-fact */
h6->ip6.src_address.as_u64[0] = t->tunnel_src.ip6.as_u64[0];
h6->ip6.src_address.as_u64[1] = t->tunnel_src.ip6.as_u64[1];
h6->ip6.dst_address.as_u64[0] = t->tunnel_dst.fp_addr.ip6.as_u64[0];
h6->ip6.dst_address.as_u64[1] = t->tunnel_dst.fp_addr.ip6.as_u64[1];
}
return (rewrite);
}
#define is_v4_packet(_h) ((*(u8*) _h) & 0xF0) == 0x40
void
gre_fixup (vlib_main_t *vm,
gre4_fixup (vlib_main_t *vm,
ip_adjacency_t *adj,
vlib_buffer_t *b0)
{
@@ -235,12 +266,37 @@ gre_fixup (vlib_main_t *vm,
ip0->checksum = ip4_header_checksum (ip0);
}
void
gre6_fixup (vlib_main_t *vm,
ip_adjacency_t *adj,
vlib_buffer_t *b0)
{
ip6_header_t * ip0;
ip0 = vlib_buffer_get_current (b0);
/* Fixup the payload length field in the GRE tunnel encap that was applied
* at the midchain node */
ip0->payload_length =
clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0))
- sizeof(*ip0);
}
void
gre_update_adj (vnet_main_t * vnm,
u32 sw_if_index,
adj_index_t ai)
{
adj_nbr_midchain_update_rewrite (ai, gre_fixup,
gre_main_t * gm = &gre_main;
gre_tunnel_t *t;
u32 ti;
u8 is_ipv6;
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;
adj_nbr_midchain_update_rewrite (ai, !is_ipv6 ? gre4_fixup : gre6_fixup,
(VNET_LINK_ETHERNET == adj_get_link_type (ai) ?
ADJ_FLAG_MIDCHAIN_NO_COUNT :
ADJ_FLAG_NONE),
@@ -264,6 +320,7 @@ gre_interface_tx_inline (vlib_main_t * vm,
u32 * from, * to_next, n_left_from, n_left_to_next;
vnet_interface_output_runtime_t * rd = (void *) node->runtime_data;
const gre_tunnel_t *gt = pool_elt_at_index (gm->tunnels, rd->dev_instance);
u8 is_ipv6 = gt->tunnel_dst.fp_proto == FIB_PROTOCOL_IP6 ? 1 : 0;
/* Vector of buffer / pkt indices we're supposed to process */
from = vlib_frame_vector_args (frame);
@@ -303,10 +360,10 @@ gre_interface_tx_inline (vlib_main_t * vm,
{
gre_tx_trace_t *tr = vlib_add_trace (vm, node,
b0, sizeof (*tr));
tr->tunnel_id = gt - gm->tunnels;
tr->length = vlib_buffer_length_in_chain (vm, b0);
tr->src.as_u32 = gt->tunnel_src.as_u32;
tr->dst.as_u32 = gt->tunnel_src.as_u32;
tr->tunnel_id = gt - gm->tunnels;
tr->src = gt->tunnel_src;
tr->dst = gt->tunnel_src;
tr->length = vlib_buffer_length_in_chain (vm, b0);
}
vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
@@ -317,7 +374,8 @@ gre_interface_tx_inline (vlib_main_t * vm,
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}
vlib_node_increment_counter (vm, gre_input_node.index,
vlib_node_increment_counter (vm, !is_ipv6 ? gre4_input_node.index :
gre6_input_node.index,
GRE_ERROR_PKTS_ENCAP, frame->n_vectors);
return frame->n_vectors;
@@ -434,6 +492,9 @@ static clib_error_t * gre_init (vlib_main_t * vm)
if ((error = vlib_call_init_function (vm, ip4_lookup_init)))
return error;
if ((error = vlib_call_init_function (vm, ip6_lookup_init)))
return error;
/* Set up the ip packet generator */
pi = ip_get_protocol_info (im, IP_PROTOCOL_GRE);
pi->format_header = format_gre_header;
@@ -441,7 +502,8 @@ static clib_error_t * gre_init (vlib_main_t * vm)
gm->protocol_info_by_name = hash_create_string (0, sizeof (uword));
gm->protocol_info_by_protocol = hash_create (0, sizeof (uword));
gm->tunnel_by_key = hash_create (0, sizeof (uword));
gm->tunnel_by_key4 = hash_create (0, sizeof (uword));
gm->tunnel_by_key6 = hash_create_mem (0, sizeof(u64[4]), sizeof (uword));
#define _(n,s) add_protocol (gm, GRE_PROTOCOL_##s, #s);
foreach_gre_protocol
+22 -8
View File
@@ -21,8 +21,6 @@
#include <vnet/vnet.h>
#include <vnet/gre/packet.h>
#include <vnet/ip/ip.h>
#include <vnet/ip/ip4.h>
#include <vnet/ip/ip4_packet.h>
#include <vnet/pg/pg.h>
#include <vnet/ip/format.h>
#include <vnet/adj/adj_types.h>
@@ -87,11 +85,11 @@ typedef struct {
/**
* The tunnel's source/local address
*/
ip4_address_t tunnel_src;
ip46_address_t tunnel_src;
/**
* The tunnel's destination/remote address
*/
ip4_address_t tunnel_dst;
fib_prefix_t tunnel_dst;
/**
* The FIB in which the src.dst address are present
*/
@@ -142,10 +140,16 @@ typedef struct {
* Hash tables mapping name/protocol to protocol info index.
*/
uword * protocol_info_by_name, * protocol_info_by_protocol;
/**
* Hash mapping src/dst addr pair to tunnel
* Hash mapping ipv4 src/dst addr pair to tunnel
*/
uword * tunnel_by_key;
uword * tunnel_by_key4;
/**
* Hash mapping ipv6 src/dst addr pair to tunnel
*/
uword * tunnel_by_key6;
/**
* Free vlib hw_if_indices.
@@ -176,6 +180,14 @@ typedef CLIB_PACKED (struct {
gre_header_t gre;
}) ip4_and_gre_header_t;
/**
* @brief IPv6 and GRE header.
*/
typedef CLIB_PACKED (struct {
ip6_header_t ip6;
gre_header_t gre;
}) ip6_and_gre_header_t;
always_inline gre_protocol_info_t *
gre_get_protocol_info (gre_main_t * em, gre_protocol_t protocol)
{
@@ -204,7 +216,8 @@ format_function_t format_gre_protocol;
format_function_t format_gre_header;
format_function_t format_gre_header_with_length;
extern vlib_node_registration_t gre_input_node;
extern vlib_node_registration_t gre4_input_node;
extern vlib_node_registration_t gre6_input_node;
extern vnet_device_class_t gre_device_class;
extern vnet_device_class_t gre_device_teb_class;
@@ -228,7 +241,8 @@ gre_register_input_protocol (vlib_main_t * vm,
typedef struct {
u8 is_add;
ip4_address_t src, dst;
ip46_address_t src, dst;
u8 is_ipv6;
u32 outer_fib_id;
u8 teb;
} vnet_gre_add_del_tunnel_args_t;
+33 -11
View File
@@ -55,17 +55,17 @@ static void vl_api_gre_add_del_tunnel_t_handler
int rv = 0;
vnet_gre_add_del_tunnel_args_t _a, *a = &_a;
u32 outer_fib_id;
uword *p;
ip4_main_t *im = &ip4_main;
u32 p;
u32 sw_if_index = ~0;
p = hash_get (im->fib_index_by_table_id, ntohl (mp->outer_fib_id));
if (!p)
p = fib_table_find (!mp->is_ipv6 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6,
ntohl (mp->outer_fib_id));
if (p == ~0)
{
rv = VNET_API_ERROR_NO_SUCH_FIB;
goto out;
}
outer_fib_id = p[0];
outer_fib_id = p;
/* Check src & dst are different */
if ((mp->is_ipv6 && memcmp (mp->src_address, mp->dst_address, 16) == 0) ||
@@ -78,10 +78,19 @@ static void vl_api_gre_add_del_tunnel_t_handler
a->is_add = mp->is_add;
a->teb = mp->teb;
a->is_ipv6 = mp->is_ipv6;
/* ip addresses sent in network byte order */
clib_memcpy (&(a->src), mp->src_address, 4);
clib_memcpy (&(a->dst), mp->dst_address, 4);
if (!mp->is_ipv6)
{
clib_memcpy (&(a->src.ip4), mp->src_address, 4);
clib_memcpy (&(a->dst.ip4), mp->dst_address, 4);
}
else
{
clib_memcpy (&(a->src.ip6), mp->src_address, 16);
clib_memcpy (&(a->dst.ip6), mp->dst_address, 16);
}
a->outer_fib_id = outer_fib_id;
rv = vnet_gre_add_del_tunnel (a, &sw_if_index);
@@ -99,17 +108,30 @@ static void send_gre_tunnel_details
(gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
{
vl_api_gre_tunnel_details_t *rmp;
ip4_main_t *im = &ip4_main;
u8 is_ipv6 = t->tunnel_dst.fp_proto == FIB_PROTOCOL_IP6 ? 1 : 0;
fib_table_t *ft;
rmp = vl_msg_api_alloc (sizeof (*rmp));
memset (rmp, 0, sizeof (*rmp));
rmp->_vl_msg_id = ntohs (VL_API_GRE_TUNNEL_DETAILS);
clib_memcpy (rmp->src_address, &(t->tunnel_src), 4);
clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4);
rmp->outer_fib_id = htonl (im->fibs[t->outer_fib_index].ft_table_id);
if (!is_ipv6)
{
clib_memcpy (rmp->src_address, &(t->tunnel_src.ip4.as_u8), 4);
clib_memcpy (rmp->dst_address, &(t->tunnel_dst.fp_addr.ip4.as_u8), 4);
ft = fib_table_get (t->outer_fib_index, FIB_PROTOCOL_IP4);
rmp->outer_fib_id = ft->ft_table_id;
}
else
{
clib_memcpy (rmp->src_address, &(t->tunnel_src.ip6.as_u8), 16);
clib_memcpy (rmp->dst_address, &(t->tunnel_dst.fp_addr.ip6.as_u8), 16);
ft = fib_table_get (t->outer_fib_index, FIB_PROTOCOL_IP6);
rmp->outer_fib_id = ft->ft_table_id;
}
rmp->teb = (GRE_TUNNEL_TYPE_TEB == t->type);
rmp->sw_if_index = htonl (t->sw_if_index);
rmp->context = context;
rmp->is_ipv6 = is_ipv6;
vl_msg_api_send_shmem (q, (u8 *) & rmp);
}
+139 -53
View File
File diff suppressed because it is too large Load Diff
+249 -65
View File
File diff suppressed because it is too large Load Diff
+12 -12
View File
@@ -92,6 +92,8 @@ ipsec_gre_input (vlib_main_t * vm,
u32 n_left_from, next_index, * from, * to_next;
u64 cached_tunnel_key = (u64) ~0;
u32 cached_tunnel_sw_if_index = 0, tunnel_sw_if_index;
u32 tun_src0, tun_dst0;
u32 tun_src1, tun_dst1;
from = vlib_frame_vector_args (from_frame);
n_left_from = from_frame->n_vectors;
@@ -146,10 +148,10 @@ ipsec_gre_input (vlib_main_t * vm,
ip1 = vlib_buffer_get_current (b1);
/* Save src + dst ip4 address */
vnet_buffer(b0)->gre.src = ip0->src_address.as_u32;
vnet_buffer(b0)->gre.dst = ip0->dst_address.as_u32;
vnet_buffer(b1)->gre.src = ip1->src_address.as_u32;
vnet_buffer(b1)->gre.dst = ip1->dst_address.as_u32;
tun_src0 = ip0->src_address.as_u32;
tun_dst0 = ip0->dst_address.as_u32;
tun_src1 = ip1->src_address.as_u32;
tun_dst1 = ip1->dst_address.as_u32;
vlib_buffer_advance (b0, sizeof (*ip0));
vlib_buffer_advance (b1, sizeof (*ip1));
@@ -197,8 +199,7 @@ ipsec_gre_input (vlib_main_t * vm,
/* For L2 payload set input sw_if_index to GRE tunnel for learning */
if (PREDICT_TRUE(next0 == IPSEC_GRE_INPUT_NEXT_L2_INPUT))
{
u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) |
(u64)(vnet_buffer(b0)->gre.src);
u64 key = ((u64)(tun_dst0) << 32) | (u64)(tun_src0);
if (cached_tunnel_key != key)
{
@@ -230,8 +231,7 @@ drop0:
/* For L2 payload set input sw_if_index to GRE tunnel for learning */
if (PREDICT_TRUE(next1 == IPSEC_GRE_INPUT_NEXT_L2_INPUT))
{
u64 key = ((u64)(vnet_buffer(b1)->gre.dst) << 32) |
(u64)(vnet_buffer(b1)->gre.src);
u64 key = ((u64)(tun_dst1) << 32) | (u64)(tun_src1);
if (cached_tunnel_key != key)
{
@@ -297,6 +297,7 @@ drop1:
u16 version0, protocol0;
int verr0;
u32 next0;
u32 tun_src0, tun_dst0;
bi0 = from[0];
to_next[0] = bi0;
@@ -308,8 +309,8 @@ drop1:
b0 = vlib_get_buffer (vm, bi0);
ip0 = vlib_buffer_get_current (b0);
vnet_buffer(b0)->gre.src = ip0->src_address.as_u32;
vnet_buffer(b0)->gre.dst = ip0->dst_address.as_u32;
tun_src0 = ip0->src_address.as_u32;
tun_dst0 = ip0->dst_address.as_u32;
vlib_buffer_advance (b0, sizeof (*ip0));
@@ -337,8 +338,7 @@ drop1:
/* For L2 payload set input sw_if_index to GRE tunnel for learning */
if (PREDICT_FALSE(next0 == IPSEC_GRE_INPUT_NEXT_L2_INPUT))
{
u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) |
(u64)(vnet_buffer(b0)->gre.src);
u64 key = ((u64)(tun_dst0) << 32) | (u64)(tun_src0);
if (cached_tunnel_key != key)
{
+142 -7
View File
@@ -5,7 +5,7 @@ from logging import *
from framework import VppTestCase, VppTestRunner
from vpp_sub_interface import VppDot1QSubint
from vpp_gre_interface import VppGreInterface
from vpp_gre_interface import VppGreInterface, VppGre6Interface
from vpp_ip_route import VppIpRoute, VppRoutePath
from vpp_papi_provider import L2_VTR_OP
@@ -28,14 +28,19 @@ class TestGRE(VppTestCase):
def setUp(self):
super(TestGRE, self).setUp()
# create 2 pg interfaces - set one in a non-default table.
self.create_pg_interfaces(range(2))
# create 3 pg interfaces - set one in a non-default table.
self.create_pg_interfaces(range(3))
self.pg1.set_table_ip4(1)
for i in self.pg_interfaces:
i.admin_up()
i.config_ip4()
i.resolve_arp()
self.pg0.config_ip4()
self.pg0.resolve_arp()
self.pg1.config_ip4()
self.pg1.resolve_arp()
self.pg2.config_ip6()
self.pg2.resolve_ndp()
def tearDown(self):
super(TestGRE, self).tearDown()
@@ -57,6 +62,19 @@ class TestGRE(VppTestCase):
pkts.append(p)
return pkts
def create_stream_ip6(self, src_if, src_ip, dst_ip):
pkts = []
for i in range(0, 257):
info = self.create_packet_info(src_if, src_if)
payload = self.info_to_payload(info)
p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
IPv6(src=src_ip, dst=dst_ip) /
UDP(sport=1234, dport=1234) /
Raw(payload))
info.data = p.copy()
pkts.append(p)
return pkts
def create_tunnel_stream_4o4(self, src_if,
tunnel_src, tunnel_dst,
src_ip, dst_ip):
@@ -91,6 +109,23 @@ class TestGRE(VppTestCase):
pkts.append(p)
return pkts
def create_tunnel_stream_6o6(self, src_if,
tunnel_src, tunnel_dst,
src_ip, dst_ip):
pkts = []
for i in range(0, 257):
info = self.create_packet_info(src_if, src_if)
payload = self.info_to_payload(info)
p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
IPv6(src=tunnel_src, dst=tunnel_dst) /
GRE() /
IPv6(src=src_ip, dst=dst_ip) /
UDP(sport=1234, dport=1234) /
Raw(payload))
info.data = p.copy()
pkts.append(p)
return pkts
def create_tunnel_stream_l2o4(self, src_if,
tunnel_src, tunnel_dst):
pkts = []
@@ -157,6 +192,33 @@ class TestGRE(VppTestCase):
self.logger.error(ppp("Tx:", tx))
raise
def verify_tunneled_6o6(self, src_if, capture, sent,
tunnel_src, tunnel_dst):
self.assertEqual(len(capture), len(sent))
for i in range(len(capture)):
try:
tx = sent[i]
rx = capture[i]
tx_ip = tx[IPv6]
rx_ip = rx[IPv6]
self.assertEqual(rx_ip.src, tunnel_src)
self.assertEqual(rx_ip.dst, tunnel_dst)
rx_gre = GRE(str(rx_ip[IPv6].payload))
rx_ip = rx_gre[IPv6]
self.assertEqual(rx_ip.src, tx_ip.src)
self.assertEqual(rx_ip.dst, tx_ip.dst)
except:
self.logger.error(ppp("Rx:", rx))
self.logger.error(ppp("Tx:", tx))
raise
def verify_tunneled_l2o4(self, src_if, capture, sent,
tunnel_src, tunnel_dst):
self.assertEqual(len(capture), len(sent))
@@ -275,7 +337,7 @@ class TestGRE(VppTestCase):
raise
def test_gre(self):
""" GRE tunnel Tests """
""" GRE IPv4 tunnel Tests """
#
# Create an L3 GRE tunnel.
@@ -438,6 +500,79 @@ class TestGRE(VppTestCase):
self.pg0.unconfig_ip6()
def test_gre6(self):
""" GRE IPv6 tunnel Tests """
#
# Create an L3 GRE tunnel.
# - set it admin up
# - assign an IP Address
# - Add a route via the tunnel
#
gre_if = VppGre6Interface(self,
self.pg2.local_ip6,
"1002::1")
gre_if.add_vpp_config()
gre_if.admin_up()
gre_if.config_ip6()
route_via_tun = VppIpRoute(self, "4004::1", 128,
[VppRoutePath("0::0",
gre_if.sw_if_index,
is_ip6=1)],
is_ip6=1)
route_via_tun.add_vpp_config()
#
# Send a packet stream that is routed into the tunnel
# - they are all dropped since the tunnel's desintation IP
# is unresolved - or resolves via the default route - which
# which is a drop.
#
tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
self.pg2.add_stream(tx)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
self.pg2.assert_nothing_captured(
remark="GRE packets forwarded without DIP resolved")
#
# Add a route that resolves the tunnel's destination
#
route_tun_dst = VppIpRoute(self, "1002::1", 128,
[VppRoutePath(self.pg2.remote_ip6,
self.pg2.sw_if_index,
is_ip6=1)],
is_ip6=1)
route_tun_dst.add_vpp_config()
#
# Send a packet stream that is routed into the tunnel
# - packets are GRE encapped
#
self.vapi.cli("clear trace")
tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
self.pg2.add_stream(tx)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
rx = self.pg2.get_capture(len(tx))
self.verify_tunneled_6o6(self.pg2, rx, tx,
self.pg2.local_ip6, "1002::1")
#
# test case cleanup
#
route_tun_dst.remove_vpp_config()
route_via_tun.remove_vpp_config()
gre_if.remove_vpp_config()
self.pg2.unconfig_ip6()
def test_gre_vrf(self):
""" GRE tunnel VRF Tests """
+35
View File
@@ -34,3 +34,38 @@ class VppGreInterface(VppInterface):
r = self.test.vapi.gre_tunnel_add_del(s, d,
outer_fib_id=self.t_outer_fib,
is_add=0)
class VppGre6Interface(VppInterface):
"""
VPP GRE IPv6 interface
"""
def __init__(self, test, src_ip, dst_ip, outer_fib_id=0, is_teb=0):
""" Create VPP loopback interface """
self._sw_if_index = 0
super(VppGre6Interface, self).__init__(test)
self._test = test
self.t_src = src_ip
self.t_dst = dst_ip
self.t_outer_fib = outer_fib_id
self.t_is_teb = is_teb
def add_vpp_config(self):
s = socket.inet_pton(socket.AF_INET6, self.t_src)
d = socket.inet_pton(socket.AF_INET6, self.t_dst)
r = self.test.vapi.gre_tunnel_add_del(s, d,
outer_fib_id=self.t_outer_fib,
is_teb=self.t_is_teb,
is_ip6=1)
self._sw_if_index = r.sw_if_index
self.generate_remote_hosts()
def remove_vpp_config(self):
s = socket.inet_pton(socket.AF_INET6, self.t_src)
d = socket.inet_pton(socket.AF_INET6, self.t_dst)
self.unconfig()
r = self.test.vapi.gre_tunnel_add_del(s, d,
outer_fib_id=self.t_outer_fib,
is_add=0,
is_ip6=1)