IPIP: Add IP{v4,v6} over IP{v4,v6} configured tunnel support.
Change-Id: I166301c9e2388bae5f70ec0179d663a2703e27f5 Signed-off-by: Ole Troan <ot@cisco.com>
This commit is contained in:
+4
-5
@@ -139,16 +139,15 @@ M: Andrew Yourtchenko <ayourtch@gmail.com>
|
||||
F: src/plugins/acl/
|
||||
F: src/plugins/acl.am
|
||||
|
||||
VNET IPIP
|
||||
M: Ole Troan <otroan@employees.org>
|
||||
F: src/vnet/ipip/
|
||||
|
||||
Plugin - flowprobe
|
||||
M: Ole Troan <otroan@employees.org>
|
||||
F: src/plugins/flowprobe/
|
||||
F: src/plugins/flowprobe.am
|
||||
|
||||
Plugin - SIXRD
|
||||
M: Ole Troan <ot@cisco.com>
|
||||
F: src/plugins/sixrd/
|
||||
F: src/plugins/sixrd.am
|
||||
|
||||
Plugin - GTPU
|
||||
M: Hongjun Ni <hongjun.ni@intel.com>
|
||||
F: src/plugins/gtpu/
|
||||
|
||||
@@ -226,7 +226,6 @@ PLUGIN_ENABLED(marvell)
|
||||
PLUGIN_ENABLED(memif)
|
||||
PLUGIN_ENABLED(pppoe)
|
||||
PLUGIN_ENABLED(nat)
|
||||
PLUGIN_ENABLED(sixrd)
|
||||
PLUGIN_ENABLED(srv6ad)
|
||||
PLUGIN_ENABLED(srv6am)
|
||||
PLUGIN_ENABLED(srv6as)
|
||||
|
||||
@@ -83,10 +83,6 @@ if ENABLE_PPPOE_PLUGIN
|
||||
include pppoe.am
|
||||
endif
|
||||
|
||||
if ENABLE_SIXRD_PLUGIN
|
||||
include sixrd.am
|
||||
endif
|
||||
|
||||
if ENABLE_SRV6AD_PLUGIN
|
||||
include srv6_ad.am
|
||||
endif
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
# Copyright (c) 2015 Cisco and/or its affiliates.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
libsixrd_plugin_la_SOURCES = \
|
||||
sixrd/sixrd.c \
|
||||
sixrd/ip4_sixrd.c
|
||||
|
||||
noinst_HEADERS += \
|
||||
sixrd/sixrd.h \
|
||||
sixrd/sixrd_all_api_h.h \
|
||||
sixrd/sixrd_msg_enum.h
|
||||
|
||||
vppplugins_LTLIBRARIES += libsixrd_plugin.la
|
||||
|
||||
API_FILES += sixrd/sixrd.api
|
||||
|
||||
# vi:syntax=automake
|
||||
@@ -1,165 +0,0 @@
|
||||
/*---------------------------------------------------------------------------
|
||||
* Copyright (c) 2009-2014 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "sixrd.h"
|
||||
|
||||
vlib_node_registration_t ip4_sixrd_node;
|
||||
|
||||
typedef enum {
|
||||
IP4_SIXRD_NEXT_IP6_LOOKUP,
|
||||
IP4_SIXRD_NEXT_DROP,
|
||||
IP4_SIXRD_N_NEXT,
|
||||
} ip4_sixrd_next_t;
|
||||
|
||||
typedef struct {
|
||||
u32 tunnel_id;
|
||||
u32 length;
|
||||
ip4_address_t src;
|
||||
ip4_address_t dst;
|
||||
} sixrd_rx_trace_t;
|
||||
|
||||
u8 *
|
||||
format_sixrd_rx_trace (u8 * s, va_list * args)
|
||||
{
|
||||
CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
|
||||
CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
|
||||
sixrd_rx_trace_t *t = va_arg (*args, sixrd_rx_trace_t *);
|
||||
|
||||
s = format (s, "6RD: tunnel %d len %d src %U dst %U",
|
||||
t->tunnel_id, clib_net_to_host_u16 (t->length),
|
||||
format_ip4_address, &t->src, format_ip4_address, &t->dst);
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* ip4_sixrd_sec_check
|
||||
*/
|
||||
static_always_inline void
|
||||
ip4_sixrd_sec_check(sixrd_tunnel_t *t, ip4_address_t sa4,
|
||||
ip6_address_t sa6, u8 *error) {
|
||||
if (PREDICT_FALSE(sixrd_get_addr_net(t, sa6.as_u64[0]) != sa4.as_u32))
|
||||
*error = SIXRD_ERROR_SEC_CHECK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ip4_sixrd
|
||||
*/
|
||||
uword ip4_sixrd(vlib_main_t *vm, vlib_node_runtime_t *node,
|
||||
vlib_frame_t *frame) {
|
||||
u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
|
||||
vlib_node_runtime_t *error_node = vlib_node_get_runtime(vm, ip4_sixrd_node.index);
|
||||
vnet_interface_main_t * im = &vnet_get_main()->interface_main;
|
||||
u32 thread_index = vlib_get_thread_index ();
|
||||
|
||||
from = vlib_frame_vector_args(frame);
|
||||
n_left_from = frame->n_vectors;
|
||||
next_index = node->cached_next_index;
|
||||
while (n_left_from > 0) {
|
||||
vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
|
||||
|
||||
/* Single loop */
|
||||
while (n_left_from > 0 && n_left_to_next > 0) {
|
||||
u32 pi0;
|
||||
vlib_buffer_t *p0;
|
||||
u8 error0 = SIXRD_ERROR_NONE;
|
||||
sixrd_tunnel_t *t0 = 0;
|
||||
ip4_header_t *ip40;
|
||||
ip6_header_t *ip60;
|
||||
u32 tunnel_sw_if_index = ~0;
|
||||
u32 next0 = IP4_SIXRD_NEXT_DROP;
|
||||
|
||||
pi0 = to_next[0] = from[0];
|
||||
from += 1;
|
||||
n_left_from -= 1;
|
||||
to_next += 1;
|
||||
n_left_to_next -= 1;
|
||||
|
||||
p0 = vlib_get_buffer(vm, pi0);
|
||||
ip40 = vlib_buffer_get_current(p0);
|
||||
|
||||
/* Throw away anything that isn't IP in IP. */
|
||||
if (PREDICT_TRUE(ip40->protocol == IP_PROTOCOL_IPV6 && clib_net_to_host_u16(ip40->length) >= 60)) {
|
||||
vlib_buffer_advance(p0, sizeof(ip4_header_t));
|
||||
t0 = ip4_sixrd_get_tunnel(vnet_buffer(p0)->ip.adj_index[VLIB_TX], (ip4_address_t *)&ip40->dst_address, &error0);
|
||||
} else {
|
||||
error0 = SIXRD_ERROR_BAD_PROTOCOL;
|
||||
}
|
||||
|
||||
if (!t0) {
|
||||
error0 = SIXRD_ERROR_NO_TUNNEL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
tunnel_sw_if_index = t0->sw_if_index;
|
||||
|
||||
/* SIXRD inbound security check */
|
||||
if (t0->security_check) {
|
||||
ip60 = vlib_buffer_get_current(p0);
|
||||
ip4_sixrd_sec_check(t0, ip40->src_address, ip60->src_address, &error0);
|
||||
}
|
||||
next0 = error0 == SIXRD_ERROR_NONE ? IP4_SIXRD_NEXT_IP6_LOOKUP
|
||||
: IP4_SIXRD_NEXT_DROP;
|
||||
|
||||
if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED)) {
|
||||
sixrd_rx_trace_t *tr = vlib_add_trace(vm, node, p0, sizeof(*tr));
|
||||
tr->tunnel_id = tunnel_sw_if_index;
|
||||
tr->length = ip40->length;
|
||||
tr->src.as_u32 = ip40->src_address.as_u32;
|
||||
tr->dst.as_u32 = ip40->dst_address.as_u32;
|
||||
}
|
||||
|
||||
error:
|
||||
if (PREDICT_TRUE(error0 == SIXRD_ERROR_NONE)) {
|
||||
u32 len = vlib_buffer_length_in_chain (vm, p0);
|
||||
vlib_increment_combined_counter (im->combined_sw_if_counters
|
||||
+ VNET_INTERFACE_COUNTER_RX,
|
||||
thread_index,
|
||||
tunnel_sw_if_index,
|
||||
1 /* packets */ ,
|
||||
len /* bytes */ );
|
||||
|
||||
vnet_buffer (p0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;
|
||||
} else {
|
||||
p0->error = error_node->errors[error0];
|
||||
}
|
||||
vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
|
||||
n_left_to_next, pi0, next0);
|
||||
}
|
||||
vlib_put_next_frame(vm, node, next_index, n_left_to_next);
|
||||
}
|
||||
return frame->n_vectors;
|
||||
}
|
||||
|
||||
static char *sixrd_error_strings[] = {
|
||||
#define _(sym, string) string,
|
||||
foreach_sixrd_error
|
||||
#undef _
|
||||
};
|
||||
|
||||
VLIB_REGISTER_NODE(ip4_sixrd_node) = {
|
||||
.function = ip4_sixrd,
|
||||
.name = "ip4-sixrd",
|
||||
.vector_size = sizeof(u32),
|
||||
.format_trace = format_sixrd_rx_trace,
|
||||
.n_errors = SIXRD_N_ERROR,
|
||||
.error_strings = sixrd_error_strings,
|
||||
.n_next_nodes = IP4_SIXRD_N_NEXT,
|
||||
.next_nodes =
|
||||
{
|
||||
[IP4_SIXRD_NEXT_IP6_LOOKUP] = "ip6-lookup",
|
||||
[IP4_SIXRD_NEXT_DROP] = "error-drop",
|
||||
},
|
||||
};
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
option version = "2.0.0";
|
||||
|
||||
define sixrd_add_tunnel
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 fib_index;
|
||||
u8 ip6_prefix[16];
|
||||
u8 ip4_prefix[4];
|
||||
u8 ip4_src[4];
|
||||
u8 ip6_prefix_len;
|
||||
u8 ip4_prefix_len;
|
||||
u16 mtu;
|
||||
u8 security_check;
|
||||
};
|
||||
|
||||
define sixrd_add_tunnel_reply
|
||||
{
|
||||
u32 context;
|
||||
u32 sw_if_index;
|
||||
i32 retval;
|
||||
};
|
||||
|
||||
autoreply define sixrd_del_tunnel
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 sw_if_index;
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/* Include the generated file, see BUILT_SOURCES in Makefile.am */
|
||||
#include <sixrd/sixrd.api.h>
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef included_sixrd_msg_enum_h
|
||||
#define included_sixrd_msg_enum_h
|
||||
|
||||
#include <vppinfra/byte_order.h>
|
||||
|
||||
#define vl_msg_id(n,h) n,
|
||||
typedef enum {
|
||||
#include <sixrd/sixrd_all_api_h.h>
|
||||
/* We'll want to know how many messages IDs we need... */
|
||||
VL_MSG_FIRST_AVAILABLE,
|
||||
} vl_msg_id_t;
|
||||
#undef vl_msg_id
|
||||
|
||||
#endif
|
||||
+15
@@ -567,6 +567,21 @@ nobase_include_HEADERS += \
|
||||
|
||||
API_FILES += vnet/gre/gre.api
|
||||
|
||||
########################################
|
||||
# Tunnel protocol: ipip
|
||||
########################################
|
||||
libvnet_la_SOURCES += \
|
||||
vnet/ipip/ipip.c \
|
||||
vnet/ipip/node.c \
|
||||
vnet/ipip/sixrd.c \
|
||||
vnet/ipip/ipip_api.c \
|
||||
vnet/ipip/ipip_cli.c
|
||||
|
||||
nobase_include_HEADERS += \
|
||||
vnet/ipip/ipip.h
|
||||
|
||||
API_FILES += vnet/ipip/ipip.api
|
||||
|
||||
########################################
|
||||
# Tunnel protocol: l2tpv3
|
||||
########################################
|
||||
|
||||
@@ -81,6 +81,7 @@ typedef CLIB_PACKED (union {
|
||||
#define ip46_address_is_zero(ip46) (((ip46)->as_u64[0] == 0) && ((ip46)->as_u64[1] == 0))
|
||||
#define ip46_address_is_equal(a1, a2) (((a1)->as_u64[0] == (a2)->as_u64[0]) \
|
||||
&& ((a1)->as_u64[1] == (a2)->as_u64[1]))
|
||||
#define ip46_address_initializer {{{ 0 }}}
|
||||
|
||||
always_inline ip46_address_t
|
||||
to_ip46 (u32 is_ipv6, u8 * buf)
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
option version = "1.0.0";
|
||||
|
||||
/** \brief Create or delete an IPIP tunnel
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param is_ipv6 - Use 0 for IPv4, 1 for IPv6
|
||||
@param instance - optional unique custom device instance, else ~0.
|
||||
@param src_address - Source IP address
|
||||
@param dst_address - Destination IP address, can be multicast
|
||||
@param fib_index - Encap FIB table ID
|
||||
*/
|
||||
define ipip_add_tunnel
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u8 is_ipv6;
|
||||
u32 instance; /* If non-~0, specifies a custom dev instance */
|
||||
u8 src_address[16];
|
||||
u8 dst_address[16];
|
||||
u32 fib_index;
|
||||
};
|
||||
|
||||
define ipip_add_tunnel_reply
|
||||
{
|
||||
u32 context;
|
||||
i32 retval;
|
||||
u32 sw_if_index;
|
||||
};
|
||||
|
||||
autoreply define ipip_del_tunnel
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 sw_if_index;
|
||||
};
|
||||
|
||||
define ipip_6rd_add_tunnel
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 fib_index;
|
||||
u8 ip6_prefix[16];
|
||||
u8 ip4_prefix[4];
|
||||
u8 ip4_src[4];
|
||||
u8 ip6_prefix_len;
|
||||
u8 ip4_prefix_len;
|
||||
u8 security_check;
|
||||
};
|
||||
|
||||
define ipip_6rd_add_tunnel_reply
|
||||
{
|
||||
u32 context;
|
||||
i32 retval;
|
||||
u32 sw_if_index;
|
||||
};
|
||||
|
||||
autoreply define ipip_6rd_del_tunnel
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 sw_if_index;
|
||||
};
|
||||
|
||||
define ipip_tunnel_dump
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 sw_if_index;
|
||||
};
|
||||
|
||||
define ipip_tunnel_details
|
||||
{
|
||||
u32 context;
|
||||
u32 sw_if_index;
|
||||
u32 instance;
|
||||
u8 is_ipv6;
|
||||
u8 src_address[16];
|
||||
u8 dst_address[16];
|
||||
u32 fib_index;
|
||||
};
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* ipip.h: types/functions for ipip.
|
||||
*
|
||||
* Copyright (c) 2018 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or aipiped to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef included_ipip_h
|
||||
#define included_ipip_h
|
||||
|
||||
#include <vnet/adj/adj_types.h>
|
||||
#include <vnet/ip/ip6_packet.h>
|
||||
#include <vnet/ip/format.h>
|
||||
#include <vnet/ip/ip.h>
|
||||
#include <vnet/vnet.h>
|
||||
|
||||
extern vnet_hw_interface_class_t ipip_hw_interface_class;
|
||||
|
||||
#define foreach_ipip_error \
|
||||
/* Must be first. */ \
|
||||
_(DECAP_PKTS, "packets decapsulated") \
|
||||
_(BAD_PROTOCOL, "bad protocol") \
|
||||
_(NO_TUNNEL, "no tunnel")
|
||||
|
||||
typedef enum
|
||||
{
|
||||
#define _(sym, str) IPIP_ERROR_##sym,
|
||||
foreach_ipip_error
|
||||
#undef _
|
||||
IPIP_N_ERROR,
|
||||
} ipip_error_t;
|
||||
|
||||
/**
|
||||
* @brief IPIP Tunnel key
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
IPIP_TRANSPORT_IP4,
|
||||
IPIP_TRANSPORT_IP6,
|
||||
} ipip_transport_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ipip_transport_t transport;
|
||||
u32 fib_index;
|
||||
ip46_address_t src;
|
||||
ip46_address_t dst;
|
||||
} __attribute__ ((packed)) ipip_tunnel_key_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IPIP_MODE_P2P = 0,
|
||||
IPIP_MODE_6RD,
|
||||
} ipip_mode_t;
|
||||
|
||||
/**
|
||||
* @brief A representation of a IPIP tunnel
|
||||
*/
|
||||
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;
|
||||
u32 hw_if_index;
|
||||
u32 sw_if_index;
|
||||
u32 dev_instance; /* Real device instance in tunnel vector */
|
||||
u32 user_instance; /* Instance name being shown to user */
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
fib_node_t node;
|
||||
fib_node_index_t fib_entry_index;
|
||||
u32 sibling_index;
|
||||
} p2p;
|
||||
struct
|
||||
{
|
||||
ip6_address_t ip6_prefix;
|
||||
ip4_address_t ip4_prefix;
|
||||
u8 ip6_prefix_len;
|
||||
u8 ip4_prefix_len;
|
||||
u8 shift;
|
||||
bool security_check;
|
||||
} sixrd;
|
||||
};
|
||||
} ipip_tunnel_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ipip_tunnel_t *tunnels;
|
||||
uword *tunnel_by_key;
|
||||
u32 *tunnel_index_by_sw_if_index;
|
||||
fib_node_type_t fib_node_type;
|
||||
|
||||
/* convenience */
|
||||
vlib_main_t *vlib_main;
|
||||
vnet_main_t *vnet_main;
|
||||
|
||||
/* Record used instances */
|
||||
uword *instance_used;
|
||||
|
||||
bool ip4_protocol_registered;
|
||||
bool ip6_protocol_registered;
|
||||
} ipip_main_t;
|
||||
|
||||
extern ipip_main_t ipip_main;
|
||||
extern vlib_node_registration_t ipip4_input_node;
|
||||
extern vlib_node_registration_t ipip6_input_node;
|
||||
|
||||
/*
|
||||
* sixrd_get_addr_net
|
||||
*/
|
||||
static_always_inline u32
|
||||
sixrd_get_addr_net (const ipip_tunnel_t * t, u64 dal)
|
||||
{
|
||||
/* 1:1 mode */
|
||||
if (t->sixrd.ip4_prefix_len == 32)
|
||||
return (t->sixrd.ip4_prefix.as_u32);
|
||||
|
||||
dal = clib_net_to_host_u64 (dal);
|
||||
|
||||
/* Grab 32 - ip4_prefix_len bits out of IPv6 address from offset
|
||||
* ip6_prefix_len */
|
||||
u32 mask = ~(~0ULL << (32 - t->sixrd.ip4_prefix_len));
|
||||
u32 ip4 =
|
||||
clib_net_to_host_u32 (t->sixrd.
|
||||
ip4_prefix.as_u32) | ((u32) (dal >> t->sixrd.
|
||||
shift) & mask);
|
||||
return clib_host_to_net_u32 (ip4);
|
||||
}
|
||||
|
||||
int ipip_add_tunnel (ipip_transport_t transport, u32 instance,
|
||||
ip46_address_t * src, ip46_address_t * dst,
|
||||
u32 fib_index, 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,
|
||||
ip4_address_t * ip4_src, bool security_check,
|
||||
u32 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);
|
||||
ipip_tunnel_t *ipip_tunnel_db_find_by_sw_if_index (u32 sw_if_index);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* ipip_api.c - ipip api
|
||||
*
|
||||
* Copyright (c) 2018 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <vlibmemory/api.h>
|
||||
#include <vnet/api_errno.h>
|
||||
#include <vnet/fib/fib_table.h>
|
||||
#include <vnet/interface.h>
|
||||
#include <vnet/ipip/ipip.h>
|
||||
#include <vnet/vnet.h>
|
||||
#include <vnet/vnet_msg_enum.h>
|
||||
|
||||
#define vl_typedefs /* define message structures */
|
||||
#include <vnet/vnet_all_api_h.h>
|
||||
#undef vl_typedefs
|
||||
|
||||
#define vl_endianfun /* define message structures */
|
||||
#include <vnet/vnet_all_api_h.h>
|
||||
#undef vl_endianfun
|
||||
|
||||
/* instantiate all the print functions we know about */
|
||||
#define vl_print(handle, ...) vlib_cli_output(handle, __VA_ARGS__)
|
||||
#define vl_printfun
|
||||
#include <vnet/vnet_all_api_h.h>
|
||||
#undef vl_printfun
|
||||
|
||||
#include <vlibapi/api_helper_macros.h>
|
||||
|
||||
#define foreach_vpe_api_msg \
|
||||
_(IPIP_ADD_TUNNEL, ipip_add_tunnel) \
|
||||
_(IPIP_DEL_TUNNEL, ipip_del_tunnel) \
|
||||
_(IPIP_6RD_ADD_TUNNEL, ipip_6rd_add_tunnel) \
|
||||
_(IPIP_6RD_DEL_TUNNEL, ipip_6rd_del_tunnel) \
|
||||
_(IPIP_TUNNEL_DUMP, ipip_tunnel_dump)
|
||||
|
||||
static void
|
||||
vl_api_ipip_add_tunnel_t_handler (vl_api_ipip_add_tunnel_t * mp)
|
||||
{
|
||||
vl_api_ipip_add_tunnel_reply_t *rmp;
|
||||
int rv = 0;
|
||||
u32 sw_if_index = ~0;
|
||||
ip46_address_t src = ip46_address_initializer, dst =
|
||||
ip46_address_initializer;
|
||||
|
||||
/* ip addresses sent in network byte order */
|
||||
if (mp->is_ipv6)
|
||||
{
|
||||
clib_memcpy (&src.ip6, mp->src_address, 16);
|
||||
clib_memcpy (&dst.ip6, mp->dst_address, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
clib_memcpy (&src.ip4, mp->src_address, 4);
|
||||
clib_memcpy (&dst.ip4, mp->dst_address, 4);
|
||||
}
|
||||
|
||||
rv = ipip_add_tunnel (mp->is_ipv6 ? IPIP_TRANSPORT_IP6 : IPIP_TRANSPORT_IP4,
|
||||
ntohl (mp->instance), &src, &dst,
|
||||
ntohl (mp->fib_index), &sw_if_index);
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
REPLY_MACRO2(VL_API_IPIP_ADD_TUNNEL_REPLY,
|
||||
({ rmp->sw_if_index = ntohl(sw_if_index); }));
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_ipip_del_tunnel_t_handler (vl_api_ipip_del_tunnel_t * mp)
|
||||
{
|
||||
vl_api_ipip_del_tunnel_reply_t *rmp;
|
||||
|
||||
int rv = ipip_del_tunnel (ntohl (mp->sw_if_index));
|
||||
|
||||
REPLY_MACRO (VL_API_IPIP_DEL_TUNNEL_REPLY);
|
||||
}
|
||||
|
||||
static void
|
||||
send_ipip_tunnel_details (ipip_tunnel_t * t,
|
||||
vl_api_registration_t * reg, u32 context)
|
||||
{
|
||||
vl_api_ipip_tunnel_details_t *rmp;
|
||||
bool is_ipv6 = t->transport == IPIP_TRANSPORT_IP6 ? true : false;
|
||||
fib_table_t *ft;
|
||||
|
||||
rmp = vl_msg_api_alloc (sizeof (*rmp));
|
||||
memset (rmp, 0, sizeof (*rmp));
|
||||
rmp->_vl_msg_id = htons (VL_API_IPIP_TUNNEL_DETAILS);
|
||||
if (is_ipv6)
|
||||
{
|
||||
clib_memcpy (rmp->src_address, &t->tunnel_src.ip6.as_u8, 16);
|
||||
clib_memcpy (rmp->dst_address, &t->tunnel_dst.ip6.as_u8, 16);
|
||||
ft = fib_table_get (t->fib_index, FIB_PROTOCOL_IP6);
|
||||
rmp->fib_index = htonl (ft->ft_table_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
clib_memcpy (rmp->src_address, &t->tunnel_src.ip4.as_u8, 4);
|
||||
clib_memcpy (rmp->dst_address, &t->tunnel_dst.ip4.as_u8, 4);
|
||||
ft = fib_table_get (t->fib_index, FIB_PROTOCOL_IP4);
|
||||
rmp->fib_index = htonl (ft->ft_table_id);
|
||||
}
|
||||
rmp->instance = htonl (t->user_instance);
|
||||
rmp->sw_if_index = htonl (t->sw_if_index);
|
||||
rmp->context = context;
|
||||
rmp->is_ipv6 = is_ipv6;
|
||||
|
||||
vl_api_send_msg (reg, (u8 *) rmp);
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_ipip_tunnel_dump_t_handler (vl_api_ipip_tunnel_dump_t * mp)
|
||||
{
|
||||
vl_api_registration_t *reg;
|
||||
ipip_main_t *gm = &ipip_main;
|
||||
ipip_tunnel_t *t;
|
||||
u32 sw_if_index;
|
||||
|
||||
reg = vl_api_client_index_to_registration (mp->client_index);
|
||||
if (!reg)
|
||||
return;
|
||||
|
||||
sw_if_index = ntohl (mp->sw_if_index);
|
||||
|
||||
if (sw_if_index == ~0)
|
||||
{
|
||||
/* *INDENT-OFF* */
|
||||
pool_foreach(t, gm->tunnels,
|
||||
({ send_ipip_tunnel_details(t, reg, mp->context); }));
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
else
|
||||
{
|
||||
t = ipip_tunnel_db_find_by_sw_if_index (sw_if_index);
|
||||
if (t)
|
||||
send_ipip_tunnel_details (t, reg, mp->context);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_ipip_6rd_add_tunnel_t_handler (vl_api_ipip_6rd_add_tunnel_t * mp)
|
||||
{
|
||||
vl_api_ipip_6rd_add_tunnel_reply_t *rmp;
|
||||
u32 sixrd_tunnel_index;
|
||||
|
||||
int rv = sixrd_add_tunnel ((ip6_address_t *) & mp->ip6_prefix,
|
||||
mp->ip6_prefix_len,
|
||||
(ip4_address_t *) & mp->ip4_prefix,
|
||||
mp->ip4_prefix_len,
|
||||
(ip4_address_t *) & mp->ip4_src,
|
||||
mp->security_check,
|
||||
ntohl (mp->fib_index), &sixrd_tunnel_index);
|
||||
|
||||
REPLY_MACRO2 (VL_API_IPIP_6RD_ADD_TUNNEL_REPLY, (
|
||||
{
|
||||
rmp->sw_if_index =
|
||||
htonl
|
||||
(sixrd_tunnel_index);}));
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_ipip_6rd_del_tunnel_t_handler (vl_api_ipip_6rd_del_tunnel_t * mp)
|
||||
{
|
||||
vl_api_ipip_6rd_del_tunnel_reply_t *rmp;
|
||||
|
||||
int rv = sixrd_del_tunnel (ntohl (mp->sw_if_index));
|
||||
|
||||
REPLY_MACRO (VL_API_IPIP_6RD_DEL_TUNNEL_REPLY);
|
||||
}
|
||||
|
||||
/*
|
||||
* ipip_api_hookup
|
||||
* Add vpe's API message handlers to the table.
|
||||
* vlib has alread mapped shared memory and
|
||||
* added the client registration handlers.
|
||||
* See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
|
||||
*/
|
||||
#define vl_msg_name_crc_list
|
||||
#include <vnet/vnet_all_api_h.h>
|
||||
#undef vl_msg_name_crc_list
|
||||
|
||||
static void
|
||||
setup_message_id_table (api_main_t * am)
|
||||
{
|
||||
#define _(id, n, crc) vl_msg_api_add_msg_name_crc(am, #n "_" #crc, id);
|
||||
foreach_vl_msg_name_crc_ipip;
|
||||
#undef _
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
ipip_api_hookup (vlib_main_t * vm)
|
||||
{
|
||||
api_main_t *am = &api_main;
|
||||
|
||||
#define _(N, n) \
|
||||
vl_msg_api_set_handlers(VL_API_##N, #n, vl_api_##n##_t_handler, \
|
||||
vl_noop_handler, vl_api_##n##_t_endian, \
|
||||
vl_api_##n##_t_print, sizeof(vl_api_##n##_t), 1);
|
||||
foreach_vpe_api_msg;
|
||||
#undef _
|
||||
|
||||
/*
|
||||
* Set up the (msg_name, crc, message-id) table
|
||||
*/
|
||||
setup_message_id_table (am);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VLIB_API_INIT_FUNCTION (ipip_api_hookup);
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* node.c: ipip packet processing
|
||||
*
|
||||
* Copyright (c) 2018 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or aipiped to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <vlib/vlib.h>
|
||||
#include <vnet/ipip/ipip.h>
|
||||
#include <vnet/ip/ip6_packet.h>
|
||||
#include <vnet/mpls/mpls.h>
|
||||
#include <vnet/pg/pg.h>
|
||||
#include <vppinfra/sparse_vec.h>
|
||||
|
||||
#define foreach_ipip_input_next \
|
||||
_(PUNT, "error-punt") \
|
||||
_(DROP, "error-drop") \
|
||||
_(IP4_INPUT, "ip4-input") \
|
||||
_(IP6_INPUT, "ip6-input")
|
||||
|
||||
typedef enum
|
||||
{
|
||||
#define _(s, n) IPIP_INPUT_NEXT_##s,
|
||||
foreach_ipip_input_next
|
||||
#undef _
|
||||
IPIP_INPUT_N_NEXT,
|
||||
} ipip_input_next_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 tunnel_id;
|
||||
u32 length;
|
||||
ip46_address_t src;
|
||||
ip46_address_t dst;
|
||||
u8 is_ipv6;
|
||||
} ipip_rx_trace_t;
|
||||
|
||||
u8 *
|
||||
format_ipip_rx_trace (u8 * s, va_list * args)
|
||||
{
|
||||
CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
|
||||
CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
|
||||
ipip_rx_trace_t *t = va_arg (*args, ipip_rx_trace_t *);
|
||||
|
||||
s = format (s, "IPIP: tunnel %d len %d src %U dst %U", t->tunnel_id,
|
||||
clib_net_to_host_u16 (t->length), format_ip46_address, &t->src,
|
||||
IP46_TYPE_ANY, format_ip46_address, &t->dst, IP46_TYPE_ANY);
|
||||
return s;
|
||||
}
|
||||
|
||||
always_inline uword
|
||||
ipip_input (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
vlib_frame_t * from_frame, bool is_ipv6)
|
||||
{
|
||||
ipip_main_t *gm = &ipip_main;
|
||||
u32 n_left_from, next_index, *from, *to_next, n_left_to_next;
|
||||
u32 tunnel_sw_if_index = ~0;
|
||||
u32 thread_index = vlib_get_thread_index ();
|
||||
u32 len;
|
||||
vnet_interface_main_t *im = &gm->vnet_main->interface_main;
|
||||
|
||||
from = vlib_frame_vector_args (from_frame);
|
||||
n_left_from = from_frame->n_vectors;
|
||||
next_index = node->cached_next_index;
|
||||
while (n_left_from > 0)
|
||||
{
|
||||
vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
|
||||
|
||||
while (n_left_from > 0 && n_left_to_next > 0)
|
||||
{
|
||||
u32 bi0;
|
||||
vlib_buffer_t *b0;
|
||||
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];
|
||||
from += 1;
|
||||
n_left_from -= 1;
|
||||
to_next += 1;
|
||||
n_left_to_next -= 1;
|
||||
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
|
||||
if (is_ipv6)
|
||||
{
|
||||
ip60 = vlib_buffer_get_current (b0);
|
||||
vlib_buffer_advance (b0, sizeof (*ip60));
|
||||
ip_set (&src0, &ip60->src_address, false);
|
||||
ip_set (&dst0, &ip60->dst_address, false);
|
||||
inner_protocol0 = ip60->protocol;
|
||||
transport0 = IPIP_TRANSPORT_IP6;
|
||||
}
|
||||
else
|
||||
{
|
||||
ip40 = vlib_buffer_get_current (b0);
|
||||
vlib_buffer_advance (b0, sizeof (*ip40));
|
||||
ip_set (&src0, &ip40->src_address, true);
|
||||
ip_set (&dst0, &ip40->dst_address, true);
|
||||
inner_protocol0 = ip40->protocol;
|
||||
transport0 = 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);
|
||||
t0 = ipip_tunnel_db_find (&key0);
|
||||
if (!t0)
|
||||
{
|
||||
next0 = IPIP_INPUT_NEXT_DROP;
|
||||
b0->error = node->errors[IPIP_ERROR_NO_TUNNEL];
|
||||
goto drop;
|
||||
}
|
||||
}
|
||||
tunnel_sw_if_index = t0->sw_if_index;
|
||||
|
||||
len = vlib_buffer_length_in_chain (vm, b0);
|
||||
vnet_buffer (b0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;
|
||||
|
||||
if (inner_protocol0 == IP_PROTOCOL_IPV6)
|
||||
next0 = IPIP_INPUT_NEXT_IP6_INPUT;
|
||||
else if (inner_protocol0 == IP_PROTOCOL_IP_IN_IP)
|
||||
next0 = IPIP_INPUT_NEXT_IP4_INPUT;
|
||||
|
||||
if (!is_ipv6 && t0->mode == IPIP_MODE_6RD
|
||||
&& t0->sixrd.security_check)
|
||||
{
|
||||
ip6_header_t *inner_ip60 = vlib_buffer_get_current (b0);
|
||||
if (sixrd_get_addr_net (t0, inner_ip60->src_address.as_u64[0])
|
||||
!= ip40->src_address.as_u32)
|
||||
{
|
||||
next0 = IPIP_INPUT_NEXT_DROP;
|
||||
b0->error = node->errors[IPIP_ERROR_NO_TUNNEL];
|
||||
goto drop;
|
||||
}
|
||||
}
|
||||
|
||||
vlib_increment_combined_counter (im->combined_sw_if_counters +
|
||||
VNET_INTERFACE_COUNTER_RX,
|
||||
thread_index, tunnel_sw_if_index,
|
||||
1 /* packets */ ,
|
||||
len /* bytes */ );
|
||||
|
||||
drop:
|
||||
if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
|
||||
{
|
||||
ipip_rx_trace_t *tr =
|
||||
vlib_add_trace (vm, node, b0, sizeof (*tr));
|
||||
tr->tunnel_id = tunnel_sw_if_index;
|
||||
if (is_ipv6)
|
||||
{
|
||||
tr->length = ip60->payload_length;
|
||||
tr->src.ip6.as_u64[0] = ip60->src_address.as_u64[0];
|
||||
tr->src.ip6.as_u64[1] = ip60->src_address.as_u64[1];
|
||||
tr->dst.ip6.as_u64[0] = ip60->dst_address.as_u64[0];
|
||||
tr->dst.ip6.as_u64[1] = ip60->dst_address.as_u64[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
tr->length = ip40->length;
|
||||
tr->src.ip4.as_u32 = ip40->src_address.as_u32;
|
||||
tr->dst.ip4.as_u32 = ip40->dst_address.as_u32;
|
||||
}
|
||||
}
|
||||
|
||||
vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
|
||||
n_left_to_next, bi0, next0);
|
||||
}
|
||||
|
||||
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
|
||||
}
|
||||
vlib_node_increment_counter (vm,
|
||||
!is_ipv6 ? ipip4_input_node.index :
|
||||
ipip6_input_node.index, IPIP_ERROR_DECAP_PKTS,
|
||||
from_frame->n_vectors);
|
||||
return from_frame->n_vectors;
|
||||
}
|
||||
|
||||
static uword
|
||||
ipip4_input (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
vlib_frame_t * from_frame)
|
||||
{
|
||||
return ipip_input (vm, node, from_frame, /* is_ip6 */ false);
|
||||
}
|
||||
|
||||
static uword
|
||||
ipip6_input (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
vlib_frame_t * from_frame)
|
||||
{
|
||||
return ipip_input (vm, node, from_frame, /* is_ip6 */ true);
|
||||
}
|
||||
|
||||
static char *ipip_error_strings[] = {
|
||||
#define _(sym,string) string,
|
||||
foreach_ipip_error
|
||||
#undef _
|
||||
};
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_REGISTER_NODE(ipip4_input_node) = {
|
||||
.function = ipip4_input,
|
||||
.name = "ipip4-input",
|
||||
/* Takes a vector of packets. */
|
||||
.vector_size = sizeof(u32),
|
||||
.n_errors = IPIP_N_ERROR,
|
||||
.error_strings = ipip_error_strings,
|
||||
.n_next_nodes = IPIP_INPUT_N_NEXT,
|
||||
.next_nodes =
|
||||
{
|
||||
#define _(s, n) [IPIP_INPUT_NEXT_##s] = n,
|
||||
foreach_ipip_input_next
|
||||
#undef _
|
||||
},
|
||||
.format_trace = format_ipip_rx_trace,
|
||||
};
|
||||
|
||||
VLIB_REGISTER_NODE(ipip6_input_node) = {
|
||||
.function = ipip6_input,
|
||||
.name = "ipip6-input",
|
||||
/* Takes a vector of packets. */
|
||||
.vector_size = sizeof(u32),
|
||||
.n_errors = IPIP_N_ERROR,
|
||||
.error_strings = ipip_error_strings,
|
||||
.n_next_nodes = IPIP_INPUT_N_NEXT,
|
||||
.next_nodes =
|
||||
{
|
||||
#define _(s, n) [IPIP_INPUT_NEXT_##s] = n,
|
||||
foreach_ipip_input_next
|
||||
#undef _
|
||||
},
|
||||
.format_trace = format_ipip_rx_trace,
|
||||
};
|
||||
|
||||
VLIB_NODE_FUNCTION_MULTIARCH(ipip4_input_node, ipip4_input)
|
||||
VLIB_NODE_FUNCTION_MULTIARCH(ipip6_input_node, ipip6_input)
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,41 +16,12 @@
|
||||
#include <stdbool.h>
|
||||
#include <vnet/fib/ip6_fib.h>
|
||||
#include <vnet/ip/ip.h>
|
||||
#include <vnet/ipip/ipip.h>
|
||||
#include <vnet/vnet.h>
|
||||
#include <vppinfra/error.h>
|
||||
|
||||
#define SIXRD_DEFAULT_MTU 1480 /* 1500 - IPv4 header */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 fib_index;
|
||||
u32 hw_if_index;
|
||||
u32 sw_if_index;
|
||||
u32 tunnel_index;
|
||||
ip6_address_t ip6_prefix;
|
||||
ip4_address_t ip4_prefix;
|
||||
ip4_address_t ip4_src;
|
||||
u8 ip6_prefix_len;
|
||||
u8 ip4_prefix_len;
|
||||
|
||||
/* helpers */
|
||||
u8 shift;
|
||||
|
||||
u16 mtu;
|
||||
bool security_check;
|
||||
} sixrd_tunnel_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u16 msg_id_base;
|
||||
|
||||
/* pool of SIXRD domains */
|
||||
sixrd_tunnel_t *tunnels;
|
||||
u32 *tunnel_index_by_sw_if_index;
|
||||
uword *tunnel_by_ip;
|
||||
|
||||
} sixrd_main_t;
|
||||
|
||||
#define foreach_sixrd_error \
|
||||
/* Must be first. */ \
|
||||
_(NONE, "valid SIXRD packets") \
|
||||
@@ -69,28 +40,6 @@ typedef enum
|
||||
|
||||
extern sixrd_main_t sixrd_main;
|
||||
|
||||
/*
|
||||
* sixrd_get_addr
|
||||
*/
|
||||
static_always_inline u32
|
||||
sixrd_get_addr_net (const sixrd_tunnel_t * t, u64 dal)
|
||||
{
|
||||
/* 1:1 mode */
|
||||
if (t->ip4_prefix_len == 32)
|
||||
return (t->ip4_prefix.as_u32);
|
||||
|
||||
dal = clib_net_to_host_u64 (dal);
|
||||
|
||||
/* Grab 32 - ip4_prefix_len bits out of IPv6 address from offset
|
||||
* ip6_prefix_len */
|
||||
u32 mask = ~(~0ULL << (32 - t->ip4_prefix_len));
|
||||
u32 ip4 =
|
||||
clib_net_to_host_u32 (t->
|
||||
ip4_prefix.as_u32) | ((u32) (dal >> t->
|
||||
shift) & mask);
|
||||
return clib_host_to_net_u32 (ip4);
|
||||
}
|
||||
|
||||
static_always_inline sixrd_tunnel_t *
|
||||
find_tunnel_by_ip4_address (ip4_address_t * ip)
|
||||
{
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <vnet/devices/virtio/vhost_user.api.h>
|
||||
#include <vnet/devices/tap/tapv2.api.h>
|
||||
#include <vnet/gre/gre.api.h>
|
||||
#include <vnet/ipip/ipip.api.h>
|
||||
#include <vnet/interface.api.h>
|
||||
#include <vnet/map/map.api.h>
|
||||
#include <vnet/l2/l2.api.h>
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
#
|
||||
# IP{4,6} over IP{v,6} tunnel functional tests
|
||||
#
|
||||
|
||||
import unittest
|
||||
from scapy.layers.inet import IP, UDP, ICMP
|
||||
from scapy.layers.inet6 import IPv6
|
||||
from scapy.layers.l2 import Ether, GRE
|
||||
from scapy.packet import Raw
|
||||
|
||||
from framework import VppTestCase
|
||||
from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto
|
||||
from util import ppp
|
||||
from ipaddress import *
|
||||
|
||||
""" Testipip is a subclass of VPPTestCase classes.
|
||||
|
||||
IPIP tests.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class TestIPIP(VppTestCase):
|
||||
""" IPIP Test Case """
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestIPIP, cls).setUpClass()
|
||||
try:
|
||||
cls.create_pg_interfaces(range(2))
|
||||
cls.interfaces = list(cls.pg_interfaces)
|
||||
except Exception:
|
||||
super(TestIPIP, cls).tearDownClass()
|
||||
raise
|
||||
|
||||
def setUp(cls):
|
||||
super(TestIPIP, cls).setUp()
|
||||
try:
|
||||
for i in cls.interfaces:
|
||||
i.admin_up()
|
||||
i.config_ip4()
|
||||
i.config_ip6()
|
||||
i.disable_ipv6_ra()
|
||||
i.resolve_arp()
|
||||
i.resolve_ndp()
|
||||
except Exception:
|
||||
super(TestIPIP, cls).tearDown()
|
||||
raise
|
||||
|
||||
def tearDown(self):
|
||||
super(TestIPIP, self).tearDown()
|
||||
if not self.vpp_dead:
|
||||
self.vapi.cli("show hardware")
|
||||
for i in self.pg_interfaces:
|
||||
i.unconfig_ip4()
|
||||
i.unconfig_ip6()
|
||||
i.admin_down()
|
||||
self.vapi.cli("show error")
|
||||
|
||||
def validate(self, rx, expected):
|
||||
expected = expected.__class__(str(expected))
|
||||
if rx != expected:
|
||||
print('RX packet:')
|
||||
print(rx.show())
|
||||
print('EXPECTED packet:')
|
||||
print(expected.show())
|
||||
self.assertDictEqual(rx, expected)
|
||||
|
||||
def payload(self, len):
|
||||
return 'x' * len
|
||||
|
||||
def test_ipip4(self):
|
||||
""" ip{v4,v6} over ip4 test """
|
||||
p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
|
||||
p_ip6 = IPv6(src="1::1", dst="DEAD::1", nh='UDP')
|
||||
p_ip4 = IP(src="1.2.3.4", dst="130.67.0.1")
|
||||
p_payload = UDP(sport=1234, dport=1234)
|
||||
|
||||
# IPv4 transport
|
||||
rv = self.vapi.ipip_add_tunnel(
|
||||
src_address=str(ip_address(self.pg0.local_ip4).packed),
|
||||
dst_address=str(ip_address(self.pg1.remote_ip4).packed),
|
||||
is_ipv6=0)
|
||||
self.assertEqual(rv.retval, 0)
|
||||
sw_if_index = rv.sw_if_index
|
||||
|
||||
# Set interface up and enable IP on it
|
||||
rv = self.vapi.sw_interface_set_flags(sw_if_index, 1)
|
||||
self.assertEqual(rv.retval, 0)
|
||||
rv = self.vapi.sw_interface_set_unnumbered(
|
||||
ip_sw_if_index=self.pg0.sw_if_index,
|
||||
sw_if_index=sw_if_index)
|
||||
self.assertEqual(rv.retval, 0)
|
||||
|
||||
# Add IPv4 and IPv6 routes via tunnel interface
|
||||
ip4_via_tunnel = VppIpRoute(
|
||||
self, "130.67.0.0", 16,
|
||||
[VppRoutePath("0.0.0.0",
|
||||
sw_if_index,
|
||||
proto=DpoProto.DPO_PROTO_IP4)], is_ip6=0)
|
||||
ip4_via_tunnel.add_vpp_config()
|
||||
|
||||
ip6_via_tunnel = VppIpRoute(
|
||||
self, "dead::", 16,
|
||||
[VppRoutePath("::",
|
||||
sw_if_index,
|
||||
proto=DpoProto.DPO_PROTO_IP6)], is_ip6=1)
|
||||
ip6_via_tunnel.add_vpp_config()
|
||||
|
||||
# IPv6 in to IPv4 tunnel
|
||||
p6 = (p_ether / p_ip6 / p_payload)
|
||||
p_inner_ip6 = p_ip6
|
||||
p_inner_ip6.hlim -= 1
|
||||
p6_reply = (IP(src=self.pg0.local_ip4, dst=self.pg1.remote_ip4,
|
||||
proto='ipv6', id=0) / p_inner_ip6 / p_payload)
|
||||
p6_reply.ttl -= 1
|
||||
rx = self.send_and_expect(self.pg0, p6*10, self.pg1)
|
||||
for p in rx:
|
||||
self.validate(p[1], p6_reply)
|
||||
|
||||
# IPv4 in to IPv4 tunnel
|
||||
p4 = (p_ether / p_ip4 / p_payload)
|
||||
p_ip4_inner = p_ip4
|
||||
p_ip4_inner.ttl -= 1
|
||||
p4_reply = (IP(src=self.pg0.local_ip4,
|
||||
dst=self.pg1.remote_ip4) / p_ip4_inner / p_payload)
|
||||
p4_reply.ttl -= 1
|
||||
p4_reply.id = 0
|
||||
rx = self.send_and_expect(self.pg0, p4*10, self.pg1)
|
||||
for p in rx:
|
||||
self.validate(p[1], p4_reply)
|
||||
|
||||
# Decapsulation
|
||||
p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
|
||||
|
||||
# IPv4 tunnel to IPv4
|
||||
p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
|
||||
p4 = (p_ether / IP(src=self.pg1.remote_ip4,
|
||||
dst=self.pg0.local_ip4) / p_ip4 / p_payload)
|
||||
p4_reply = (p_ip4 / p_payload)
|
||||
p4_reply.ttl -= 1
|
||||
rx = self.send_and_expect(self.pg1, p4*10, self.pg0)
|
||||
for p in rx:
|
||||
self.validate(p[1], p4_reply)
|
||||
|
||||
# IPv4 tunnel to IPv6
|
||||
p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
|
||||
p6 = (p_ether / IP(src=self.pg1.remote_ip4,
|
||||
dst=self.pg0.local_ip4) / p_ip6 / p_payload)
|
||||
p6_reply = (p_ip6 / p_payload)
|
||||
p6_reply.hlim = 63
|
||||
rx = self.send_and_expect(self.pg1, p6*10, self.pg0)
|
||||
for p in rx:
|
||||
self.validate(p[1], p6_reply)
|
||||
|
||||
def test_ipip6(self):
|
||||
""" ip{v4,v6} over ip6 test """
|
||||
p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
|
||||
p_ip6 = IPv6(src="1::1", dst="DEAD::1", nh='UDP')
|
||||
p_ip4 = IP(src="1.2.3.4", dst="130.67.0.1")
|
||||
p_payload = UDP(sport=1234, dport=1234)
|
||||
|
||||
# IPv6 transport
|
||||
rv = self.vapi.ipip_add_tunnel(
|
||||
src_address=str(ip_address(self.pg0.local_ip6).packed),
|
||||
dst_address=str(ip_address(self.pg1.remote_ip6).packed))
|
||||
self.assertEqual(rv.retval, 0)
|
||||
|
||||
sw_if_index = rv.sw_if_index
|
||||
|
||||
rv = self.vapi.sw_interface_set_flags(sw_if_index, 1)
|
||||
self.assertEqual(rv.retval, 0)
|
||||
rv = self.vapi.sw_interface_set_unnumbered(
|
||||
ip_sw_if_index=self.pg0.sw_if_index, sw_if_index=sw_if_index)
|
||||
self.assertEqual(rv.retval, 0)
|
||||
|
||||
# Add IPv4 and IPv6 routes via tunnel interface
|
||||
ip4_via_tunnel = VppIpRoute(
|
||||
self, "130.67.0.0", 16,
|
||||
[VppRoutePath("0.0.0.0",
|
||||
sw_if_index,
|
||||
proto=DpoProto.DPO_PROTO_IP4)], is_ip6=0)
|
||||
ip4_via_tunnel.add_vpp_config()
|
||||
|
||||
ip6_via_tunnel = VppIpRoute(
|
||||
self, "dead::", 16,
|
||||
[VppRoutePath("::",
|
||||
sw_if_index,
|
||||
proto=DpoProto.DPO_PROTO_IP6)], is_ip6=1)
|
||||
ip6_via_tunnel.add_vpp_config()
|
||||
|
||||
# Encapsulation
|
||||
|
||||
# IPv6 in to IPv6 tunnel
|
||||
p6 = (p_ether / p_ip6 / p_payload)
|
||||
p6_reply = (IPv6(src=self.pg0.local_ip6,
|
||||
dst=self.pg1.remote_ip6, hlim=63) / p_ip6 / p_payload)
|
||||
p6_reply[1].hlim -= 1
|
||||
rx = self.send_and_expect(self.pg0, p6*10, self.pg1)
|
||||
for p in rx:
|
||||
self.validate(p[1], p6_reply)
|
||||
|
||||
# IPv4 in to IPv6 tunnel
|
||||
p4 = (p_ether / p_ip4 / p_payload)
|
||||
p4_reply = (IPv6(src=self.pg0.local_ip6,
|
||||
dst=self.pg1.remote_ip6, hlim=63) / p_ip4 / p_payload)
|
||||
p4_reply[1].ttl -= 1
|
||||
rx = self.send_and_expect(self.pg0, p4*10, self.pg1)
|
||||
for p in rx:
|
||||
self.validate(p[1], p4_reply)
|
||||
|
||||
# Decapsulation
|
||||
|
||||
p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
|
||||
|
||||
# IPv6 tunnel to IPv4
|
||||
p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
|
||||
p4 = (p_ether / IPv6(src=self.pg1.remote_ip6,
|
||||
dst=self.pg0.local_ip6) / p_ip4 / p_payload)
|
||||
p4_reply = (p_ip4 / p_payload)
|
||||
p4_reply.ttl -= 1
|
||||
rx = self.send_and_expect(self.pg1, p4*10, self.pg0)
|
||||
for p in rx:
|
||||
self.validate(p[1], p4_reply)
|
||||
|
||||
# IPv6 tunnel to IPv6
|
||||
p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
|
||||
p6 = (p_ether / IPv6(src=self.pg1.remote_ip6,
|
||||
dst=self.pg0.local_ip6) / p_ip6 / p_payload)
|
||||
p6_reply = (p_ip6 / p_payload)
|
||||
p6_reply.hlim = 63
|
||||
rx = self.send_and_expect(self.pg1, p6*10, self.pg0)
|
||||
for p in rx:
|
||||
self.validate(p[1], p6_reply)
|
||||
|
||||
def test_ipip_create(self):
|
||||
""" ipip create / delete interface test """
|
||||
rv = self.vapi.ipip_add_tunnel(
|
||||
src_address=str(ip_address('1.2.3.4').packed),
|
||||
dst_address=str(ip_address('2.3.4.5').packed), is_ipv6=0)
|
||||
self.assertEqual(rv.retval, 0)
|
||||
sw_if_index = rv.sw_if_index
|
||||
rv = self.vapi.ipip_del_tunnel(sw_if_index)
|
||||
self.assertEqual(rv.retval, 0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(testRunner=VppTestRunner)
|
||||
+30
-18
@@ -57,9 +57,11 @@ class Test6RD(VppTestCase):
|
||||
i.admin_down()
|
||||
if type(self.tunnel_index) is list:
|
||||
for sw_if_index in self.tunnel_index:
|
||||
self.vapi.sixrd_del_tunnel(sw_if_index)
|
||||
rv = self.vapi.ipip_6rd_del_tunnel(sw_if_index)
|
||||
self.assertEqual(rv.retval, 0)
|
||||
else:
|
||||
self.vapi.sixrd_del_tunnel(self.tunnel_index)
|
||||
rv = self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
|
||||
self.assertEqual(rv.retval, 0)
|
||||
self.vapi.cli("show error")
|
||||
|
||||
def validate_6in4(self, rx, expected):
|
||||
@@ -92,13 +94,14 @@ class Test6RD(VppTestCase):
|
||||
p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
|
||||
p_ip6 = IPv6(src="1::1", dst="2002:AC10:0202::1", nh='UDP')
|
||||
|
||||
rv = self.vapi.sixrd_add_tunnel(
|
||||
rv = self.vapi.ipip_6rd_add_tunnel(
|
||||
0, str(ip_address('2002::').packed), 16,
|
||||
str(ip_address('0.0.0.0').packed), 0,
|
||||
str(ip_address(self.pg0.local_ip4).packed), 0, True)
|
||||
str(ip_address(self.pg0.local_ip4).packed), True)
|
||||
|
||||
self.assertEqual(rv.retval, 0)
|
||||
self.tunnel_index = rv.sw_if_index
|
||||
|
||||
self.vapi.cli("show ip6 fib")
|
||||
p_payload = UDP(sport=1234, dport=1234)
|
||||
p = (p_ether / p_ip6 / p_payload)
|
||||
@@ -124,13 +127,21 @@ class Test6RD(VppTestCase):
|
||||
def test_6rd_ip4_to_ip6(self):
|
||||
""" ip4 -> ip6 (decap) 6rd test """
|
||||
|
||||
rv = self.vapi.sixrd_add_tunnel(
|
||||
rv = self.vapi.ipip_6rd_add_tunnel(
|
||||
0, str(ip_address('2002::').packed),
|
||||
16, str(ip_address('0.0.0.0').packed),
|
||||
0, str(ip_address(self.pg0.local_ip4).packed), 0, True)
|
||||
0, str(ip_address(self.pg0.local_ip4).packed), True)
|
||||
self.assertEqual(rv.retval, 0)
|
||||
self.tunnel_index = rv.sw_if_index
|
||||
self.vapi.cli("show ip6 fib")
|
||||
rv = self.vapi.ipip_6rd_del_tunnel(rv.sw_if_index)
|
||||
self.assertEqual(rv.retval, 0)
|
||||
rv = self.vapi.ipip_6rd_add_tunnel(
|
||||
0, str(ip_address('2002::').packed),
|
||||
16, str(ip_address('0.0.0.0').packed),
|
||||
0, str(ip_address(self.pg0.local_ip4).packed), True)
|
||||
self.tunnel_index = rv.sw_if_index
|
||||
self.assertEqual(rv.retval, 0)
|
||||
|
||||
p_ip6 = (IPv6(src="2002:AC10:0202::1", dst=self.pg1.remote_ip6) /
|
||||
UDP(sport=1234, dport=1234))
|
||||
|
||||
@@ -149,18 +160,18 @@ class Test6RD(VppTestCase):
|
||||
""" ip4 -> ip6 (decap) 6rd test """
|
||||
|
||||
self.tunnel_index = []
|
||||
rv = self.vapi.sixrd_add_tunnel(
|
||||
rv = self.vapi.ipip_6rd_add_tunnel(
|
||||
0, str(ip_address('2002::').packed),
|
||||
16, str(ip_address('0.0.0.0').packed),
|
||||
0, str(ip_address(self.pg0.local_ip4).packed), 0, True)
|
||||
0, str(ip_address(self.pg0.local_ip4).packed), True)
|
||||
self.assertEqual(rv.retval, 0)
|
||||
self.tunnel_index.append(rv.sw_if_index)
|
||||
rv = self.vapi.sixrd_add_tunnel(
|
||||
|
||||
rv = self.vapi.ipip_6rd_add_tunnel(
|
||||
0, str(ip_address('2003::').packed),
|
||||
16, str(ip_address('0.0.0.0').packed),
|
||||
0, str(ip_address(self.pg1.local_ip4).packed), 0, True)
|
||||
0, str(ip_address(self.pg1.local_ip4).packed), True)
|
||||
self.assertEqual(rv.retval, 0)
|
||||
|
||||
self.tunnel_index.append(rv.sw_if_index)
|
||||
|
||||
self.vapi.cli("show ip6 fib")
|
||||
@@ -184,10 +195,10 @@ class Test6RD(VppTestCase):
|
||||
def test_6rd_ip4_to_ip6_suffix(self):
|
||||
""" ip4 -> ip6 (decap) 6rd test """
|
||||
|
||||
rv = self.vapi.sixrd_add_tunnel(
|
||||
rv = self.vapi.ipip_6rd_add_tunnel(
|
||||
0, str(ip_address('2002::').packed), 16,
|
||||
str(ip_address('172.0.0.0').packed), 8,
|
||||
str(ip_address(self.pg0.local_ip4).packed), 0, True)
|
||||
str(ip_address(self.pg0.local_ip4).packed), True)
|
||||
self.assertEqual(rv.retval, 0)
|
||||
|
||||
self.tunnel_index = rv.sw_if_index
|
||||
@@ -206,12 +217,13 @@ class Test6RD(VppTestCase):
|
||||
def test_6rd_ip4_to_ip6_sec_check(self):
|
||||
""" ip4 -> ip6 (decap) security check 6rd test """
|
||||
|
||||
rv = self.vapi.sixrd_add_tunnel(
|
||||
rv = self.vapi.ipip_6rd_add_tunnel(
|
||||
0, str(ip_address('2002::').packed),
|
||||
16, str(ip_address('0.0.0.0').packed),
|
||||
0, str(ip_address(self.pg0.local_ip4).packed), 0, True)
|
||||
0, str(ip_address(self.pg0.local_ip4).packed), True)
|
||||
self.assertEqual(rv.retval, 0)
|
||||
self.tunnel_index = rv.sw_if_index
|
||||
|
||||
self.vapi.cli("show ip6 fib")
|
||||
p_ip6 = (IPv6(src="2002:AC10:0202::1", dst=self.pg1.remote_ip6) /
|
||||
UDP(sport=1234, dport=1234))
|
||||
@@ -238,10 +250,10 @@ class Test6RD(VppTestCase):
|
||||
def test_6rd_bgp_tunnel(self):
|
||||
""" 6rd BGP tunnel """
|
||||
|
||||
rv = self.vapi.sixrd_add_tunnel(
|
||||
rv = self.vapi.ipip_6rd_add_tunnel(
|
||||
0, str(ip_address('2002::').packed),
|
||||
16, str(ip_address('0.0.0.0').packed),
|
||||
0, str(ip_address(self.pg0.local_ip4).packed), 0, False)
|
||||
0, str(ip_address(self.pg0.local_ip4).packed), False)
|
||||
self.assertEqual(rv.retval, 0)
|
||||
self.tunnel_index = rv.sw_if_index
|
||||
|
||||
|
||||
@@ -3202,21 +3202,35 @@ class VppPapiProvider(object):
|
||||
""" GBP contract Dump """
|
||||
return self.api(self.papi.gbp_contract_dump, {})
|
||||
|
||||
def sixrd_add_tunnel(self, fib_index, ip6_prefix, ip6_prefix_len,
|
||||
ip4_prefix, ip4_prefix_len, ip4_src, mtu,
|
||||
security_check):
|
||||
def ipip_6rd_add_tunnel(self, fib_index, ip6_prefix, ip6_prefix_len,
|
||||
ip4_prefix, ip4_prefix_len, ip4_src,
|
||||
security_check):
|
||||
""" 6RD tunnel Add """
|
||||
return self.api(self.papi.sixrd_add_tunnel,
|
||||
return self.api(self.papi.ipip_6rd_add_tunnel,
|
||||
{'fib_index': fib_index,
|
||||
'ip6_prefix': ip6_prefix,
|
||||
'ip6_prefix_len': ip6_prefix_len,
|
||||
'ip4_prefix': ip4_prefix,
|
||||
'ip4_prefix_len': ip4_prefix_len,
|
||||
'ip4_src': ip4_src,
|
||||
'mtu': mtu,
|
||||
'security_check': security_check})
|
||||
|
||||
def sixrd_del_tunnel(self, sw_if_index):
|
||||
def ipip_6rd_del_tunnel(self, sw_if_index):
|
||||
""" 6RD tunnel Delete """
|
||||
return self.api(self.papi.sixrd_del_tunnel,
|
||||
return self.api(self.papi.ipip_6rd_del_tunnel,
|
||||
{'sw_if_index': sw_if_index})
|
||||
|
||||
def ipip_add_tunnel(self, src_address, dst_address, is_ipv6=1,
|
||||
instance=0xFFFFFFFF, fib_index=0):
|
||||
""" IPIP tunnel Add/Del """
|
||||
return self.api(self.papi.ipip_add_tunnel,
|
||||
{'is_ipv6': is_ipv6,
|
||||
'instance': instance,
|
||||
'src_address': src_address,
|
||||
'dst_address': dst_address,
|
||||
'fib_index': fib_index})
|
||||
|
||||
def ipip_del_tunnel(self, sw_if_index):
|
||||
""" IPIP tunnel Delete """
|
||||
return self.api(self.papi.ipip_del_tunnel,
|
||||
{'sw_if_index': sw_if_index})
|
||||
|
||||
Reference in New Issue
Block a user