nat: nat66 to plugin
Type: refactor Change-Id: I8c1f0c02a4522c1f9e461ddadd59938579ec00c6 Signed-off-by: Ole Troan <ot@cisco.com>
This commit is contained in:
committed by
Andrew Yourtchenko
parent
c6eae9c079
commit
96068d6b94
@@ -21,6 +21,7 @@
|
||||
#include "vom/rpc_cmd.hpp"
|
||||
|
||||
#include <vapi/nat.api.vapi.hpp>
|
||||
#include <vapi/nat66.api.vapi.hpp>
|
||||
|
||||
namespace VOM {
|
||||
namespace nat_binding_cmds {
|
||||
@@ -253,8 +254,8 @@ private:
|
||||
|
||||
/////
|
||||
/**
|
||||
* A functor class that binds a NAT configuration to an input interface
|
||||
*/
|
||||
* A functor class that binds a NAT configuration to an input interface
|
||||
*/
|
||||
class bind_66_input_cmd
|
||||
: public rpc_cmd<HW::item<bool>, vapi::Nat66_add_del_interface>
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "vom/nat_static_cmds.hpp"
|
||||
|
||||
DEFINE_VAPI_MSG_IDS_NAT_API_JSON;
|
||||
DEFINE_VAPI_MSG_IDS_NAT66_API_JSON;
|
||||
|
||||
namespace VOM {
|
||||
namespace nat_static_cmds {
|
||||
@@ -28,8 +29,7 @@ create_44_cmd::create_44_cmd(HW::item<bool>& item,
|
||||
, m_id(id)
|
||||
, m_inside(inside)
|
||||
, m_outside(outside)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
bool
|
||||
create_44_cmd::operator==(const create_44_cmd& other) const
|
||||
@@ -77,8 +77,7 @@ delete_44_cmd::delete_44_cmd(HW::item<bool>& item,
|
||||
, m_id(id)
|
||||
, m_inside(inside)
|
||||
, m_outside(outside)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
bool
|
||||
delete_44_cmd::operator==(const delete_44_cmd& other) const
|
||||
@@ -153,8 +152,7 @@ create_66_cmd::create_66_cmd(HW::item<bool>& item,
|
||||
, m_id(id)
|
||||
, m_inside(inside)
|
||||
, m_outside(outside)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
bool
|
||||
create_66_cmd::operator==(const create_66_cmd& other) const
|
||||
@@ -198,8 +196,7 @@ delete_66_cmd::delete_66_cmd(HW::item<bool>& item,
|
||||
, m_id(id)
|
||||
, m_inside(inside)
|
||||
, m_outside(outside)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
bool
|
||||
delete_66_cmd::operator==(const delete_66_cmd& other) const
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "vom/dump_cmd.hpp"
|
||||
|
||||
#include <vapi/nat.api.vapi.hpp>
|
||||
#include <vapi/nat66.api.vapi.hpp>
|
||||
|
||||
namespace VOM {
|
||||
namespace nat_static_cmds {
|
||||
|
||||
@@ -43,10 +43,6 @@ add_vpp_plugin(nat
|
||||
nat64_in2out.c
|
||||
nat64_out2in.c
|
||||
nat64_db.c
|
||||
nat66.c
|
||||
nat66_cli.c
|
||||
nat66_in2out.c
|
||||
nat66_out2in.c
|
||||
nat_affinity.c
|
||||
nat_format.c
|
||||
nat_syslog.c
|
||||
@@ -60,8 +56,6 @@ add_vpp_plugin(nat
|
||||
nat44_handoff.c
|
||||
nat64_in2out.c
|
||||
nat64_out2in.c
|
||||
nat66_in2out.c
|
||||
nat66_out2in.c
|
||||
nat_det_in2out.c
|
||||
nat_det_out2in.c
|
||||
out2in.c
|
||||
@@ -69,6 +63,7 @@ add_vpp_plugin(nat
|
||||
|
||||
API_FILES
|
||||
nat.api
|
||||
nat_types.api
|
||||
|
||||
API_TEST_SOURCES
|
||||
nat_test.c
|
||||
@@ -101,3 +96,23 @@ add_vpp_plugin(dslite
|
||||
|
||||
LINK_LIBRARIES nat
|
||||
)
|
||||
|
||||
add_vpp_plugin(nat66
|
||||
SOURCES
|
||||
nat_syslog.c
|
||||
nat66/nat66.c
|
||||
nat66/nat66_cli.c
|
||||
nat66/nat66_api.c
|
||||
nat66/nat66_in2out.c
|
||||
nat66/nat66_out2in.c
|
||||
|
||||
MULTIARCH_SOURCES
|
||||
nat66/nat66_in2out.c
|
||||
nat66/nat66_out2in.c
|
||||
|
||||
API_FILES
|
||||
nat66/nat66.api
|
||||
nat_types.api
|
||||
|
||||
LINK_LIBRARIES nat
|
||||
)
|
||||
|
||||
+1
-96
@@ -16,6 +16,7 @@
|
||||
option version = "5.2.0";
|
||||
import "vnet/ip/ip_types.api";
|
||||
import "vnet/interface_types.api";
|
||||
import "plugins/nat/nat_types.api";
|
||||
|
||||
/**
|
||||
* @file nat.api
|
||||
@@ -29,19 +30,6 @@ import "vnet/interface_types.api";
|
||||
* Common NAT plugin APIs
|
||||
*/
|
||||
|
||||
enum nat_config_flags : u8
|
||||
{
|
||||
NAT_IS_NONE = 0x00,
|
||||
NAT_IS_TWICE_NAT = 0x01,
|
||||
NAT_IS_SELF_TWICE_NAT = 0x02,
|
||||
NAT_IS_OUT2IN_ONLY = 0x04,
|
||||
NAT_IS_ADDR_ONLY = 0x08,
|
||||
NAT_IS_OUTSIDE = 0x10,
|
||||
NAT_IS_INSIDE = 0x20,
|
||||
NAT_IS_STATIC = 0x40,
|
||||
NAT_IS_EXT_HOST_VALID = 0x80,
|
||||
};
|
||||
|
||||
/** \brief Control ping from client to api server request
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@@ -1398,86 +1386,3 @@ autoreply define nat64_add_del_interface_addr {
|
||||
bool is_add;
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
};
|
||||
|
||||
/*
|
||||
* NAT66 APIs
|
||||
*/
|
||||
/** \brief Enable/disable NAT66 feature on the interface
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param is_add - true if add, false if delete
|
||||
@param flags - flag NAT_IS_INSIDE if interface is inside or
|
||||
interface is outside,
|
||||
@param sw_if_index - software index of the interface
|
||||
*/
|
||||
autoreply define nat66_add_del_interface {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
bool is_add;
|
||||
vl_api_nat_config_flags_t flags;
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
};
|
||||
|
||||
/** \brief Dump interfaces with NAT66 feature
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
*/
|
||||
define nat66_interface_dump {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
};
|
||||
|
||||
/** \brief NAT66 interface details response
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param flags - flag NAT_IS_INSIDE if interface is inside or
|
||||
interface is outside,
|
||||
@param sw_if_index - software index of the interface
|
||||
*/
|
||||
define nat66_interface_details {
|
||||
u32 context;
|
||||
vl_api_nat_config_flags_t flags;
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
};
|
||||
|
||||
/** \brief Add/delete 1:1 NAT66
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param is_add - true if add, false if delete
|
||||
@param local_ip_address - local IPv6 address
|
||||
@param external_ip_address - external IPv6 address
|
||||
@param vrf_id - VRF id of tenant
|
||||
*/
|
||||
autoreply define nat66_add_del_static_mapping {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
bool is_add;
|
||||
vl_api_ip6_address_t local_ip_address;
|
||||
vl_api_ip6_address_t external_ip_address;
|
||||
u32 vrf_id;
|
||||
};
|
||||
|
||||
/** \brief Dump NAT66 static mappings
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
*/
|
||||
define nat66_static_mapping_dump {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
};
|
||||
|
||||
/** \brief NAT66 static mapping details response
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param local_ip_address - local IPv6 address
|
||||
@param external_ip_address - external IPv6 address
|
||||
@param vrf_id - VRF id of tenant
|
||||
@param total_bytes - count of bytes sent through static mapping
|
||||
@param total_pkts - count of pakets sent through static mapping
|
||||
*/
|
||||
define nat66_static_mapping_details {
|
||||
u32 context;
|
||||
vl_api_ip6_address_t local_ip_address;
|
||||
vl_api_ip6_address_t external_ip_address;
|
||||
u32 vrf_id;
|
||||
u64 total_bytes;
|
||||
u64 total_pkts;
|
||||
};
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <nat/nat_ipfix_logging.h>
|
||||
#include <nat/nat_det.h>
|
||||
#include <nat/nat64.h>
|
||||
#include <nat/nat66.h>
|
||||
#include <nat/nat_inlines.h>
|
||||
#include <nat/nat44/inlines.h>
|
||||
#include <nat/nat_affinity.h>
|
||||
@@ -2598,8 +2597,6 @@ snat_init (vlib_main_t * vm)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
nat66_init (vm);
|
||||
|
||||
ip4_table_bind_callback_t cbt4 = {
|
||||
.function = snat_ip4_table_bind,
|
||||
};
|
||||
@@ -3913,7 +3910,6 @@ static clib_error_t *
|
||||
snat_config (vlib_main_t * vm, unformat_input_t * input)
|
||||
{
|
||||
snat_main_t *sm = &snat_main;
|
||||
nat66_main_t *nm = &nat66_main;
|
||||
snat_main_per_thread_data_t *tsm;
|
||||
|
||||
u32 static_mapping_buckets = 1024;
|
||||
@@ -4075,10 +4071,6 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
|
||||
sm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
|
||||
outside_vrf_id,
|
||||
nat_fib_src_hi);
|
||||
nm->outside_vrf_id = outside_ip6_vrf_id;
|
||||
nm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
|
||||
outside_ip6_vrf_id,
|
||||
nat_fib_src_hi);
|
||||
sm->inside_vrf_id = inside_vrf_id;
|
||||
sm->inside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
|
||||
inside_vrf_id,
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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";
|
||||
import "vnet/ip/ip_types.api";
|
||||
import "vnet/interface_types.api";
|
||||
import "plugins/nat/nat_types.api";
|
||||
|
||||
/** \brief Enable/disable NAT66 feature on the interface
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param is_add - true if add, false if delete
|
||||
@param flags - flag NAT_IS_INSIDE if interface is inside or
|
||||
interface is outside,
|
||||
@param sw_if_index - software index of the interface
|
||||
*/
|
||||
autoreply define nat66_add_del_interface {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
bool is_add;
|
||||
vl_api_nat_config_flags_t flags;
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
};
|
||||
|
||||
/** \brief Dump interfaces with NAT66 feature
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
*/
|
||||
define nat66_interface_dump {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
};
|
||||
|
||||
/** \brief NAT66 interface details response
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param flags - flag NAT_IS_INSIDE if interface is inside or
|
||||
interface is outside,
|
||||
@param sw_if_index - software index of the interface
|
||||
*/
|
||||
define nat66_interface_details {
|
||||
u32 context;
|
||||
vl_api_nat_config_flags_t flags;
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
};
|
||||
|
||||
/** \brief Add/delete 1:1 NAT66
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param is_add - true if add, false if delete
|
||||
@param local_ip_address - local IPv6 address
|
||||
@param external_ip_address - external IPv6 address
|
||||
@param vrf_id - VRF id of tenant
|
||||
*/
|
||||
autoreply define nat66_add_del_static_mapping {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
bool is_add;
|
||||
vl_api_ip6_address_t local_ip_address;
|
||||
vl_api_ip6_address_t external_ip_address;
|
||||
u32 vrf_id;
|
||||
};
|
||||
|
||||
/** \brief Dump NAT66 static mappings
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
*/
|
||||
define nat66_static_mapping_dump {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
};
|
||||
|
||||
/** \brief NAT66 static mapping details response
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param local_ip_address - local IPv6 address
|
||||
@param external_ip_address - external IPv6 address
|
||||
@param vrf_id - VRF id of tenant
|
||||
@param total_bytes - count of bytes sent through static mapping
|
||||
@param total_pkts - count of pakets sent through static mapping
|
||||
*/
|
||||
define nat66_static_mapping_details {
|
||||
u32 context;
|
||||
vl_api_ip6_address_t local_ip_address;
|
||||
vl_api_ip6_address_t external_ip_address;
|
||||
u32 vrf_id;
|
||||
u64 total_bytes;
|
||||
u64 total_pkts;
|
||||
};
|
||||
@@ -17,11 +17,14 @@
|
||||
* @brief NAT66 implementation
|
||||
*/
|
||||
|
||||
#include <nat/nat66.h>
|
||||
#include <vpp/app/version.h>
|
||||
#include <vnet/plugin/plugin.h>
|
||||
#include <nat/nat66/nat66.h>
|
||||
#include <vnet/fib/fib_table.h>
|
||||
#include <vnet/ip/reass/ip6_sv_reass.h>
|
||||
|
||||
nat66_main_t nat66_main;
|
||||
fib_source_t nat_fib_src_hi;
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
|
||||
@@ -41,8 +44,8 @@ VNET_FEATURE_INIT (nat66_out2in, static) = {
|
||||
|
||||
/* *INDENT-ON* */
|
||||
|
||||
|
||||
void
|
||||
clib_error_t *nat66_plugin_api_hookup (vlib_main_t * vm);
|
||||
static clib_error_t *
|
||||
nat66_init (vlib_main_t * vm)
|
||||
{
|
||||
nat66_main_t *nm = &nat66_main;
|
||||
@@ -62,13 +65,19 @@ nat66_init (vlib_main_t * vm)
|
||||
static_mapping_buckets, static_mapping_memory_size);
|
||||
|
||||
nm->session_counters.name = "session counters";
|
||||
|
||||
nat_fib_src_hi = fib_source_allocate ("nat66-hi",
|
||||
FIB_SOURCE_PRIORITY_HI,
|
||||
FIB_SOURCE_BH_SIMPLE);
|
||||
|
||||
return nat66_plugin_api_hookup (vm);
|
||||
}
|
||||
|
||||
int
|
||||
nat66_interface_add_del (u32 sw_if_index, u8 is_inside, u8 is_add)
|
||||
{
|
||||
nat66_main_t *nm = &nat66_main;
|
||||
snat_interface_t *interface = 0, *i;
|
||||
nat66_interface_t *interface = 0, *i;
|
||||
const char *feature_name;
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
@@ -90,8 +99,8 @@ nat66_interface_add_del (u32 sw_if_index, u8 is_inside, u8 is_add)
|
||||
pool_get (nm->interfaces, interface);
|
||||
interface->sw_if_index = sw_if_index;
|
||||
interface->flags =
|
||||
is_inside ? NAT_INTERFACE_FLAG_IS_INSIDE :
|
||||
NAT_INTERFACE_FLAG_IS_OUTSIDE;
|
||||
is_inside ? NAT66_INTERFACE_FLAG_IS_INSIDE :
|
||||
NAT66_INTERFACE_FLAG_IS_OUTSIDE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -113,7 +122,7 @@ void
|
||||
nat66_interfaces_walk (nat66_interface_walk_fn_t fn, void *ctx)
|
||||
{
|
||||
nat66_main_t *nm = &nat66_main;
|
||||
snat_interface_t *i = 0;
|
||||
nat66_interface_t *i = 0;
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
pool_foreach (i, nm->interfaces,
|
||||
@@ -191,7 +200,7 @@ nat66_static_mapping_add_del (ip6_address_t * l_addr, ip6_address_t * e_addr,
|
||||
kv.key[2] = sm_key.as_u64[2];
|
||||
kv.value = sm - nm->sm;
|
||||
if (clib_bihash_add_del_24_8 (&nm->sm_l, &kv, 1))
|
||||
nat_elog_warn ("nat66-static-map-by-local add key failed");
|
||||
nat66_elog_warn ("nat66-static-map-by-local add key failed");
|
||||
sm_key.addr.as_u64[0] = e_addr->as_u64[0];
|
||||
sm_key.addr.as_u64[1] = e_addr->as_u64[1];
|
||||
sm_key.fib_index = 0;
|
||||
@@ -199,7 +208,7 @@ nat66_static_mapping_add_del (ip6_address_t * l_addr, ip6_address_t * e_addr,
|
||||
kv.key[1] = sm_key.as_u64[1];
|
||||
kv.key[2] = sm_key.as_u64[2];
|
||||
if (clib_bihash_add_del_24_8 (&nm->sm_e, &kv, 1))
|
||||
nat_elog_warn ("nat66-static-map-by-external add key failed");
|
||||
nat66_elog_warn ("nat66-static-map-by-external add key failed");
|
||||
|
||||
vlib_validate_combined_counter (&nm->session_counters, kv.value);
|
||||
vlib_zero_combined_counter (&nm->session_counters, kv.value);
|
||||
@@ -211,7 +220,7 @@ nat66_static_mapping_add_del (ip6_address_t * l_addr, ip6_address_t * e_addr,
|
||||
|
||||
kv.value = sm - nm->sm;
|
||||
if (clib_bihash_add_del_24_8 (&nm->sm_l, &kv, 0))
|
||||
nat_elog_warn ("nat66-static-map-by-local delete key failed");
|
||||
nat66_elog_warn ("nat66-static-map-by-local delete key failed");
|
||||
sm_key.addr.as_u64[0] = e_addr->as_u64[0];
|
||||
sm_key.addr.as_u64[1] = e_addr->as_u64[1];
|
||||
sm_key.fib_index = 0;
|
||||
@@ -219,7 +228,7 @@ nat66_static_mapping_add_del (ip6_address_t * l_addr, ip6_address_t * e_addr,
|
||||
kv.key[1] = sm_key.as_u64[1];
|
||||
kv.key[2] = sm_key.as_u64[2];
|
||||
if (clib_bihash_add_del_24_8 (&nm->sm_e, &kv, 0))
|
||||
nat_elog_warn ("nat66-static-map-by-external delete key failed");
|
||||
nat66_elog_warn ("nat66-static-map-by-external delete key failed");
|
||||
fib_table_unlock (sm->fib_index, FIB_PROTOCOL_IP6, nat_fib_src_hi);
|
||||
pool_put (nm->sm, sm);
|
||||
}
|
||||
@@ -242,6 +251,30 @@ nat66_static_mappings_walk (nat66_static_mapping_walk_fn_t fn, void *ctx)
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
nat66_config (void)
|
||||
{
|
||||
nat66_main_t *nm = &nat66_main;
|
||||
u32 outside_ip6_vrf_id = 0;
|
||||
|
||||
nm->outside_vrf_id = outside_ip6_vrf_id;
|
||||
nm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
|
||||
outside_ip6_vrf_id,
|
||||
nat_fib_src_hi);
|
||||
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_PLUGIN_REGISTER () =
|
||||
{
|
||||
.version = VPP_BUILD_VER,
|
||||
.description = "NAT66",
|
||||
};
|
||||
|
||||
VLIB_INIT_FUNCTION (nat66_init);
|
||||
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
@@ -19,8 +19,8 @@
|
||||
#ifndef __included_nat66_h__
|
||||
#define __included_nat66_h__
|
||||
|
||||
#include <vnet/ip/ip.h>
|
||||
#include <vppinfra/bihash_24_8.h>
|
||||
#include <nat/nat.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -43,10 +43,20 @@ typedef struct
|
||||
};
|
||||
} nat66_sm_key_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 sw_if_index;
|
||||
u8 flags;
|
||||
} nat66_interface_t;
|
||||
#define NAT66_INTERFACE_FLAG_IS_INSIDE 1
|
||||
#define NAT66_INTERFACE_FLAG_IS_OUTSIDE 2
|
||||
#define nat66_interface_is_inside(i) i->flags & NAT66_INTERFACE_FLAG_IS_INSIDE
|
||||
#define nat66_interface_is_outside(i) i->flags & NAT66_INTERFACE_FLAG_IS_OUTSIDE
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/** Interface pool */
|
||||
snat_interface_t *interfaces;
|
||||
nat66_interface_t *interfaces;
|
||||
/** Static mapping pool */
|
||||
nat66_static_mapping_t *sm;
|
||||
/** Static mapping by local address lookup table */
|
||||
@@ -61,14 +71,35 @@ typedef struct
|
||||
|
||||
u32 outside_vrf_id;
|
||||
u32 outside_fib_index;
|
||||
|
||||
u16 msg_id_base;
|
||||
u8 log_level;
|
||||
} nat66_main_t;
|
||||
|
||||
#define nat66_elog(_level, _str) \
|
||||
do \
|
||||
{ \
|
||||
nat66_main_t *nm = &nat66_main; \
|
||||
if (PREDICT_FALSE (nm->log_level >= _level)) \
|
||||
{ \
|
||||
ELOG_TYPE_DECLARE (e) = \
|
||||
{ \
|
||||
.format = "nat66-msg " _str, \
|
||||
.format_args = "", \
|
||||
}; \
|
||||
ELOG_DATA (&vlib_global_main.elog_main, e); \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define nat66_elog_warn(nat_elog_str) \
|
||||
nat66_elog(0x02, "[warning] " nat_elog_str)
|
||||
|
||||
|
||||
extern nat66_main_t nat66_main;
|
||||
extern vlib_node_registration_t nat66_in2out_node;
|
||||
extern vlib_node_registration_t nat66_out2in_node;
|
||||
|
||||
void nat66_init (vlib_main_t * vm);
|
||||
typedef int (*nat66_interface_walk_fn_t) (snat_interface_t * i, void *ctx);
|
||||
typedef int (*nat66_interface_walk_fn_t) (nat66_interface_t * i, void *ctx);
|
||||
void nat66_interfaces_walk (nat66_interface_walk_fn_t fn, void *ctx);
|
||||
int nat66_interface_add_del (u32 sw_if_index, u8 is_inside, u8 is_add);
|
||||
typedef int (*nat66_static_mapping_walk_fn_t) (nat66_static_mapping_t * sm,
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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 <nat/nat66/nat66.h>
|
||||
#include <nat/nat66/nat66.api_enum.h>
|
||||
#include <nat/nat66/nat66.api_types.h>
|
||||
#include <vnet/fib/fib_table.h>
|
||||
|
||||
#define REPLY_MSG_ID_BASE nm->msg_id_base
|
||||
#include <vlibapi/api_helper_macros.h>
|
||||
|
||||
/*************/
|
||||
/*** NAT66 ***/
|
||||
/*************/
|
||||
|
||||
static void
|
||||
vl_api_nat66_add_del_interface_t_handler (vl_api_nat66_add_del_interface_t *
|
||||
mp)
|
||||
{
|
||||
nat66_main_t *nm = &nat66_main;
|
||||
vl_api_nat66_add_del_interface_reply_t *rmp;
|
||||
int rv = 0;
|
||||
|
||||
VALIDATE_SW_IF_INDEX (mp);
|
||||
|
||||
rv =
|
||||
nat66_interface_add_del (ntohl (mp->sw_if_index),
|
||||
mp->flags & NAT_IS_INSIDE, mp->is_add);
|
||||
|
||||
BAD_SW_IF_INDEX_LABEL;
|
||||
|
||||
REPLY_MACRO (VL_API_NAT66_ADD_DEL_INTERFACE_REPLY);
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_nat66_add_del_static_mapping_t_handler
|
||||
(vl_api_nat66_add_del_static_mapping_t * mp)
|
||||
{
|
||||
nat66_main_t *nm = &nat66_main;
|
||||
vl_api_nat66_add_del_static_mapping_reply_t *rmp;
|
||||
ip6_address_t l_addr, e_addr;
|
||||
int rv = 0;
|
||||
|
||||
memcpy (&l_addr.as_u8, mp->local_ip_address, 16);
|
||||
memcpy (&e_addr.as_u8, mp->external_ip_address, 16);
|
||||
|
||||
rv =
|
||||
nat66_static_mapping_add_del (&l_addr, &e_addr,
|
||||
clib_net_to_host_u32 (mp->vrf_id),
|
||||
mp->is_add);
|
||||
|
||||
REPLY_MACRO (VL_API_NAT66_ADD_DEL_STATIC_MAPPING_REPLY);
|
||||
}
|
||||
|
||||
typedef struct nat66_api_walk_ctx_t_
|
||||
{
|
||||
vl_api_registration_t *rp;
|
||||
u32 context;
|
||||
} nat66_api_walk_ctx_t;
|
||||
|
||||
static int
|
||||
nat66_api_interface_walk (nat66_interface_t * i, void *arg)
|
||||
{
|
||||
vl_api_nat66_interface_details_t *rmp;
|
||||
nat66_main_t *nm = &nat66_main;
|
||||
nat66_api_walk_ctx_t *ctx = arg;
|
||||
|
||||
rmp = vl_msg_api_alloc (sizeof (*rmp));
|
||||
clib_memset (rmp, 0, sizeof (*rmp));
|
||||
rmp->_vl_msg_id = ntohs (VL_API_NAT66_INTERFACE_DETAILS + nm->msg_id_base);
|
||||
rmp->sw_if_index = ntohl (i->sw_if_index);
|
||||
if (nat66_interface_is_inside (i))
|
||||
rmp->flags |= NAT_IS_INSIDE;
|
||||
rmp->context = ctx->context;
|
||||
|
||||
vl_api_send_msg (ctx->rp, (u8 *) rmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_nat66_interface_dump_t_handler (vl_api_nat66_interface_dump_t * mp)
|
||||
{
|
||||
vl_api_registration_t *rp;
|
||||
|
||||
rp = vl_api_client_index_to_registration (mp->client_index);
|
||||
if (rp == 0)
|
||||
return;
|
||||
|
||||
nat66_api_walk_ctx_t ctx = {
|
||||
.rp = rp,
|
||||
.context = mp->context,
|
||||
};
|
||||
|
||||
nat66_interfaces_walk (nat66_api_interface_walk, &ctx);
|
||||
}
|
||||
|
||||
static int
|
||||
nat66_api_static_mapping_walk (nat66_static_mapping_t * m, void *arg)
|
||||
{
|
||||
vl_api_nat66_static_mapping_details_t *rmp;
|
||||
nat66_main_t *nm = &nat66_main;
|
||||
nat66_api_walk_ctx_t *ctx = arg;
|
||||
fib_table_t *fib;
|
||||
vlib_counter_t vc;
|
||||
|
||||
fib = fib_table_get (m->fib_index, FIB_PROTOCOL_IP6);
|
||||
if (!fib)
|
||||
return -1;
|
||||
|
||||
vlib_get_combined_counter (&nm->session_counters, m - nm->sm, &vc);
|
||||
|
||||
rmp = vl_msg_api_alloc (sizeof (*rmp));
|
||||
clib_memset (rmp, 0, sizeof (*rmp));
|
||||
rmp->_vl_msg_id =
|
||||
ntohs (VL_API_NAT66_STATIC_MAPPING_DETAILS + nm->msg_id_base);
|
||||
clib_memcpy (rmp->local_ip_address, &m->l_addr, 16);
|
||||
clib_memcpy (rmp->external_ip_address, &m->e_addr, 16);
|
||||
rmp->vrf_id = ntohl (fib->ft_table_id);
|
||||
rmp->total_bytes = clib_host_to_net_u64 (vc.bytes);
|
||||
rmp->total_pkts = clib_host_to_net_u64 (vc.packets);
|
||||
rmp->context = ctx->context;
|
||||
|
||||
vl_api_send_msg (ctx->rp, (u8 *) rmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_nat66_static_mapping_dump_t_handler (vl_api_nat66_static_mapping_dump_t
|
||||
* mp)
|
||||
{
|
||||
vl_api_registration_t *rp;
|
||||
|
||||
rp = vl_api_client_index_to_registration (mp->client_index);
|
||||
if (rp == 0)
|
||||
return;
|
||||
|
||||
nat66_api_walk_ctx_t ctx = {
|
||||
.rp = rp,
|
||||
.context = mp->context,
|
||||
};
|
||||
|
||||
nat66_static_mappings_walk (nat66_api_static_mapping_walk, &ctx);
|
||||
}
|
||||
|
||||
/* API definitions */
|
||||
#include <vnet/format_fns.h>
|
||||
#include <nat/nat66/nat66.api.c>
|
||||
|
||||
/* Set up the API message handling tables */
|
||||
clib_error_t *
|
||||
nat66_plugin_api_hookup (vlib_main_t * vm)
|
||||
{
|
||||
nat66_main_t *nm = &nat66_main;
|
||||
|
||||
nm->msg_id_base = setup_message_id_table ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -17,8 +17,7 @@
|
||||
* @brief NAT66 CLI
|
||||
*/
|
||||
|
||||
#include <nat/nat66.h>
|
||||
#include <nat/nat.h>
|
||||
#include <nat/nat66/nat66.h>
|
||||
#include <vnet/fib/fib_table.h>
|
||||
|
||||
static clib_error_t *
|
||||
@@ -136,14 +135,14 @@ done:
|
||||
}
|
||||
|
||||
static int
|
||||
nat66_cli_interface_walk (snat_interface_t * i, void *ctx)
|
||||
nat66_cli_interface_walk (nat66_interface_t * i, void *ctx)
|
||||
{
|
||||
vlib_main_t *vm = ctx;
|
||||
vnet_main_t *vnm = vnet_get_main ();
|
||||
|
||||
vlib_cli_output (vm, " %U %s", format_vnet_sw_interface_name, vnm,
|
||||
vnet_get_sw_interface (vnm, i->sw_if_index),
|
||||
nat_interface_is_inside (i) ? "in" : "out");
|
||||
nat66_interface_is_inside (i) ? "in" : "out");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* @brief NAT66 inside to outside network translation
|
||||
*/
|
||||
|
||||
#include <nat/nat66.h>
|
||||
#include <nat/nat66/nat66.h>
|
||||
#include <vnet/ip/ip6_to_ip4.h>
|
||||
#include <vnet/fib/fib_table.h>
|
||||
|
||||
@@ -72,7 +72,7 @@ nat66_not_translate (u32 rx_fib_index, ip6_address_t ip6_addr)
|
||||
{
|
||||
nat66_main_t *nm = &nat66_main;
|
||||
u32 sw_if_index;
|
||||
snat_interface_t *i;
|
||||
nat66_interface_t *i;
|
||||
fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
|
||||
fib_prefix_t pfx = {
|
||||
.fp_proto = FIB_PROTOCOL_IP6,
|
||||
@@ -99,7 +99,7 @@ nat66_not_translate (u32 rx_fib_index, ip6_address_t ip6_addr)
|
||||
pool_foreach (i, nm->interfaces,
|
||||
({
|
||||
/* NAT packet aimed at outside interface */
|
||||
if (nat_interface_is_outside (i) && sw_if_index == i->sw_if_index)
|
||||
if (nat66_interface_is_outside (i) && sw_if_index == i->sw_if_index)
|
||||
return 0;
|
||||
}));
|
||||
/* *INDENT-ON* */
|
||||
@@ -17,7 +17,7 @@
|
||||
* @brief NAT66 outside to inside network translation
|
||||
*/
|
||||
|
||||
#include <nat/nat66.h>
|
||||
#include <nat/nat66/nat66.h>
|
||||
#include <vnet/ip/ip6_to_ip4.h>
|
||||
#include <vnet/fib/fib_table.h>
|
||||
|
||||
+1
-194
@@ -21,7 +21,6 @@
|
||||
#include <nat/nat.h>
|
||||
#include <nat/nat_det.h>
|
||||
#include <nat/nat64.h>
|
||||
#include <nat/nat66.h>
|
||||
#include <nat/nat_inlines.h>
|
||||
#include <nat/nat44/inlines.h>
|
||||
#include <nat/nat_ha.h>
|
||||
@@ -3035,194 +3034,6 @@ static void *vl_api_nat64_add_del_interface_addr_t_print
|
||||
FINISH;
|
||||
}
|
||||
|
||||
/*************/
|
||||
/*** NAT66 ***/
|
||||
/*************/
|
||||
|
||||
static void
|
||||
vl_api_nat66_add_del_interface_t_handler (vl_api_nat66_add_del_interface_t *
|
||||
mp)
|
||||
{
|
||||
snat_main_t *sm = &snat_main;
|
||||
vl_api_nat66_add_del_interface_reply_t *rmp;
|
||||
int rv = 0;
|
||||
|
||||
VALIDATE_SW_IF_INDEX (mp);
|
||||
|
||||
rv =
|
||||
nat66_interface_add_del (ntohl (mp->sw_if_index),
|
||||
mp->flags & NAT_API_IS_INSIDE, mp->is_add);
|
||||
|
||||
BAD_SW_IF_INDEX_LABEL;
|
||||
|
||||
REPLY_MACRO (VL_API_NAT66_ADD_DEL_INTERFACE_REPLY);
|
||||
}
|
||||
|
||||
static void *
|
||||
vl_api_nat66_add_del_interface_t_print (vl_api_nat66_add_del_interface_t * mp,
|
||||
void *handle)
|
||||
{
|
||||
u8 *s;
|
||||
|
||||
s = format (0, "SCRIPT: nat66_add_del_interface ");
|
||||
s = format (s, "sw_if_index %d %s %s",
|
||||
clib_host_to_net_u32 (mp->sw_if_index),
|
||||
mp->flags & NAT_API_IS_INSIDE ? "in" : "out",
|
||||
mp->is_add ? "" : "del");
|
||||
|
||||
FINISH;
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_nat66_add_del_static_mapping_t_handler
|
||||
(vl_api_nat66_add_del_static_mapping_t * mp)
|
||||
{
|
||||
snat_main_t *sm = &snat_main;
|
||||
vl_api_nat66_add_del_static_mapping_reply_t *rmp;
|
||||
ip6_address_t l_addr, e_addr;
|
||||
int rv = 0;
|
||||
|
||||
memcpy (&l_addr.as_u8, mp->local_ip_address, 16);
|
||||
memcpy (&e_addr.as_u8, mp->external_ip_address, 16);
|
||||
|
||||
rv =
|
||||
nat66_static_mapping_add_del (&l_addr, &e_addr,
|
||||
clib_net_to_host_u32 (mp->vrf_id),
|
||||
mp->is_add);
|
||||
|
||||
REPLY_MACRO (VL_API_NAT66_ADD_DEL_STATIC_MAPPING_REPLY);
|
||||
}
|
||||
|
||||
static void *vl_api_nat66_add_del_static_mapping_t_print
|
||||
(vl_api_nat66_add_del_static_mapping_t * mp, void *handle)
|
||||
{
|
||||
u8 *s;
|
||||
|
||||
s = format (0, "SCRIPT: nat66_add_del_static_mapping ");
|
||||
s = format (s, "local_ip_address %U external_ip_address %U vrf_id %d %s",
|
||||
format_ip6_address, mp->local_ip_address,
|
||||
format_ip6_address, mp->external_ip_address,
|
||||
clib_net_to_host_u32 (mp->vrf_id), mp->is_add ? "" : "del");
|
||||
|
||||
FINISH;
|
||||
}
|
||||
|
||||
typedef struct nat66_api_walk_ctx_t_
|
||||
{
|
||||
vl_api_registration_t *rp;
|
||||
u32 context;
|
||||
} nat66_api_walk_ctx_t;
|
||||
|
||||
static int
|
||||
nat66_api_interface_walk (snat_interface_t * i, void *arg)
|
||||
{
|
||||
vl_api_nat66_interface_details_t *rmp;
|
||||
snat_main_t *sm = &snat_main;
|
||||
nat66_api_walk_ctx_t *ctx = arg;
|
||||
|
||||
rmp = vl_msg_api_alloc (sizeof (*rmp));
|
||||
clib_memset (rmp, 0, sizeof (*rmp));
|
||||
rmp->_vl_msg_id = ntohs (VL_API_NAT66_INTERFACE_DETAILS + sm->msg_id_base);
|
||||
rmp->sw_if_index = ntohl (i->sw_if_index);
|
||||
if (nat_interface_is_inside (i))
|
||||
rmp->flags |= NAT_API_IS_INSIDE;
|
||||
rmp->context = ctx->context;
|
||||
|
||||
vl_api_send_msg (ctx->rp, (u8 *) rmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_nat66_interface_dump_t_handler (vl_api_nat66_interface_dump_t * mp)
|
||||
{
|
||||
vl_api_registration_t *rp;
|
||||
|
||||
rp = vl_api_client_index_to_registration (mp->client_index);
|
||||
if (rp == 0)
|
||||
return;
|
||||
|
||||
nat66_api_walk_ctx_t ctx = {
|
||||
.rp = rp,
|
||||
.context = mp->context,
|
||||
};
|
||||
|
||||
nat66_interfaces_walk (nat66_api_interface_walk, &ctx);
|
||||
}
|
||||
|
||||
static void *
|
||||
vl_api_nat66_interface_dump_t_print (vl_api_nat66_interface_dump_t * mp,
|
||||
void *handle)
|
||||
{
|
||||
u8 *s;
|
||||
|
||||
s = format (0, "SCRIPT: nat66_interface_dump ");
|
||||
|
||||
FINISH;
|
||||
}
|
||||
|
||||
static int
|
||||
nat66_api_static_mapping_walk (nat66_static_mapping_t * m, void *arg)
|
||||
{
|
||||
vl_api_nat66_static_mapping_details_t *rmp;
|
||||
nat66_main_t *nm = &nat66_main;
|
||||
snat_main_t *sm = &snat_main;
|
||||
nat66_api_walk_ctx_t *ctx = arg;
|
||||
fib_table_t *fib;
|
||||
vlib_counter_t vc;
|
||||
|
||||
fib = fib_table_get (m->fib_index, FIB_PROTOCOL_IP6);
|
||||
if (!fib)
|
||||
return -1;
|
||||
|
||||
vlib_get_combined_counter (&nm->session_counters, m - nm->sm, &vc);
|
||||
|
||||
rmp = vl_msg_api_alloc (sizeof (*rmp));
|
||||
clib_memset (rmp, 0, sizeof (*rmp));
|
||||
rmp->_vl_msg_id =
|
||||
ntohs (VL_API_NAT66_STATIC_MAPPING_DETAILS + sm->msg_id_base);
|
||||
clib_memcpy (rmp->local_ip_address, &m->l_addr, 16);
|
||||
clib_memcpy (rmp->external_ip_address, &m->e_addr, 16);
|
||||
rmp->vrf_id = ntohl (fib->ft_table_id);
|
||||
rmp->total_bytes = clib_host_to_net_u64 (vc.bytes);
|
||||
rmp->total_pkts = clib_host_to_net_u64 (vc.packets);
|
||||
rmp->context = ctx->context;
|
||||
|
||||
vl_api_send_msg (ctx->rp, (u8 *) rmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_nat66_static_mapping_dump_t_handler (vl_api_nat66_static_mapping_dump_t
|
||||
* mp)
|
||||
{
|
||||
vl_api_registration_t *rp;
|
||||
|
||||
rp = vl_api_client_index_to_registration (mp->client_index);
|
||||
if (rp == 0)
|
||||
return;
|
||||
|
||||
nat66_api_walk_ctx_t ctx = {
|
||||
.rp = rp,
|
||||
.context = mp->context,
|
||||
};
|
||||
|
||||
nat66_static_mappings_walk (nat66_api_static_mapping_walk, &ctx);
|
||||
}
|
||||
|
||||
static void *
|
||||
vl_api_nat66_static_mapping_dump_t_print (vl_api_nat66_static_mapping_dump_t *
|
||||
mp, void *handle)
|
||||
{
|
||||
u8 *s;
|
||||
|
||||
s = format (0, "SCRIPT: nat66_static_mapping_dump ");
|
||||
|
||||
FINISH;
|
||||
}
|
||||
|
||||
|
||||
/* List of message types that this plugin understands */
|
||||
#define foreach_snat_plugin_api_msg \
|
||||
_(NAT_CONTROL_PING, nat_control_ping) \
|
||||
@@ -3284,11 +3095,7 @@ _(NAT64_BIB_DUMP, nat64_bib_dump) \
|
||||
_(NAT64_ST_DUMP, nat64_st_dump) \
|
||||
_(NAT64_ADD_DEL_PREFIX, nat64_add_del_prefix) \
|
||||
_(NAT64_PREFIX_DUMP, nat64_prefix_dump) \
|
||||
_(NAT64_ADD_DEL_INTERFACE_ADDR, nat64_add_del_interface_addr) \
|
||||
_(NAT66_ADD_DEL_INTERFACE, nat66_add_del_interface) \
|
||||
_(NAT66_INTERFACE_DUMP, nat66_interface_dump) \
|
||||
_(NAT66_ADD_DEL_STATIC_MAPPING, nat66_add_del_static_mapping) \
|
||||
_(NAT66_STATIC_MAPPING_DUMP, nat66_static_mapping_dump)
|
||||
_(NAT64_ADD_DEL_INTERFACE_ADDR, nat64_add_del_interface_addr)
|
||||
|
||||
/* Set up the API message handling tables */
|
||||
static clib_error_t *
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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 = "0.0.1";
|
||||
|
||||
enum nat_config_flags : u8
|
||||
{
|
||||
NAT_IS_NONE = 0x00,
|
||||
NAT_IS_TWICE_NAT = 0x01,
|
||||
NAT_IS_SELF_TWICE_NAT = 0x02,
|
||||
NAT_IS_OUT2IN_ONLY = 0x04,
|
||||
NAT_IS_ADDR_ONLY = 0x08,
|
||||
NAT_IS_OUTSIDE = 0x10,
|
||||
NAT_IS_INSIDE = 0x20,
|
||||
NAT_IS_STATIC = 0x40,
|
||||
NAT_IS_EXT_HOST_VALID = 0x80,
|
||||
};
|
||||
@@ -9506,158 +9506,5 @@ class TestNAT64(MethodHolder):
|
||||
self.logger.info(self.vapi.cli("show nat64 session table all"))
|
||||
|
||||
|
||||
class TestNAT66(MethodHolder):
|
||||
""" NAT66 Test Cases """
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestNAT66, cls).setUpClass()
|
||||
|
||||
cls.nat_addr = 'fd01:ff::2'
|
||||
|
||||
cls.create_pg_interfaces(range(2))
|
||||
cls.interfaces = list(cls.pg_interfaces)
|
||||
|
||||
for i in cls.interfaces:
|
||||
i.admin_up()
|
||||
i.config_ip6()
|
||||
i.configure_ipv6_neighbors()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(TestNAT66, cls).tearDownClass()
|
||||
|
||||
def test_static(self):
|
||||
""" 1:1 NAT66 test """
|
||||
flags = self.config_flags.NAT_IS_INSIDE
|
||||
self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
|
||||
sw_if_index=self.pg0.sw_if_index)
|
||||
self.vapi.nat66_add_del_interface(is_add=1,
|
||||
sw_if_index=self.pg1.sw_if_index)
|
||||
self.vapi.nat66_add_del_static_mapping(
|
||||
local_ip_address=self.pg0.remote_ip6,
|
||||
external_ip_address=self.nat_addr,
|
||||
is_add=1)
|
||||
|
||||
# in2out
|
||||
pkts = []
|
||||
p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||
IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
|
||||
TCP())
|
||||
pkts.append(p)
|
||||
p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||
IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
|
||||
UDP())
|
||||
pkts.append(p)
|
||||
p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||
IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
|
||||
ICMPv6EchoRequest())
|
||||
pkts.append(p)
|
||||
p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||
IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
|
||||
GRE() / IP() / TCP())
|
||||
pkts.append(p)
|
||||
self.pg0.add_stream(pkts)
|
||||
self.pg_enable_capture(self.pg_interfaces)
|
||||
self.pg_start()
|
||||
capture = self.pg1.get_capture(len(pkts))
|
||||
|
||||
for packet in capture:
|
||||
try:
|
||||
self.assertEqual(packet[IPv6].src, self.nat_addr)
|
||||
self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
|
||||
self.assert_packet_checksums_valid(packet)
|
||||
except:
|
||||
self.logger.error(ppp("Unexpected or invalid packet:", packet))
|
||||
raise
|
||||
|
||||
# out2in
|
||||
pkts = []
|
||||
p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
|
||||
IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
|
||||
TCP())
|
||||
pkts.append(p)
|
||||
p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
|
||||
IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
|
||||
UDP())
|
||||
pkts.append(p)
|
||||
p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
|
||||
IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
|
||||
ICMPv6EchoReply())
|
||||
pkts.append(p)
|
||||
p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
|
||||
IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
|
||||
GRE() / IP() / TCP())
|
||||
pkts.append(p)
|
||||
self.pg1.add_stream(pkts)
|
||||
self.pg_enable_capture(self.pg_interfaces)
|
||||
self.pg_start()
|
||||
capture = self.pg0.get_capture(len(pkts))
|
||||
for packet in capture:
|
||||
try:
|
||||
self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
|
||||
self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
|
||||
self.assert_packet_checksums_valid(packet)
|
||||
except:
|
||||
self.logger.error(ppp("Unexpected or invalid packet:", packet))
|
||||
raise
|
||||
|
||||
sm = self.vapi.nat66_static_mapping_dump()
|
||||
self.assertEqual(len(sm), 1)
|
||||
self.assertEqual(sm[0].total_pkts, 8)
|
||||
|
||||
def test_check_no_translate(self):
|
||||
""" NAT66 translate only when egress interface is outside interface """
|
||||
flags = self.config_flags.NAT_IS_INSIDE
|
||||
self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
|
||||
sw_if_index=self.pg0.sw_if_index)
|
||||
self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
|
||||
sw_if_index=self.pg1.sw_if_index)
|
||||
self.vapi.nat66_add_del_static_mapping(
|
||||
local_ip_address=self.pg0.remote_ip6,
|
||||
external_ip_address=self.nat_addr,
|
||||
is_add=1)
|
||||
|
||||
# in2out
|
||||
p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||
IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
|
||||
UDP())
|
||||
self.pg0.add_stream([p])
|
||||
self.pg_enable_capture(self.pg_interfaces)
|
||||
self.pg_start()
|
||||
capture = self.pg1.get_capture(1)
|
||||
packet = capture[0]
|
||||
try:
|
||||
self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
|
||||
self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
|
||||
except:
|
||||
self.logger.error(ppp("Unexpected or invalid packet:", packet))
|
||||
raise
|
||||
|
||||
def clear_nat66(self):
|
||||
"""
|
||||
Clear NAT66 configuration.
|
||||
"""
|
||||
interfaces = self.vapi.nat66_interface_dump()
|
||||
for intf in interfaces:
|
||||
self.vapi.nat66_add_del_interface(is_add=0, flags=intf.flags,
|
||||
sw_if_index=intf.sw_if_index)
|
||||
|
||||
static_mappings = self.vapi.nat66_static_mapping_dump()
|
||||
for sm in static_mappings:
|
||||
self.vapi.nat66_add_del_static_mapping(
|
||||
local_ip_address=sm.local_ip_address,
|
||||
external_ip_address=sm.external_ip_address, vrf_id=sm.vrf_id,
|
||||
is_add=0)
|
||||
|
||||
def tearDown(self):
|
||||
super(TestNAT66, self).tearDown()
|
||||
self.clear_nat66()
|
||||
|
||||
def show_commands_at_teardown(self):
|
||||
self.logger.info(self.vapi.cli("show nat66 interfaces"))
|
||||
self.logger.info(self.vapi.cli("show nat66 static mappings"))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(testRunner=VppTestRunner)
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import ipaddress
|
||||
import random
|
||||
import socket
|
||||
import struct
|
||||
import unittest
|
||||
from io import BytesIO
|
||||
from time import sleep
|
||||
|
||||
import scapy.compat
|
||||
from framework import VppTestCase, VppTestRunner, running_extended_tests
|
||||
from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
|
||||
from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
|
||||
IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
|
||||
PacketListField
|
||||
from scapy.data import IP_PROTOS
|
||||
from scapy.layers.inet import IP, TCP, UDP, ICMP
|
||||
from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
|
||||
from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
|
||||
from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
|
||||
ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6
|
||||
from scapy.layers.l2 import Ether, ARP, GRE
|
||||
from scapy.packet import Raw
|
||||
from syslog_rfc5424_parser import SyslogMessage, ParseError
|
||||
from syslog_rfc5424_parser.constants import SyslogSeverity
|
||||
from util import ip4_range
|
||||
from util import ppc, ppp
|
||||
from vpp_acl import AclRule, VppAcl, VppAclInterface
|
||||
from vpp_ip_route import VppIpRoute, VppRoutePath
|
||||
from vpp_neighbor import VppNeighbor
|
||||
from vpp_papi import VppEnum
|
||||
|
||||
|
||||
class MethodHolder(VppTestCase):
|
||||
""" NAT create capture and verify method holder """
|
||||
@property
|
||||
def config_flags(self):
|
||||
return VppEnum.vl_api_nat_config_flags_t
|
||||
|
||||
|
||||
class TestNAT66(MethodHolder):
|
||||
""" NAT66 Test Cases """
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestNAT66, cls).setUpClass()
|
||||
|
||||
cls.nat_addr = 'fd01:ff::2'
|
||||
|
||||
cls.create_pg_interfaces(range(2))
|
||||
cls.interfaces = list(cls.pg_interfaces)
|
||||
|
||||
for i in cls.interfaces:
|
||||
i.admin_up()
|
||||
i.config_ip6()
|
||||
i.configure_ipv6_neighbors()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(TestNAT66, cls).tearDownClass()
|
||||
|
||||
def test_static(self):
|
||||
""" 1:1 NAT66 test """
|
||||
flags = self.config_flags.NAT_IS_INSIDE
|
||||
self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
|
||||
sw_if_index=self.pg0.sw_if_index)
|
||||
self.vapi.nat66_add_del_interface(is_add=1,
|
||||
sw_if_index=self.pg1.sw_if_index)
|
||||
self.vapi.nat66_add_del_static_mapping(
|
||||
local_ip_address=self.pg0.remote_ip6,
|
||||
external_ip_address=self.nat_addr,
|
||||
is_add=1)
|
||||
|
||||
# in2out
|
||||
pkts = []
|
||||
p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||
IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
|
||||
TCP())
|
||||
pkts.append(p)
|
||||
p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||
IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
|
||||
UDP())
|
||||
pkts.append(p)
|
||||
p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||
IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
|
||||
ICMPv6EchoRequest())
|
||||
pkts.append(p)
|
||||
p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||
IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
|
||||
GRE() / IP() / TCP())
|
||||
pkts.append(p)
|
||||
self.pg0.add_stream(pkts)
|
||||
self.pg_enable_capture(self.pg_interfaces)
|
||||
self.pg_start()
|
||||
capture = self.pg1.get_capture(len(pkts))
|
||||
|
||||
for packet in capture:
|
||||
try:
|
||||
self.assertEqual(packet[IPv6].src, self.nat_addr)
|
||||
self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
|
||||
self.assert_packet_checksums_valid(packet)
|
||||
except:
|
||||
self.logger.error(ppp("Unexpected or invalid packet:", packet))
|
||||
raise
|
||||
|
||||
# out2in
|
||||
pkts = []
|
||||
p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
|
||||
IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
|
||||
TCP())
|
||||
pkts.append(p)
|
||||
p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
|
||||
IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
|
||||
UDP())
|
||||
pkts.append(p)
|
||||
p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
|
||||
IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
|
||||
ICMPv6EchoReply())
|
||||
pkts.append(p)
|
||||
p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
|
||||
IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
|
||||
GRE() / IP() / TCP())
|
||||
pkts.append(p)
|
||||
self.pg1.add_stream(pkts)
|
||||
self.pg_enable_capture(self.pg_interfaces)
|
||||
self.pg_start()
|
||||
capture = self.pg0.get_capture(len(pkts))
|
||||
for packet in capture:
|
||||
try:
|
||||
self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
|
||||
self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
|
||||
self.assert_packet_checksums_valid(packet)
|
||||
except:
|
||||
self.logger.error(ppp("Unexpected or invalid packet:", packet))
|
||||
raise
|
||||
|
||||
sm = self.vapi.nat66_static_mapping_dump()
|
||||
self.assertEqual(len(sm), 1)
|
||||
self.assertEqual(sm[0].total_pkts, 8)
|
||||
|
||||
def test_check_no_translate(self):
|
||||
""" NAT66 translate only when egress interface is outside interface """
|
||||
flags = self.config_flags.NAT_IS_INSIDE
|
||||
self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
|
||||
sw_if_index=self.pg0.sw_if_index)
|
||||
self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
|
||||
sw_if_index=self.pg1.sw_if_index)
|
||||
self.vapi.nat66_add_del_static_mapping(
|
||||
local_ip_address=self.pg0.remote_ip6,
|
||||
external_ip_address=self.nat_addr,
|
||||
is_add=1)
|
||||
|
||||
# in2out
|
||||
p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||
IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
|
||||
UDP())
|
||||
self.pg0.add_stream([p])
|
||||
self.pg_enable_capture(self.pg_interfaces)
|
||||
self.pg_start()
|
||||
capture = self.pg1.get_capture(1)
|
||||
packet = capture[0]
|
||||
try:
|
||||
self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
|
||||
self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
|
||||
except:
|
||||
self.logger.error(ppp("Unexpected or invalid packet:", packet))
|
||||
raise
|
||||
|
||||
def clear_nat66(self):
|
||||
"""
|
||||
Clear NAT66 configuration.
|
||||
"""
|
||||
interfaces = self.vapi.nat66_interface_dump()
|
||||
for intf in interfaces:
|
||||
self.vapi.nat66_add_del_interface(is_add=0, flags=intf.flags,
|
||||
sw_if_index=intf.sw_if_index)
|
||||
|
||||
static_mappings = self.vapi.nat66_static_mapping_dump()
|
||||
for sm in static_mappings:
|
||||
self.vapi.nat66_add_del_static_mapping(
|
||||
local_ip_address=sm.local_ip_address,
|
||||
external_ip_address=sm.external_ip_address, vrf_id=sm.vrf_id,
|
||||
is_add=0)
|
||||
|
||||
def tearDown(self):
|
||||
super(TestNAT66, self).tearDown()
|
||||
self.clear_nat66()
|
||||
|
||||
def show_commands_at_teardown(self):
|
||||
self.logger.info(self.vapi.cli("show nat66 interfaces"))
|
||||
self.logger.info(self.vapi.cli("show nat66 static mappings"))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(testRunner=VppTestRunner)
|
||||
Reference in New Issue
Block a user