nat: move dslite to separate sub-plugin 69/24069/9
authorOle Troan <ot@cisco.com>
Thu, 19 Dec 2019 10:55:54 +0000 (11:55 +0100)
committerAndrew Yourtchenko <ayourtch@gmail.com>
Wed, 5 Feb 2020 15:45:30 +0000 (15:45 +0000)
Type: refactor
Change-Id: If3d9f16f3a06c10b354f1eef674e8db5f3c44de7
Signed-off-by: Ole Troan <ot@cisco.com>
19 files changed:
src/plugins/nat/CMakeLists.txt
src/plugins/nat/dslite/dslite.api [new file with mode: 0644]
src/plugins/nat/dslite/dslite.c [moved from src/plugins/nat/dslite.c with 83% similarity]
src/plugins/nat/dslite/dslite.h [moved from src/plugins/nat/dslite.h with 97% similarity]
src/plugins/nat/dslite/dslite_api.c [new file with mode: 0644]
src/plugins/nat/dslite/dslite_ce_decap.c [moved from src/plugins/nat/dslite_ce_decap.c with 99% similarity]
src/plugins/nat/dslite/dslite_ce_encap.c [moved from src/plugins/nat/dslite_ce_encap.c with 99% similarity]
src/plugins/nat/dslite/dslite_cli.c [moved from src/plugins/nat/dslite_cli.c with 93% similarity]
src/plugins/nat/dslite/dslite_dpo.c [moved from src/plugins/nat/dslite_dpo.c with 98% similarity]
src/plugins/nat/dslite/dslite_dpo.h [moved from src/plugins/nat/dslite_dpo.h with 100% similarity]
src/plugins/nat/dslite/dslite_in2out.c [moved from src/plugins/nat/dslite_in2out.c with 94% similarity]
src/plugins/nat/dslite/dslite_out2in.c [moved from src/plugins/nat/dslite_out2in.c with 99% similarity]
src/plugins/nat/nat.api
src/plugins/nat/nat.c
src/plugins/nat/nat.h
src/plugins/nat/nat_api.c
src/plugins/nat/nat_inlines.h
src/plugins/nat/test/test_dslite.py [new file with mode: 0644]
src/plugins/nat/test/test_nat.py

index edba893..a1a0178 100644 (file)
 # 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 (file)
index 0000000..b5f8c5b
--- /dev/null
@@ -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;
+};
similarity index 83%
rename from src/plugins/nat/dslite.c
rename to src/plugins/nat/dslite/dslite.c
index d9a1729..e03dd0c 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <nat/dslite.h>
-#include <nat/dslite_dpo.h>
+#include <vnet/plugin/plugin.h>
+#include <nat/dslite/dslite.h>
+#include <nat/dslite/dslite_dpo.h>
 #include <vnet/fib/fib_table.h>
+#include <vpp/app/version.h>
 
 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
  *
similarity index 97%
rename from src/plugins/nat/dslite.h
rename to src/plugins/nat/dslite/dslite.h
index 65498ee..d512cf4 100644 (file)
@@ -18,7 +18,9 @@
 #include <vppinfra/bihash_8_8.h>
 #include <vppinfra/bihash_16_8.h>
 #include <vppinfra/bihash_24_8.h>
+#include <nat/lib/alloc.h>
 #include <nat/nat.h>
+#include <nat/nat_inlines.h>
 
 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 (file)
index 0000000..420e821
--- /dev/null
@@ -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 <vnet/ip/ip_types_api.h>
+#include <nat/dslite/dslite.h>
+#include <nat/dslite/dslite.api_enum.h>
+#include <nat/dslite/dslite.api_types.h>
+#include <vnet/ip/ip.h>
+#include <vnet/fib/fib_table.h>
+#include <vlibmemory/api.h>
+
+#define REPLY_MSG_ID_BASE dm->msg_id_base
+#include <vlibapi/api_helper_macros.h>
+
+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 <vnet/format_fns.h>
+#include <nat/dslite/dslite.api.c>
+
+/* 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;
+}
similarity index 99%
rename from src/plugins/nat/dslite_ce_decap.c
rename to src/plugins/nat/dslite/dslite_ce_decap.c
index 77b80ea..3d6ca99 100644 (file)
@@ -12,7 +12,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <nat/dslite.h>
+#include <nat/dslite/dslite.h>
 #include <nat/nat_inlines.h>
 
 typedef enum
similarity index 99%
rename from src/plugins/nat/dslite_ce_encap.c
rename to src/plugins/nat/dslite/dslite_ce_encap.c
index 39ff797..8cec543 100644 (file)
@@ -12,7 +12,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <nat/dslite.h>
+#include <nat/dslite/dslite.h>
 #include <nat/nat_inlines.h>
 
 typedef enum
similarity index 93%
rename from src/plugins/nat/dslite_cli.c
rename to src/plugins/nat/dslite/dslite_cli.c
index 515929b..d5c0ca6 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-#include <nat/dslite.h>
+#include <nat/dslite/dslite.h>
 
 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;
similarity index 98%
rename from src/plugins/nat/dslite_dpo.c
rename to src/plugins/nat/dslite/dslite_dpo.c
index 97ebb18..009b553 100644 (file)
@@ -14,7 +14,7 @@
  */
 
 #include <vnet/ip/ip.h>
-#include <nat/dslite_dpo.h>
+#include <nat/dslite/dslite_dpo.h>
 
 dpo_type_t dslite_dpo_type;
 dpo_type_t dslite_ce_dpo_type;
similarity index 94%
rename from src/plugins/nat/dslite_in2out.c
rename to src/plugins/nat/dslite/dslite_in2out.c
index 4494a77..d1ac175 100644 (file)
@@ -12,7 +12,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <nat/dslite.h>
+#include <nat/dslite/dslite.h>
 #include <nat/nat_inlines.h>
 #include <nat/nat_syslog.h>
 
@@ -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
similarity index 99%
rename from src/plugins/nat/dslite_out2in.c
rename to src/plugins/nat/dslite/dslite_out2in.c
index 265d79f..ac64a58 100644 (file)
@@ -12,7 +12,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <nat/dslite.h>
+#include <nat/dslite/dslite.h>
 #include <nat/nat_inlines.h>
 
 typedef enum
index 356dd0c..58eee45 100644 (file)
@@ -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
  */
index 1485532..9f51658 100755 (executable)
@@ -25,7 +25,6 @@
 #include <nat/nat_det.h>
 #include <nat/nat64.h>
 #include <nat/nat66.h>
-#include <nat/dslite.h>
 #include <nat/nat_inlines.h>
 #include <nat/nat_affinity.h>
 #include <nat/nat_syslog.h>
@@ -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
index d3fa3ee..9cde968 100644 (file)
@@ -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
  *
index 6df1a85..d73a033 100644 (file)
@@ -22,7 +22,6 @@
 #include <nat/nat_det.h>
 #include <nat/nat64.h>
 #include <nat/nat66.h>
-#include <nat/dslite.h>
 #include <nat/nat_inlines.h>
 #include <nat/nat_ha.h>
 #include <vlibapi/api.h>
@@ -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)           \
index a58317a..f693032 100644 (file)
@@ -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 (file)
index 0000000..dfa7d7c
--- /dev/null
@@ -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"))
index f870655..d16204e 100644 (file)
@@ -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 """