From: Ole Troan Date: Thu, 19 Dec 2019 10:55:54 +0000 (+0100) Subject: nat: move dslite to separate sub-plugin X-Git-Tag: v20.09-rc0~657 X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commitdiff_plain;h=2c6639c695aebf0cd5ac74ad31fd331547fa0126 nat: move dslite to separate sub-plugin Type: refactor Change-Id: If3d9f16f3a06c10b354f1eef674e8db5f3c44de7 Signed-off-by: Ole Troan --- diff --git a/src/plugins/nat/CMakeLists.txt b/src/plugins/nat/CMakeLists.txt index edba893cafe..a1a01789240 100644 --- a/src/plugins/nat/CMakeLists.txt +++ b/src/plugins/nat/CMakeLists.txt @@ -11,21 +11,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -set(NAT_SRCS +set(CMAKE_VERBOSE_MAKEFILE ON) + +add_vpp_library(nat + SOURCES lib/alloc.c -) -set(NAT_HEADERS + INSTALL_HEADERS lib/alloc.h ) -add_vpp_library(nat - SOURCES ${NAT_SRCS} - LINK_LIBRARIES m - INSTALL_HEADERS ${NAT_HEADERS} - COMPONENT libnat -) - add_vpp_plugin(nat SOURCES nat.c @@ -48,13 +43,6 @@ add_vpp_plugin(nat nat64_in2out.c nat64_out2in.c nat64_db.c - dslite_dpo.c - dslite.c - dslite_in2out.c - dslite_out2in.c - dslite_cli.c - dslite_ce_encap.c - dslite_ce_decap.c nat66.c nat66_cli.c nat66_in2out.c @@ -65,10 +53,6 @@ add_vpp_plugin(nat nat_ha.c MULTIARCH_SOURCES - dslite_ce_decap.c - dslite_ce_encap.c - dslite_in2out.c - dslite_out2in.c in2out.c in2out_ed.c nat44_classify.c @@ -93,3 +77,28 @@ add_vpp_plugin(nat nat_all_api_h.h nat_msg_enum.h ) + +add_vpp_plugin(dslite + SOURCES + nat_format.c + nat_syslog.c + dslite/dslite_api.c + dslite/dslite_dpo.c + dslite/dslite.c + dslite/dslite_in2out.c + dslite/dslite_out2in.c + dslite/dslite_cli.c + dslite/dslite_ce_encap.c + dslite/dslite_ce_decap.c + + MULTIARCH_SOURCES + dslite/dslite_ce_decap.c + dslite/dslite_ce_encap.c + dslite/dslite_in2out.c + dslite/dslite_out2in.c + + API_FILES + dslite/dslite.api + + LINK_LIBRARIES nat +) diff --git a/src/plugins/nat/dslite/dslite.api b/src/plugins/nat/dslite/dslite.api new file mode 100644 index 00000000000..b5f8c5ba833 --- /dev/null +++ b/src/plugins/nat/dslite/dslite.api @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2019 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"; + +/** + * @file nat.api + * @brief VPP control-plane API messages. + * + * This file defines VPP control-plane API messages which are generally + * called through a shared memory interface. + */ + + +/* + * DS-Lite APIs + */ + +/** \brief Add/delete address range to DS-Lite pool + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param start_addr - start IPv4 address of the range + @param end_addr - end IPv4 address of the range + @param is_add - true if add, false if delete +*/ +autoreply define dslite_add_del_pool_addr_range { + u32 client_index; + u32 context; + vl_api_ip4_address_t start_addr; + vl_api_ip4_address_t end_addr; + bool is_add; +}; + +/** \brief Dump DS-Lite addresses + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ +define dslite_address_dump { + u32 client_index; + u32 context; +}; + +/** \brief DS-Lite address details response + @param context - sender context, to match reply w/ request + @param ip_address - IPv4 address +*/ +define dslite_address_details { + u32 context; + vl_api_ip4_address_t ip_address; +}; + +/** \brief Set AFTR IPv6 and IPv4 addresses + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param ip4_addr - IPv4 address + @param ip6_addr - IPv6 address +*/ +autoreply define dslite_set_aftr_addr { + u32 client_index; + u32 context; + vl_api_ip4_address_t ip4_addr; + vl_api_ip6_address_t ip6_addr; +}; + +/** \brief Get AFTR IPv6 and IPv4 addresses + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ +define dslite_get_aftr_addr { + u32 client_index; + u32 context; +}; + +/** \brief Response to get AFTR IPv6 and IPv4 addresses + @param context - sender context, to match reply w/ request + @param retval - return code + @param ip4_addr - IPv4 address + @param ip6_addr - IPv6 address +*/ +define dslite_get_aftr_addr_reply { + u32 context; + i32 retval; + vl_api_ip4_address_t ip4_addr; + vl_api_ip6_address_t ip6_addr; +}; + +/** \brief Set B4 IPv6 and IPv4 addresses + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param ip4_addr - IPv4 address + @param ip6_addr - IPv6 address +*/ +autoreply define dslite_set_b4_addr { + u32 client_index; + u32 context; + vl_api_ip4_address_t ip4_addr; + vl_api_ip6_address_t ip6_addr; +}; + +/** \brief Get B4 IPv6 and IPv4 addresses + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ +define dslite_get_b4_addr { + u32 client_index; + u32 context; +}; + +/** \brief Response to get B4 IPv6 and IPv4 addresses + @param context - sender context, to match reply w/ request + @param retval - return code + @param ip4_addr - IPv4 address + @param ip6_addr - IPv6 address +*/ +define dslite_get_b4_addr_reply { + u32 context; + i32 retval; + vl_api_ip4_address_t ip4_addr; + vl_api_ip6_address_t ip6_addr; +}; diff --git a/src/plugins/nat/dslite.c b/src/plugins/nat/dslite/dslite.c similarity index 83% rename from src/plugins/nat/dslite.c rename to src/plugins/nat/dslite/dslite.c index d9a17293fac..e03dd0c8431 100644 --- a/src/plugins/nat/dslite.c +++ b/src/plugins/nat/dslite/dslite.c @@ -12,13 +12,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include -#include +#include +#include +#include #include +#include dslite_main_t dslite_main; +fib_source_t nat_fib_src_hi; + +clib_error_t *dslite_api_hookup (vlib_main_t * vm); void +add_del_dslite_pool_addr_cb (ip4_address_t addr, u8 is_add, void *opaque); + +static clib_error_t * dslite_init (vlib_main_t * vm) { dslite_main_t *dm = &dslite_main; @@ -44,6 +52,10 @@ dslite_init (vlib_main_t * vm) dm->first_worker_index = 0; dm->num_workers = 0; + // init nat address pool + dm->pool.add_del_pool_addr_cb = add_del_dslite_pool_addr_cb; + dm->pool.alloc_addr_and_port_cb = nat_alloc_ip4_addr_and_port_cb_default; + p = hash_get_mem (tm->thread_registrations_by_name, "workers"); if (p) { @@ -88,6 +100,12 @@ dslite_init (vlib_main_t * vm) vlib_zero_simple_counter (&dm->total_sessions, 0); dslite_dpo_module_init (); + + nat_fib_src_hi = fib_source_allocate ("dslite-hi", + FIB_SOURCE_PRIORITY_HI, + FIB_SOURCE_BH_SIMPLE); + + return dslite_api_hookup (vm); } void @@ -184,57 +202,27 @@ dslite_set_b4_ip4_addr (dslite_main_t * dm, ip4_address_t * addr) return 0; } -int -dslite_add_del_pool_addr (dslite_main_t * dm, ip4_address_t * addr, u8 is_add) +void +add_del_dslite_pool_addr_cb (ip4_address_t addr, u8 is_add, void *opaque) { - vlib_thread_main_t *tm = vlib_get_thread_main (); - snat_address_t *a = 0; - int i = 0; dpo_id_t dpo_v4 = DPO_INVALID; fib_prefix_t pfx = { .fp_proto = FIB_PROTOCOL_IP4, .fp_len = 32, - .fp_addr.ip4.as_u32 = addr->as_u32, + .fp_addr.ip4.as_u32 = addr.as_u32, }; - for (i = 0; i < vec_len (dm->addr_pool); i++) - { - if (dm->addr_pool[i].addr.as_u32 == addr->as_u32) - { - a = dm->addr_pool + i; - break; - } - } if (is_add) { - if (a) - return VNET_API_ERROR_VALUE_EXIST; - vec_add2 (dm->addr_pool, a, 1); - a->addr = *addr; -#define _(N, i, n, s) \ - clib_bitmap_alloc (a->busy_##n##_port_bitmap, 65535); \ - a->busy_##n##_ports = 0; \ - vec_validate_init_empty (a->busy_##n##_ports_per_thread, tm->n_vlib_mains - 1, 0); - foreach_snat_protocol -#undef _ - dslite_dpo_create (DPO_PROTO_IP4, 0, &dpo_v4); + dslite_dpo_create (DPO_PROTO_IP4, 0, &dpo_v4); fib_table_entry_special_dpo_add (0, &pfx, nat_fib_src_hi, FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v4); dpo_reset (&dpo_v4); } else { - if (!a) - return VNET_API_ERROR_NO_SUCH_ENTRY; -#define _(N, id, n, s) \ - clib_bitmap_free (a->busy_##n##_port_bitmap); \ - vec_free (a->busy_##n##_ports_per_thread); - foreach_snat_protocol -#undef _ - fib_table_entry_special_remove (0, &pfx, nat_fib_src_hi); - vec_del1 (dm->addr_pool, i); + fib_table_entry_special_remove (0, &pfx, nat_fib_src_hi); } - return 0; } u8 * @@ -262,6 +250,12 @@ format_dslite_ce_trace (u8 * s, va_list * args) return s; } +VLIB_INIT_FUNCTION (dslite_init); + +VLIB_PLUGIN_REGISTER () = +{ +.version = VPP_BUILD_VER,.description = "Dual-Stack Lite",}; + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/plugins/nat/dslite.h b/src/plugins/nat/dslite/dslite.h similarity index 97% rename from src/plugins/nat/dslite.h rename to src/plugins/nat/dslite/dslite.h index 65498eebd9d..d512cf47c9b 100644 --- a/src/plugins/nat/dslite.h +++ b/src/plugins/nat/dslite/dslite.h @@ -18,7 +18,9 @@ #include #include #include +#include #include +#include typedef struct { @@ -82,11 +84,13 @@ typedef struct ip6_address_t b4_ip6_addr; ip4_address_t b4_ip4_addr; dslite_per_thread_data_t *per_thread_data; - snat_address_t *addr_pool; u32 num_workers; u32 first_worker_index; u16 port_per_thread; + /* nat address pool */ + nat_ip4_pool_t pool; + /* counters/gauges */ vlib_simple_counter_main_t total_b4s; vlib_simple_counter_main_t total_sessions; @@ -99,6 +103,8 @@ typedef struct /* If set then the DSLite component behaves as CPE/B4 * otherwise it behaves as AFTR */ u8 is_ce; + + u16 msg_id_base; } dslite_main_t; typedef struct @@ -139,7 +145,6 @@ extern vlib_node_registration_t dslite_out2in_node; extern vlib_node_registration_t dslite_ce_encap_node; extern vlib_node_registration_t dslite_ce_decap_node; -void dslite_init (vlib_main_t * vm); void dslite_set_ce (dslite_main_t * dm, u8 set); int dslite_set_aftr_ip6_addr (dslite_main_t * dm, ip6_address_t * addr); int dslite_set_b4_ip6_addr (dslite_main_t * dm, ip6_address_t * addr); diff --git a/src/plugins/nat/dslite/dslite_api.c b/src/plugins/nat/dslite/dslite_api.c new file mode 100644 index 00000000000..420e8212ad9 --- /dev/null +++ b/src/plugins/nat/dslite/dslite_api.c @@ -0,0 +1,177 @@ +/* + *------------------------------------------------------------------ + * dslite_api.c - DS-Lite API + * + * Copyright (c) 2019 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 +#include +#include +#include +#include +#include +#include + +#define REPLY_MSG_ID_BASE dm->msg_id_base +#include + +static void +vl_api_dslite_set_aftr_addr_t_handler (vl_api_dslite_set_aftr_addr_t * mp) +{ + vl_api_dslite_set_aftr_addr_reply_t *rmp; + dslite_main_t *dm = &dslite_main; + int rv = 0; + ip6_address_t ip6_addr; + ip4_address_t ip4_addr; + + memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16); + memcpy (&ip4_addr.as_u8, mp->ip4_addr, 4); + + rv = dslite_set_aftr_ip6_addr (dm, &ip6_addr); + if (rv == 0) + rv = dslite_set_aftr_ip4_addr (dm, &ip4_addr); + + REPLY_MACRO (VL_API_DSLITE_SET_AFTR_ADDR_REPLY); +} + +static void +vl_api_dslite_get_aftr_addr_t_handler (vl_api_dslite_get_aftr_addr_t * mp) +{ + vl_api_dslite_get_aftr_addr_reply_t *rmp; + dslite_main_t *dm = &dslite_main; + int rv = 0; + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_DSLITE_GET_AFTR_ADDR_REPLY, + ({ + memcpy (rmp->ip4_addr, &dm->aftr_ip4_addr.as_u8, 4); + memcpy (rmp->ip6_addr, &dm->aftr_ip6_addr.as_u8, 16); + })) + /* *INDENT-ON* */ +} + +static void +vl_api_dslite_set_b4_addr_t_handler (vl_api_dslite_set_b4_addr_t * mp) +{ + vl_api_dslite_set_b4_addr_reply_t *rmp; + dslite_main_t *dm = &dslite_main; + int rv = 0; + ip6_address_t ip6_addr; + ip4_address_t ip4_addr; + + memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16); + memcpy (&ip4_addr.as_u8, mp->ip4_addr, 4); + + rv = dslite_set_b4_ip6_addr (dm, &ip6_addr); + if (rv == 0) + rv = dslite_set_b4_ip4_addr (dm, &ip4_addr); + + REPLY_MACRO (VL_API_DSLITE_SET_B4_ADDR_REPLY); +} + +static void +vl_api_dslite_get_b4_addr_t_handler (vl_api_dslite_get_b4_addr_t * mp) +{ + vl_api_dslite_get_b4_addr_reply_t *rmp; + dslite_main_t *dm = &dslite_main; + int rv = 0; + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_DSLITE_GET_B4_ADDR_REPLY, + ({ + memcpy (rmp->ip4_addr, &dm->b4_ip4_addr.as_u8, 4); + memcpy (rmp->ip6_addr, &dm->b4_ip6_addr.as_u8, 16); + })) + /* *INDENT-ON* */ +} + +static void + vl_api_dslite_add_del_pool_addr_range_t_handler + (vl_api_dslite_add_del_pool_addr_range_t * mp) +{ + vl_api_dslite_add_del_pool_addr_range_reply_t *rmp; + dslite_main_t *dm = &dslite_main; + int rv = 0; + ip4_address_t this_addr; + u32 start_host_order, end_host_order; + int count; + u32 *tmp; + + tmp = (u32 *) mp->start_addr; + start_host_order = clib_host_to_net_u32 (tmp[0]); + tmp = (u32 *) mp->end_addr; + end_host_order = clib_host_to_net_u32 (tmp[0]); + + // TODO: + // end_host_order < start_host_order + + count = (end_host_order - start_host_order) + 1; + memcpy (&this_addr.as_u8, mp->start_addr, 4); + + rv = nat_add_del_ip4_pool_addrs (&dm->pool, this_addr, count, mp->is_add, 0); + + REPLY_MACRO (VL_API_DSLITE_ADD_DEL_POOL_ADDR_RANGE_REPLY); +} + +static void +send_dslite_address_details (nat_ip4_pool_addr_t * a, + vl_api_registration_t * reg, u32 context) +{ + dslite_main_t *dm = &dslite_main; + vl_api_dslite_address_details_t *rmp; + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + + clib_memset (rmp, 0, sizeof (*rmp)); + + rmp->_vl_msg_id = ntohs (VL_API_DSLITE_ADDRESS_DETAILS + dm->msg_id_base); + clib_memcpy (rmp->ip_address, &(a->addr), 4); + rmp->context = context; + + vl_api_send_msg (reg, (u8 *) rmp); +} + +static void +vl_api_dslite_address_dump_t_handler (vl_api_dslite_address_dump_t * mp) +{ + vl_api_registration_t *reg; + dslite_main_t *dm = &dslite_main; + nat_ip4_pool_addr_t *a; + + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + /* *INDENT-OFF* */ + vec_foreach (a, dm->pool.pool_addr) + { + send_dslite_address_details (a, reg, mp->context); + } + /* *INDENT-ON* */ +} + +/* API definitions */ +#include +#include + +/* Set up the API message handling tables */ +clib_error_t * +dslite_api_hookup (vlib_main_t * vm) +{ + dslite_main_t *dm = &dslite_main; + + dm->msg_id_base = setup_message_id_table (); + return 0; +} diff --git a/src/plugins/nat/dslite_ce_decap.c b/src/plugins/nat/dslite/dslite_ce_decap.c similarity index 99% rename from src/plugins/nat/dslite_ce_decap.c rename to src/plugins/nat/dslite/dslite_ce_decap.c index 77b80ea0f45..3d6ca992e45 100644 --- a/src/plugins/nat/dslite_ce_decap.c +++ b/src/plugins/nat/dslite/dslite_ce_decap.c @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include +#include #include typedef enum diff --git a/src/plugins/nat/dslite_ce_encap.c b/src/plugins/nat/dslite/dslite_ce_encap.c similarity index 99% rename from src/plugins/nat/dslite_ce_encap.c rename to src/plugins/nat/dslite/dslite_ce_encap.c index 39ff7975c3a..8cec5439243 100644 --- a/src/plugins/nat/dslite_ce_encap.c +++ b/src/plugins/nat/dslite/dslite_ce_encap.c @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include +#include #include typedef enum diff --git a/src/plugins/nat/dslite_cli.c b/src/plugins/nat/dslite/dslite_cli.c similarity index 93% rename from src/plugins/nat/dslite_cli.c rename to src/plugins/nat/dslite/dslite_cli.c index 515929b2135..d5c0ca6498b 100644 --- a/src/plugins/nat/dslite_cli.c +++ b/src/plugins/nat/dslite/dslite_cli.c @@ -13,7 +13,7 @@ * limitations under the License. */ -#include +#include static clib_error_t * dslite_add_del_pool_addr_command_fn (vlib_main_t * vm, @@ -24,7 +24,7 @@ dslite_add_del_pool_addr_command_fn (vlib_main_t * vm, unformat_input_t _line_input, *line_input = &_line_input; ip4_address_t start_addr, end_addr, this_addr; u32 start_host_order, end_host_order; - int i, count, rv; + int count, rv; u8 is_add = 1; clib_error_t *error = 0; @@ -62,27 +62,20 @@ dslite_add_del_pool_addr_command_fn (vlib_main_t * vm, count = (end_host_order - start_host_order) + 1; this_addr = start_addr; - for (i = 0; i < count; i++) - { - rv = dslite_add_del_pool_addr (dm, &this_addr, is_add); + rv = nat_add_del_ip4_pool_addrs (&dm->pool, this_addr, count, is_add, 0); - switch (rv) - { - case VNET_API_ERROR_NO_SUCH_ENTRY: - error = - clib_error_return (0, "DS-Lite pool address %U not exist.", - format_ip4_address, &this_addr); - goto done; - case VNET_API_ERROR_VALUE_EXIST: - error = - clib_error_return (0, "DS-Lite pool address %U exist.", - format_ip4_address, &this_addr); - goto done; - default: - break; - - } - increment_v4_address (&this_addr); + switch (rv) + { + case VNET_API_ERROR_NO_SUCH_ENTRY: + error = + clib_error_return (0, "DS-Lite pool address %U not exist.", + format_ip4_address, &this_addr); + break; + case VNET_API_ERROR_VALUE_EXIST: + error = + clib_error_return (0, "DS-Lite pool address %U exist.", + format_ip4_address, &this_addr); + break; } done: @@ -97,14 +90,14 @@ dslite_show_pool_command_fn (vlib_main_t * vm, vlib_cli_command_t * cmd) { dslite_main_t *dm = &dslite_main; - snat_address_t *ap; + nat_ip4_pool_addr_t *a; vlib_cli_output (vm, "DS-Lite pool:"); /* *INDENT-OFF* */ - vec_foreach (ap, dm->addr_pool) + vec_foreach (a, dm->pool.pool_addr) { - vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr); + vlib_cli_output (vm, "%U", format_ip4_address, &a->addr); } /* *INDENT-ON* */ return 0; diff --git a/src/plugins/nat/dslite_dpo.c b/src/plugins/nat/dslite/dslite_dpo.c similarity index 98% rename from src/plugins/nat/dslite_dpo.c rename to src/plugins/nat/dslite/dslite_dpo.c index 97ebb18cf70..009b5536289 100644 --- a/src/plugins/nat/dslite_dpo.c +++ b/src/plugins/nat/dslite/dslite_dpo.c @@ -14,7 +14,7 @@ */ #include -#include +#include dpo_type_t dslite_dpo_type; dpo_type_t dslite_ce_dpo_type; diff --git a/src/plugins/nat/dslite_dpo.h b/src/plugins/nat/dslite/dslite_dpo.h similarity index 100% rename from src/plugins/nat/dslite_dpo.h rename to src/plugins/nat/dslite/dslite_dpo.h diff --git a/src/plugins/nat/dslite_in2out.c b/src/plugins/nat/dslite/dslite_in2out.c similarity index 94% rename from src/plugins/nat/dslite_in2out.c rename to src/plugins/nat/dslite/dslite_in2out.c index 4494a77701e..d1ac17509c6 100644 --- a/src/plugins/nat/dslite_in2out.c +++ b/src/plugins/nat/dslite/dslite_in2out.c @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include +#include #include #include @@ -43,6 +43,7 @@ slow_path (dslite_main_t * dm, dslite_session_key_t * in2out_key, u32 oldest_index; dslite_session_t *s; snat_session_key_t out2in_key; + nat_ip4_addr_port_t addr_port; u32 b4_index; out2in_key.protocol = in2out_key->proto; @@ -105,28 +106,39 @@ slow_path (dslite_main_t * dm, dslite_session_key_t * in2out_key, out2in_kv.key = s->out2in.as_u64; clib_bihash_add_del_8_8 (&dm->per_thread_data[thread_index].out2in, &out2in_kv, 0); - snat_free_outside_address_and_port (dm->addr_pool, thread_index, - &s->out2in); + + addr_port.addr.as_u32 = s->out2in.addr.as_u32; + addr_port.port = s->out2in.port; + + nat_free_ip4_addr_and_port (&dm->pool, thread_index, + s->out2in.protocol, &addr_port); nat_syslog_dslite_apmdel (b4_index, &s->in2out.softwire_id, &s->in2out.addr, s->in2out.port, &s->out2in.addr, s->out2in.port, s->in2out.proto); - if (snat_alloc_outside_address_and_port - (dm->addr_pool, 0, thread_index, &out2in_key, - dm->port_per_thread, thread_index)) + if (nat_alloc_ip4_addr_and_port + (&dm->pool, 0, thread_index, thread_index, + dm->port_per_thread, out2in_key.protocol, &addr_port)) ASSERT (0); + + out2in_key.addr.as_u32 = addr_port.addr.as_u32; + out2in_key.port = addr_port.port; } else { - if (snat_alloc_outside_address_and_port - (dm->addr_pool, 0, thread_index, &out2in_key, - dm->port_per_thread, thread_index)) + if (nat_alloc_ip4_addr_and_port + (&dm->pool, 0, thread_index, thread_index, + dm->port_per_thread, out2in_key.protocol, &addr_port)) { *error = DSLITE_ERROR_OUT_OF_PORTS; return DSLITE_IN2OUT_NEXT_DROP; } + + out2in_key.addr.as_u32 = addr_port.addr.as_u32; + out2in_key.port = addr_port.port; + pool_get (dm->per_thread_data[thread_index].sessions, s); clib_memset (s, 0, sizeof (*s)); b4->nsessions++; @@ -391,7 +403,7 @@ dslite_in2out_node_fn_inline (vlib_main_t * vm, vlib_node_runtime_t * node, sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t, length); - mss_clamping (&snat_main, tcp0, &sum0); + //mss_clamping (&dslite_main, tcp0, &sum0); tcp0->checksum = ip_csum_fold (sum0); } else diff --git a/src/plugins/nat/dslite_out2in.c b/src/plugins/nat/dslite/dslite_out2in.c similarity index 99% rename from src/plugins/nat/dslite_out2in.c rename to src/plugins/nat/dslite/dslite_out2in.c index 265d79fc53e..ac64a589509 100644 --- a/src/plugins/nat/dslite_out2in.c +++ b/src/plugins/nat/dslite/dslite_out2in.c @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include +#include #include typedef enum diff --git a/src/plugins/nat/nat.api b/src/plugins/nat/nat.api index 356dd0ce8a9..58eee45d47d 100644 --- a/src/plugins/nat/nat.api +++ b/src/plugins/nat/nat.api @@ -1364,113 +1364,6 @@ autoreply define nat64_add_del_interface_addr { vl_api_interface_index_t sw_if_index; }; -/* - * DS-Lite APIs - */ - -/** \brief Add/delete address range to DS-Lite pool - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param start_addr - start IPv4 address of the range - @param end_addr - end IPv4 address of the range - @param is_add - true if add, false if delete -*/ -autoreply define dslite_add_del_pool_addr_range { - u32 client_index; - u32 context; - vl_api_ip4_address_t start_addr; - vl_api_ip4_address_t end_addr; - bool is_add; -}; - -/** \brief Dump DS-Lite addresses - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request -*/ -define dslite_address_dump { - u32 client_index; - u32 context; -}; - -/** \brief DS-Lite address details response - @param context - sender context, to match reply w/ request - @param ip_address - IPv4 address -*/ -define dslite_address_details { - u32 context; - vl_api_ip4_address_t ip_address; -}; - -/** \brief Set AFTR IPv6 and IPv4 addresses - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param ip4_addr - IPv4 address - @param ip6_addr - IPv6 address -*/ -autoreply define dslite_set_aftr_addr { - u32 client_index; - u32 context; - vl_api_ip4_address_t ip4_addr; - vl_api_ip6_address_t ip6_addr; -}; - -/** \brief Get AFTR IPv6 and IPv4 addresses - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request -*/ -define dslite_get_aftr_addr { - u32 client_index; - u32 context; -}; - -/** \brief Response to get AFTR IPv6 and IPv4 addresses - @param context - sender context, to match reply w/ request - @param retval - return code - @param ip4_addr - IPv4 address - @param ip6_addr - IPv6 address -*/ -define dslite_get_aftr_addr_reply { - u32 context; - i32 retval; - vl_api_ip4_address_t ip4_addr; - vl_api_ip6_address_t ip6_addr; -}; - -/** \brief Set B4 IPv6 and IPv4 addresses - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param ip4_addr - IPv4 address - @param ip6_addr - IPv6 address -*/ -autoreply define dslite_set_b4_addr { - u32 client_index; - u32 context; - vl_api_ip4_address_t ip4_addr; - vl_api_ip6_address_t ip6_addr; -}; - -/** \brief Get B4 IPv6 and IPv4 addresses - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request -*/ -define dslite_get_b4_addr { - u32 client_index; - u32 context; -}; - -/** \brief Response to get B4 IPv6 and IPv4 addresses - @param context - sender context, to match reply w/ request - @param retval - return code - @param ip4_addr - IPv4 address - @param ip6_addr - IPv6 address -*/ -define dslite_get_b4_addr_reply { - u32 context; - i32 retval; - vl_api_ip4_address_t ip4_addr; - vl_api_ip6_address_t ip6_addr; -}; - /* * NAT66 APIs */ diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index 14855323ab7..9f516586877 100755 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -640,15 +639,6 @@ is_snat_address_used_in_static_mapping (snat_main_t * sm, ip4_address_t addr) return 0; } -void -increment_v4_address (ip4_address_t * a) -{ - u32 v; - - v = clib_net_to_host_u32 (a->as_u32) + 1; - a->as_u32 = clib_host_to_net_u32 (v); -} - static void snat_add_static_mapping_when_resolved (snat_main_t * sm, ip4_address_t l_addr, @@ -2507,8 +2497,6 @@ snat_init (vlib_main_t * vm) if (error) return error; - dslite_init (vm); - nat66_init (vm); ip4_table_bind_callback_t cbt4 = { @@ -3755,7 +3743,7 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) { snat_main_t *sm = &snat_main; nat66_main_t *nm = &nat66_main; - dslite_main_t *dm = &dslite_main; + //dslite_main_t *dm = &dslite_main; snat_main_per_thread_data_t *tsm; u32 static_mapping_buckets = 1024; @@ -3840,8 +3828,8 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) ; else if (unformat (input, "out2in dpo")) sm->out2in_dpo = 1; - else if (unformat (input, "dslite ce")) - dslite_set_ce (dm, 1); + //else if (unformat (input, "dslite ce")) + //dslite_set_ce (dm, 1); else if (unformat (input, "endpoint-dependent")) sm->endpoint_dependent = 1; else diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h index d3fa3eea38a..9cde96840f8 100644 --- a/src/plugins/nat/nat.h +++ b/src/plugins/nat/nat.h @@ -1119,11 +1119,6 @@ int nat44_o2i_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg); int nat44_i2o_is_idle_session_cb (clib_bihash_kv_8_8_t * kv, void *arg); int nat44_o2i_is_idle_session_cb (clib_bihash_kv_8_8_t * kv, void *arg); -/** - * @brief Increment IPv4 address - */ -void increment_v4_address (ip4_address_t * a); - /** * @brief Add external address to NAT44 pool * diff --git a/src/plugins/nat/nat_api.c b/src/plugins/nat/nat_api.c index 6df1a851e48..d73a0337d2a 100644 --- a/src/plugins/nat/nat_api.c +++ b/src/plugins/nat/nat_api.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -96,7 +95,7 @@ vl_api_nat_show_config_t_handler (vl_api_nat_show_config_t * mp) { vl_api_nat_show_config_reply_t *rmp; snat_main_t *sm = &snat_main; - dslite_main_t *dm = &dslite_main; + //dslite_main_t *dm = &dslite_main; nat64_main_t *n64m = &nat64_main; int rv = 0; @@ -116,7 +115,7 @@ vl_api_nat_show_config_t_handler (vl_api_nat_show_config_t * mp) rmp->deterministic = sm->deterministic; rmp->endpoint_dependent = sm->endpoint_dependent; rmp->out2in_dpo = sm->out2in_dpo; - rmp->dslite_ce = dm->is_ce; + //rmp->dslite_ce = dm->is_ce; rmp->nat64_bib_buckets = n64m->bib_buckets; rmp->nat64_bib_memory_size = n64m->bib_memory_size; rmp->nat64_st_buckets = n64m->st_buckets; @@ -2901,229 +2900,6 @@ static void *vl_api_nat64_add_del_interface_addr_t_print FINISH; } -/***************/ -/*** DS-Lite ***/ -/***************/ - -static void -vl_api_dslite_set_aftr_addr_t_handler (vl_api_dslite_set_aftr_addr_t * mp) -{ - vl_api_dslite_set_aftr_addr_reply_t *rmp; - snat_main_t *sm = &snat_main; - dslite_main_t *dm = &dslite_main; - int rv = 0; - ip6_address_t ip6_addr; - ip4_address_t ip4_addr; - - memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16); - memcpy (&ip4_addr.as_u8, mp->ip4_addr, 4); - - rv = dslite_set_aftr_ip6_addr (dm, &ip6_addr); - if (rv == 0) - rv = dslite_set_aftr_ip4_addr (dm, &ip4_addr); - - REPLY_MACRO (VL_API_DSLITE_SET_AFTR_ADDR_REPLY); -} - -static void * -vl_api_dslite_set_aftr_addr_t_print (vl_api_dslite_set_aftr_addr_t * mp, - void *handle) -{ - u8 *s; - - s = format (0, "SCRIPT: dslite_set_aftr_addr "); - s = format (s, "ip6_addr %U ip4_addr %U\n", - format_ip6_address, mp->ip6_addr, - format_ip4_address, mp->ip4_addr); - - FINISH; -} - -static void -vl_api_dslite_get_aftr_addr_t_handler (vl_api_dslite_get_aftr_addr_t * mp) -{ - snat_main_t *sm = &snat_main; - vl_api_dslite_get_aftr_addr_reply_t *rmp; - dslite_main_t *dm = &dslite_main; - int rv = 0; - - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_DSLITE_GET_AFTR_ADDR_REPLY, - ({ - memcpy (rmp->ip4_addr, &dm->aftr_ip4_addr.as_u8, 4); - memcpy (rmp->ip6_addr, &dm->aftr_ip6_addr.as_u8, 16); - })) - /* *INDENT-ON* */ -} - -static void * -vl_api_dslite_get_aftr_addr_t_print (vl_api_dslite_get_aftr_addr_t * mp, - void *handle) -{ - u8 *s; - - s = format (0, "SCRIPT: dslite_get_aftr_addr"); - - FINISH; -} - -static void -vl_api_dslite_set_b4_addr_t_handler (vl_api_dslite_set_b4_addr_t * mp) -{ - vl_api_dslite_set_b4_addr_reply_t *rmp; - snat_main_t *sm = &snat_main; - dslite_main_t *dm = &dslite_main; - int rv = 0; - ip6_address_t ip6_addr; - ip4_address_t ip4_addr; - - memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16); - memcpy (&ip4_addr.as_u8, mp->ip4_addr, 4); - - rv = dslite_set_b4_ip6_addr (dm, &ip6_addr); - if (rv == 0) - rv = dslite_set_b4_ip4_addr (dm, &ip4_addr); - - REPLY_MACRO (VL_API_DSLITE_SET_B4_ADDR_REPLY); -} - -static void * -vl_api_dslite_set_b4_addr_t_print (vl_api_dslite_set_b4_addr_t * mp, - void *handle) -{ - u8 *s; - - s = format (0, "SCRIPT: dslite_set_b4_addr "); - s = format (s, "ip6_addr %U ip4_addr %U\n", - format_ip6_address, mp->ip6_addr, - format_ip6_address, mp->ip4_addr); - - FINISH; -} - -static void -vl_api_dslite_get_b4_addr_t_handler (vl_api_dslite_get_b4_addr_t * mp) -{ - snat_main_t *sm = &snat_main; - vl_api_dslite_get_b4_addr_reply_t *rmp; - dslite_main_t *dm = &dslite_main; - int rv = 0; - - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_DSLITE_GET_B4_ADDR_REPLY, - ({ - memcpy (rmp->ip4_addr, &dm->b4_ip4_addr.as_u8, 4); - memcpy (rmp->ip6_addr, &dm->b4_ip6_addr.as_u8, 16); - })) - /* *INDENT-ON* */ -} - -static void * -vl_api_dslite_get_b4_addr_t_print (vl_api_dslite_get_b4_addr_t * mp, - void *handle) -{ - u8 *s; - - s = format (0, "SCRIPT: dslite_get_b4_addr"); - - FINISH; -} - -static void - vl_api_dslite_add_del_pool_addr_range_t_handler - (vl_api_dslite_add_del_pool_addr_range_t * mp) -{ - vl_api_dslite_add_del_pool_addr_range_reply_t *rmp; - snat_main_t *sm = &snat_main; - dslite_main_t *dm = &dslite_main; - int rv = 0; - ip4_address_t this_addr; - u32 start_host_order, end_host_order; - int i, count; - u32 *tmp; - - tmp = (u32 *) mp->start_addr; - start_host_order = clib_host_to_net_u32 (tmp[0]); - tmp = (u32 *) mp->end_addr; - end_host_order = clib_host_to_net_u32 (tmp[0]); - - count = (end_host_order - start_host_order) + 1; - memcpy (&this_addr.as_u8, mp->start_addr, 4); - - for (i = 0; i < count; i++) - { - if ((rv = dslite_add_del_pool_addr (dm, &this_addr, mp->is_add))) - goto send_reply; - - increment_v4_address (&this_addr); - } - -send_reply: - REPLY_MACRO (VL_API_DSLITE_ADD_DEL_POOL_ADDR_RANGE_REPLY); -} - -static void -send_dslite_address_details (snat_address_t * ap, - vl_api_registration_t * reg, u32 context) -{ - vl_api_dslite_address_details_t *rmp; - snat_main_t *sm = &snat_main; - - rmp = vl_msg_api_alloc (sizeof (*rmp)); - - clib_memset (rmp, 0, sizeof (*rmp)); - - rmp->_vl_msg_id = ntohs (VL_API_DSLITE_ADDRESS_DETAILS + sm->msg_id_base); - clib_memcpy (rmp->ip_address, &(ap->addr), 4); - rmp->context = context; - - vl_api_send_msg (reg, (u8 *) rmp); -} - -static void -vl_api_dslite_address_dump_t_handler (vl_api_dslite_address_dump_t * mp) -{ - vl_api_registration_t *reg; - dslite_main_t *dm = &dslite_main; - snat_address_t *ap; - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - /* *INDENT-OFF* */ - vec_foreach (ap, dm->addr_pool) - { - send_dslite_address_details (ap, reg, mp->context); - } - /* *INDENT-ON* */ -} - -static void * -vl_api_dslite_address_dump_t_print (vl_api_dslite_address_dump_t * mp, - void *handle) -{ - u8 *s; - - s = format (0, "SCRIPT: dslite_address_dump "); - - FINISH; -} - -static void *vl_api_dslite_add_del_pool_addr_range_t_print - (vl_api_dslite_add_del_pool_addr_range_t * mp, void *handle) -{ - u8 *s; - - s = format (0, "SCRIPT: dslite_add_del_pool_addr_range "); - s = format (s, "%U - %U\n", - format_ip4_address, mp->start_addr, - format_ip4_address, mp->end_addr); - - FINISH; -} - - /*************/ /*** NAT66 ***/ /*************/ @@ -3372,12 +3148,6 @@ _(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) \ -_(DSLITE_ADD_DEL_POOL_ADDR_RANGE, dslite_add_del_pool_addr_range) \ -_(DSLITE_ADDRESS_DUMP, dslite_address_dump) \ -_(DSLITE_SET_AFTR_ADDR, dslite_set_aftr_addr) \ -_(DSLITE_GET_AFTR_ADDR, dslite_get_aftr_addr) \ -_(DSLITE_SET_B4_ADDR, dslite_set_b4_addr) \ -_(DSLITE_GET_B4_ADDR, dslite_get_b4_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) \ diff --git a/src/plugins/nat/nat_inlines.h b/src/plugins/nat/nat_inlines.h index a58317acdf3..f693032a685 100644 --- a/src/plugins/nat/nat_inlines.h +++ b/src/plugins/nat/nat_inlines.h @@ -692,6 +692,15 @@ snat_not_translate_fast (snat_main_t * sm, vlib_node_runtime_t * node, return 1; } +static inline void +increment_v4_address (ip4_address_t * a) +{ + u32 v; + + v = clib_net_to_host_u32 (a->as_u32) + 1; + a->as_u32 = clib_host_to_net_u32 (v); +} + #endif /* __included_nat_inlines_h__ */ /* diff --git a/src/plugins/nat/test/test_dslite.py b/src/plugins/nat/test/test_dslite.py new file mode 100644 index 00000000000..dfa7d7c7c21 --- /dev/null +++ b/src/plugins/nat/test/test_dslite.py @@ -0,0 +1,338 @@ +#!/usr/bin/env python3 + +import socket +import unittest +import struct +import random + +from framework import VppTestCase, VppTestRunner, running_extended_tests + +import scapy.compat +from scapy.layers.inet import IP, TCP, UDP, ICMP +from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror +from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \ + ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6 +from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment +from scapy.layers.l2 import Ether, ARP, GRE +from scapy.data import IP_PROTOS +from scapy.packet import bind_layers, Raw +from util import ppp +from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder +from time import sleep +from util import ip4_range +from vpp_papi import mac_pton +from syslog_rfc5424_parser import SyslogMessage, ParseError +from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity +from io import BytesIO +from vpp_papi import VppEnum +from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathType +from vpp_neighbor import VppNeighbor +from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \ + IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \ + PacketListField +from ipaddress import IPv6Network + + +class TestDSlite(VppTestCase): + """ DS-Lite Test Cases """ + + @classmethod + def setUpClass(cls): + super(TestDSlite, cls).setUpClass() + + try: + cls.nat_addr = '10.0.0.3' + + cls.create_pg_interfaces(range(3)) + cls.pg0.admin_up() + cls.pg0.config_ip4() + cls.pg0.resolve_arp() + cls.pg1.admin_up() + cls.pg1.config_ip6() + cls.pg1.generate_remote_hosts(2) + cls.pg1.configure_ipv6_neighbors() + cls.pg2.admin_up() + cls.pg2.config_ip4() + cls.pg2.resolve_arp() + + except Exception: + super(TestDSlite, cls).tearDownClass() + raise + + @classmethod + def tearDownClass(cls): + super(TestDSlite, cls).tearDownClass() + + def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport, + sv6enc, proto): + message = data.decode('utf-8') + try: + message = SyslogMessage.parse(message) + except ParseError as e: + self.logger.error(e) + else: + self.assertEqual(message.severity, SyslogSeverity.info) + self.assertEqual(message.appname, 'NAT') + self.assertEqual(message.msgid, 'APMADD') + sd_params = message.sd.get('napmap') + self.assertTrue(sd_params is not None) + self.assertEqual(sd_params.get('IATYP'), 'IPv4') + self.assertEqual(sd_params.get('ISADDR'), isaddr) + self.assertEqual(sd_params.get('ISPORT'), "%d" % isport) + self.assertEqual(sd_params.get('XATYP'), 'IPv4') + self.assertEqual(sd_params.get('XSADDR'), xsaddr) + self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport) + self.assertEqual(sd_params.get('PROTO'), "%d" % proto) + self.assertTrue(sd_params.get('SSUBIX') is not None) + self.assertEqual(sd_params.get('SV6ENC'), sv6enc) + + def test_dslite(self): + """ Test DS-Lite """ + nat_config = self.vapi.nat_show_config() + self.assertEqual(0, nat_config.dslite_ce) + + self.vapi.dslite_add_del_pool_addr_range(start_addr=self.nat_addr, + end_addr=self.nat_addr, + is_add=1) + aftr_ip4 = '192.0.0.1' + aftr_ip6 = '2001:db8:85a3::8a2e:370:1' + self.vapi.dslite_set_aftr_addr(ip4_addr=aftr_ip4, ip6_addr=aftr_ip6) + self.vapi.syslog_set_sender(self.pg2.local_ip4, self.pg2.remote_ip4) + + # UDP + p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / + IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) / + IP(dst=self.pg0.remote_ip4, src='192.168.1.1') / + UDP(sport=20000, dport=10000)) + self.pg1.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg0.get_capture(1) + capture = capture[0] + self.assertFalse(capture.haslayer(IPv6)) + self.assertEqual(capture[IP].src, self.nat_addr) + self.assertEqual(capture[IP].dst, self.pg0.remote_ip4) + self.assertNotEqual(capture[UDP].sport, 20000) + self.assertEqual(capture[UDP].dport, 10000) + self.assert_packet_checksums_valid(capture) + out_port = capture[UDP].sport + capture = self.pg2.get_capture(1) + self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1', + 20000, self.nat_addr, out_port, + self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp) + + p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / + IP(dst=self.nat_addr, src=self.pg0.remote_ip4) / + UDP(sport=10000, dport=out_port)) + self.pg0.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg1.get_capture(1) + capture = capture[0] + self.assertEqual(capture[IPv6].src, aftr_ip6) + self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6) + self.assertEqual(capture[IP].src, self.pg0.remote_ip4) + self.assertEqual(capture[IP].dst, '192.168.1.1') + self.assertEqual(capture[UDP].sport, 10000) + self.assertEqual(capture[UDP].dport, 20000) + self.assert_packet_checksums_valid(capture) + + # TCP + p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / + IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) / + IP(dst=self.pg0.remote_ip4, src='192.168.1.1') / + TCP(sport=20001, dport=10001)) + self.pg1.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg0.get_capture(1) + capture = capture[0] + self.assertFalse(capture.haslayer(IPv6)) + self.assertEqual(capture[IP].src, self.nat_addr) + self.assertEqual(capture[IP].dst, self.pg0.remote_ip4) + self.assertNotEqual(capture[TCP].sport, 20001) + self.assertEqual(capture[TCP].dport, 10001) + self.assert_packet_checksums_valid(capture) + out_port = capture[TCP].sport + + p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / + IP(dst=self.nat_addr, src=self.pg0.remote_ip4) / + TCP(sport=10001, dport=out_port)) + self.pg0.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg1.get_capture(1) + capture = capture[0] + self.assertEqual(capture[IPv6].src, aftr_ip6) + self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6) + self.assertEqual(capture[IP].src, self.pg0.remote_ip4) + self.assertEqual(capture[IP].dst, '192.168.1.1') + self.assertEqual(capture[TCP].sport, 10001) + self.assertEqual(capture[TCP].dport, 20001) + self.assert_packet_checksums_valid(capture) + + # ICMP + p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / + IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) / + IP(dst=self.pg0.remote_ip4, src='192.168.1.1') / + ICMP(id=4000, type='echo-request')) + self.pg1.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg0.get_capture(1) + capture = capture[0] + self.assertFalse(capture.haslayer(IPv6)) + self.assertEqual(capture[IP].src, self.nat_addr) + self.assertEqual(capture[IP].dst, self.pg0.remote_ip4) + self.assertNotEqual(capture[ICMP].id, 4000) + self.assert_packet_checksums_valid(capture) + out_id = capture[ICMP].id + + p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / + IP(dst=self.nat_addr, src=self.pg0.remote_ip4) / + ICMP(id=out_id, type='echo-reply')) + self.pg0.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg1.get_capture(1) + capture = capture[0] + self.assertEqual(capture[IPv6].src, aftr_ip6) + self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6) + self.assertEqual(capture[IP].src, self.pg0.remote_ip4) + self.assertEqual(capture[IP].dst, '192.168.1.1') + self.assertEqual(capture[ICMP].id, 4000) + self.assert_packet_checksums_valid(capture) + + # ping DS-Lite AFTR tunnel endpoint address + p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / + IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) / + ICMPv6EchoRequest()) + self.pg1.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg1.get_capture(1) + capture = capture[0] + self.assertEqual(capture[IPv6].src, aftr_ip6) + self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6) + self.assertTrue(capture.haslayer(ICMPv6EchoReply)) + + b4s = self.statistics.get_counter('/dslite/total-b4s') + self.assertEqual(b4s[0][0], 2) + sessions = self.statistics.get_counter('/dslite/total-sessions') + self.assertEqual(sessions[0][0], 3) + + def tearDown(self): + super(TestDSlite, self).tearDown() + + def show_commands_at_teardown(self): + self.logger.info(self.vapi.cli("show dslite pool")) + self.logger.info( + self.vapi.cli("show dslite aftr-tunnel-endpoint-address")) + self.logger.info(self.vapi.cli("show dslite sessions")) + + +class TestDSliteCE(): + """ DS-Lite CE Test Cases """ + + @classmethod + def setUpConstants(cls): + super(TestDSliteCE, cls).setUpConstants() + cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"]) + + @classmethod + def setUpClass(cls): + super(TestDSliteCE, cls).setUpClass() + + try: + cls.create_pg_interfaces(range(2)) + cls.pg0.admin_up() + cls.pg0.config_ip4() + cls.pg0.resolve_arp() + cls.pg1.admin_up() + cls.pg1.config_ip6() + cls.pg1.generate_remote_hosts(1) + cls.pg1.configure_ipv6_neighbors() + + except Exception: + super(TestDSliteCE, cls).tearDownClass() + raise + + @classmethod + def tearDownClass(cls): + super(TestDSliteCE, cls).tearDownClass() + + def test_dslite_ce(self): + """ Test DS-Lite CE """ + + nat_config = self.vapi.nat_show_config() + self.assertEqual(1, nat_config.dslite_ce) + + b4_ip4 = '192.0.0.2' + b4_ip6 = '2001:db8:62aa::375e:f4c1:1' + self.vapi.dslite_set_b4_addr(ip4_addr=b4_ip4, ip6_addr=b4_ip6) + + aftr_ip4 = '192.0.0.1' + aftr_ip6 = '2001:db8:85a3::8a2e:370:1' + aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6) + self.vapi.dslite_set_aftr_addr(ip4_addr=aftr_ip4, ip6_addr=aftr_ip6) + + r1 = VppIpRoute(self, aftr_ip6, 128, + [VppRoutePath(self.pg1.remote_ip6, + self.pg1.sw_if_index)]) + r1.add_vpp_config() + + # UDP encapsulation + p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / + IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) / + UDP(sport=10000, dport=20000)) + self.pg0.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg1.get_capture(1) + capture = capture[0] + self.assertEqual(capture[IPv6].src, b4_ip6) + self.assertEqual(capture[IPv6].dst, aftr_ip6) + self.assertEqual(capture[IP].src, self.pg0.remote_ip4) + self.assertEqual(capture[IP].dst, self.pg1.remote_ip4) + self.assertEqual(capture[UDP].sport, 10000) + self.assertEqual(capture[UDP].dport, 20000) + self.assert_packet_checksums_valid(capture) + + # UDP decapsulation + p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / + IPv6(dst=b4_ip6, src=aftr_ip6) / + IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) / + UDP(sport=20000, dport=10000)) + self.pg1.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg0.get_capture(1) + capture = capture[0] + self.assertFalse(capture.haslayer(IPv6)) + self.assertEqual(capture[IP].src, self.pg1.remote_ip4) + self.assertEqual(capture[IP].dst, self.pg0.remote_ip4) + self.assertEqual(capture[UDP].sport, 20000) + self.assertEqual(capture[UDP].dport, 10000) + self.assert_packet_checksums_valid(capture) + + # ping DS-Lite B4 tunnel endpoint address + p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / + IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) / + ICMPv6EchoRequest()) + self.pg1.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg1.get_capture(1) + capture = capture[0] + self.assertEqual(capture[IPv6].src, b4_ip6) + self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6) + self.assertTrue(capture.haslayer(ICMPv6EchoReply)) + + def tearDown(self): + super(TestDSliteCE, self).tearDown() + + def show_commands_at_teardown(self): + self.logger.info( + self.vapi.cli("show dslite aftr-tunnel-endpoint-address")) + self.logger.info( + self.vapi.cli("show dslite b4-tunnel-endpoint-address")) diff --git a/src/plugins/nat/test/test_nat.py b/src/plugins/nat/test/test_nat.py index f87065598f1..d16204e7217 100644 --- a/src/plugins/nat/test/test_nat.py +++ b/src/plugins/nat/test/test_nat.py @@ -9186,311 +9186,6 @@ class TestNAT64(MethodHolder): self.logger.info(self.vapi.cli("show nat64 session table all")) -class TestDSlite(MethodHolder): - """ DS-Lite Test Cases """ - - @classmethod - def setUpClass(cls): - super(TestDSlite, cls).setUpClass() - - try: - cls.nat_addr = '10.0.0.3' - - cls.create_pg_interfaces(range(3)) - cls.pg0.admin_up() - cls.pg0.config_ip4() - cls.pg0.resolve_arp() - cls.pg1.admin_up() - cls.pg1.config_ip6() - cls.pg1.generate_remote_hosts(2) - cls.pg1.configure_ipv6_neighbors() - cls.pg2.admin_up() - cls.pg2.config_ip4() - cls.pg2.resolve_arp() - - except Exception: - super(TestDSlite, cls).tearDownClass() - raise - - @classmethod - def tearDownClass(cls): - super(TestDSlite, cls).tearDownClass() - - def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport, - sv6enc, proto): - message = data.decode('utf-8') - try: - message = SyslogMessage.parse(message) - except ParseError as e: - self.logger.error(e) - else: - self.assertEqual(message.severity, SyslogSeverity.info) - self.assertEqual(message.appname, 'NAT') - self.assertEqual(message.msgid, 'APMADD') - sd_params = message.sd.get('napmap') - self.assertTrue(sd_params is not None) - self.assertEqual(sd_params.get('IATYP'), 'IPv4') - self.assertEqual(sd_params.get('ISADDR'), isaddr) - self.assertEqual(sd_params.get('ISPORT'), "%d" % isport) - self.assertEqual(sd_params.get('XATYP'), 'IPv4') - self.assertEqual(sd_params.get('XSADDR'), xsaddr) - self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport) - self.assertEqual(sd_params.get('PROTO'), "%d" % proto) - self.assertTrue(sd_params.get('SSUBIX') is not None) - self.assertEqual(sd_params.get('SV6ENC'), sv6enc) - - def test_dslite(self): - """ Test DS-Lite """ - nat_config = self.vapi.nat_show_config() - self.assertEqual(0, nat_config.dslite_ce) - - self.vapi.dslite_add_del_pool_addr_range(start_addr=self.nat_addr, - end_addr=self.nat_addr, - is_add=1) - aftr_ip4 = '192.0.0.1' - aftr_ip6 = '2001:db8:85a3::8a2e:370:1' - self.vapi.dslite_set_aftr_addr(ip4_addr=aftr_ip4, ip6_addr=aftr_ip6) - self.vapi.syslog_set_sender(self.pg2.local_ip4, self.pg2.remote_ip4) - - # UDP - p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / - IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) / - IP(dst=self.pg0.remote_ip4, src='192.168.1.1') / - UDP(sport=20000, dport=10000)) - self.pg1.add_stream(p) - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - capture = self.pg0.get_capture(1) - capture = capture[0] - self.assertFalse(capture.haslayer(IPv6)) - self.assertEqual(capture[IP].src, self.nat_addr) - self.assertEqual(capture[IP].dst, self.pg0.remote_ip4) - self.assertNotEqual(capture[UDP].sport, 20000) - self.assertEqual(capture[UDP].dport, 10000) - self.assert_packet_checksums_valid(capture) - out_port = capture[UDP].sport - capture = self.pg2.get_capture(1) - self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1', - 20000, self.nat_addr, out_port, - self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp) - - p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / - IP(dst=self.nat_addr, src=self.pg0.remote_ip4) / - UDP(sport=10000, dport=out_port)) - self.pg0.add_stream(p) - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - capture = self.pg1.get_capture(1) - capture = capture[0] - self.assertEqual(capture[IPv6].src, aftr_ip6) - self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6) - self.assertEqual(capture[IP].src, self.pg0.remote_ip4) - self.assertEqual(capture[IP].dst, '192.168.1.1') - self.assertEqual(capture[UDP].sport, 10000) - self.assertEqual(capture[UDP].dport, 20000) - self.assert_packet_checksums_valid(capture) - - # TCP - p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / - IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) / - IP(dst=self.pg0.remote_ip4, src='192.168.1.1') / - TCP(sport=20001, dport=10001)) - self.pg1.add_stream(p) - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - capture = self.pg0.get_capture(1) - capture = capture[0] - self.assertFalse(capture.haslayer(IPv6)) - self.assertEqual(capture[IP].src, self.nat_addr) - self.assertEqual(capture[IP].dst, self.pg0.remote_ip4) - self.assertNotEqual(capture[TCP].sport, 20001) - self.assertEqual(capture[TCP].dport, 10001) - self.assert_packet_checksums_valid(capture) - out_port = capture[TCP].sport - - p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / - IP(dst=self.nat_addr, src=self.pg0.remote_ip4) / - TCP(sport=10001, dport=out_port)) - self.pg0.add_stream(p) - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - capture = self.pg1.get_capture(1) - capture = capture[0] - self.assertEqual(capture[IPv6].src, aftr_ip6) - self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6) - self.assertEqual(capture[IP].src, self.pg0.remote_ip4) - self.assertEqual(capture[IP].dst, '192.168.1.1') - self.assertEqual(capture[TCP].sport, 10001) - self.assertEqual(capture[TCP].dport, 20001) - self.assert_packet_checksums_valid(capture) - - # ICMP - p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / - IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) / - IP(dst=self.pg0.remote_ip4, src='192.168.1.1') / - ICMP(id=4000, type='echo-request')) - self.pg1.add_stream(p) - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - capture = self.pg0.get_capture(1) - capture = capture[0] - self.assertFalse(capture.haslayer(IPv6)) - self.assertEqual(capture[IP].src, self.nat_addr) - self.assertEqual(capture[IP].dst, self.pg0.remote_ip4) - self.assertNotEqual(capture[ICMP].id, 4000) - self.assert_packet_checksums_valid(capture) - out_id = capture[ICMP].id - - p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / - IP(dst=self.nat_addr, src=self.pg0.remote_ip4) / - ICMP(id=out_id, type='echo-reply')) - self.pg0.add_stream(p) - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - capture = self.pg1.get_capture(1) - capture = capture[0] - self.assertEqual(capture[IPv6].src, aftr_ip6) - self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6) - self.assertEqual(capture[IP].src, self.pg0.remote_ip4) - self.assertEqual(capture[IP].dst, '192.168.1.1') - self.assertEqual(capture[ICMP].id, 4000) - self.assert_packet_checksums_valid(capture) - - # ping DS-Lite AFTR tunnel endpoint address - p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / - IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) / - ICMPv6EchoRequest()) - self.pg1.add_stream(p) - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - capture = self.pg1.get_capture(1) - capture = capture[0] - self.assertEqual(capture[IPv6].src, aftr_ip6) - self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6) - self.assertTrue(capture.haslayer(ICMPv6EchoReply)) - - b4s = self.statistics.get_counter('/dslite/total-b4s') - self.assertEqual(b4s[0][0], 2) - sessions = self.statistics.get_counter('/dslite/total-sessions') - self.assertEqual(sessions[0][0], 3) - - def tearDown(self): - super(TestDSlite, self).tearDown() - - def show_commands_at_teardown(self): - self.logger.info(self.vapi.cli("show dslite pool")) - self.logger.info( - self.vapi.cli("show dslite aftr-tunnel-endpoint-address")) - self.logger.info(self.vapi.cli("show dslite sessions")) - - -class TestDSliteCE(MethodHolder): - """ DS-Lite CE Test Cases """ - - @classmethod - def setUpConstants(cls): - super(TestDSliteCE, cls).setUpConstants() - cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"]) - - @classmethod - def setUpClass(cls): - super(TestDSliteCE, cls).setUpClass() - - try: - cls.create_pg_interfaces(range(2)) - cls.pg0.admin_up() - cls.pg0.config_ip4() - cls.pg0.resolve_arp() - cls.pg1.admin_up() - cls.pg1.config_ip6() - cls.pg1.generate_remote_hosts(1) - cls.pg1.configure_ipv6_neighbors() - - except Exception: - super(TestDSliteCE, cls).tearDownClass() - raise - - @classmethod - def tearDownClass(cls): - super(TestDSliteCE, cls).tearDownClass() - - def test_dslite_ce(self): - """ Test DS-Lite CE """ - - nat_config = self.vapi.nat_show_config() - self.assertEqual(1, nat_config.dslite_ce) - - b4_ip4 = '192.0.0.2' - b4_ip6 = '2001:db8:62aa::375e:f4c1:1' - self.vapi.dslite_set_b4_addr(ip4_addr=b4_ip4, ip6_addr=b4_ip6) - - aftr_ip4 = '192.0.0.1' - aftr_ip6 = '2001:db8:85a3::8a2e:370:1' - aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6) - self.vapi.dslite_set_aftr_addr(ip4_addr=aftr_ip4, ip6_addr=aftr_ip6) - - r1 = VppIpRoute(self, aftr_ip6, 128, - [VppRoutePath(self.pg1.remote_ip6, - self.pg1.sw_if_index)]) - r1.add_vpp_config() - - # UDP encapsulation - p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / - IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) / - UDP(sport=10000, dport=20000)) - self.pg0.add_stream(p) - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - capture = self.pg1.get_capture(1) - capture = capture[0] - self.assertEqual(capture[IPv6].src, b4_ip6) - self.assertEqual(capture[IPv6].dst, aftr_ip6) - self.assertEqual(capture[IP].src, self.pg0.remote_ip4) - self.assertEqual(capture[IP].dst, self.pg1.remote_ip4) - self.assertEqual(capture[UDP].sport, 10000) - self.assertEqual(capture[UDP].dport, 20000) - self.assert_packet_checksums_valid(capture) - - # UDP decapsulation - p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / - IPv6(dst=b4_ip6, src=aftr_ip6) / - IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) / - UDP(sport=20000, dport=10000)) - self.pg1.add_stream(p) - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - capture = self.pg0.get_capture(1) - capture = capture[0] - self.assertFalse(capture.haslayer(IPv6)) - self.assertEqual(capture[IP].src, self.pg1.remote_ip4) - self.assertEqual(capture[IP].dst, self.pg0.remote_ip4) - self.assertEqual(capture[UDP].sport, 20000) - self.assertEqual(capture[UDP].dport, 10000) - self.assert_packet_checksums_valid(capture) - - # ping DS-Lite B4 tunnel endpoint address - p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / - IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) / - ICMPv6EchoRequest()) - self.pg1.add_stream(p) - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - capture = self.pg1.get_capture(1) - capture = capture[0] - self.assertEqual(capture[IPv6].src, b4_ip6) - self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6) - self.assertTrue(capture.haslayer(ICMPv6EchoReply)) - - def tearDown(self): - super(TestDSliteCE, self).tearDown() - - def show_commands_at_teardown(self): - self.logger.info( - self.vapi.cli("show dslite aftr-tunnel-endpoint-address")) - self.logger.info( - self.vapi.cli("show dslite b4-tunnel-endpoint-address")) - - class TestNAT66(MethodHolder): """ NAT66 Test Cases """