nat: NAT66 plugin enable&disable calls update 44/31744/4
authorFilip Varga <fivarga@cisco.com>
Tue, 23 Mar 2021 11:57:58 +0000 (12:57 +0100)
committerOle Tr�an <otroan@employees.org>
Wed, 31 Mar 2021 11:46:05 +0000 (11:46 +0000)
Type: improvement

Adding support for enable&disable calls
(dynamic plugin configuration).
API (nat66_plugin_enable_disable) and
CLI (nat66 plugin enable/nat66 plugin disable) with support for
outside_vrf id configuration.

Change-Id: I5637ff1621d6662adc3b7c6f7f8176d84a4b492b
Signed-off-by: Filip Varga <fivarga@cisco.com>
src/plugins/gbp/test/test_gbp.py
src/plugins/nat/nat66/nat66.api
src/plugins/nat/nat66/nat66.c
src/plugins/nat/nat66/nat66.h
src/plugins/nat/nat66/nat66_api.c
src/plugins/nat/nat66/nat66_cli.c
src/plugins/nat/test/test_nat66.py

index 2f55c08..342e5de 100644 (file)
@@ -833,6 +833,7 @@ class TestGBP(VppTestCase):
                               "2001:10:2::1", "3001::4")]
 
         self.vapi.nat44_ed_plugin_enable_disable(enable=1)
+        self.vapi.nat66_plugin_enable_disable(enable=1)
 
         #
         # Config related to each of the EPGs
@@ -852,8 +853,8 @@ class TestGBP(VppTestCase):
                     sw_if_index=epg.bvi.sw_if_index,
                     flags=flags, is_add=1)
                 self.vapi.nat66_add_del_interface(
-                    is_add=1, flags=flags,
-                    sw_if_index=epg.bvi.sw_if_index)
+                    sw_if_index=epg.bvi.sw_if_index,
+                    flags=flags, is_add=1)
 
             if_ip4 = VppIpInterfaceAddress(self, epg.bvi,
                                            epg.bvi_ip4, 32,
@@ -889,8 +890,7 @@ class TestGBP(VppTestCase):
             self.vapi.nat44_interface_add_del_feature(
                 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
             self.vapi.nat66_add_del_interface(
-                is_add=1,
-                sw_if_index=recirc.recirc.sw_if_index)
+                sw_if_index=recirc.recirc.sw_if_index, is_add=1)
 
             recirc.add_vpp_config()
 
@@ -1282,7 +1282,6 @@ class TestGBP(VppTestCase):
                                     pkt_inter_epg_220_to_222 * NUM_PKTS,
                                     eps[3].itf,
                                     str(self.router_mac))
-
         #
         # remove both contracts, traffic stops in both directions
         #
@@ -1397,7 +1396,6 @@ class TestGBP(VppTestCase):
                                      pkt_inter_epg_220_to_global * NUM_PKTS,
                                      self.pg7,
                                      eps[0].fip6)
-
         #
         # From a global address to an EP: OUT2IN
         #
@@ -1477,26 +1475,7 @@ class TestGBP(VppTestCase):
         # cleanup
         #
         self.vapi.nat44_ed_plugin_enable_disable(enable=0)
-
-        for ep in eps:
-            # del static mappings for each EP from the 10/8 to 11/8 network
-            flags = self.nat_config_flags.NAT_IS_ADDR_ONLY
-            self.vapi.nat66_add_del_static_mapping(
-                local_ip_address=ep.ip6,
-                external_ip_address=ep.fip6,
-                vrf_id=0, is_add=0)
-
-        for epg in epgs:
-            # IP config on the BVI interfaces
-            if epg != epgs[0] and epg != epgs[3]:
-                flags = self.nat_config_flags.NAT_IS_INSIDE
-                self.vapi.nat66_add_del_interface(
-                    sw_if_index=epg.bvi.sw_if_index,
-                    flags=flags, is_add=0)
-
-        for recirc in recircs:
-            self.vapi.nat66_add_del_interface(
-                sw_if_index=recirc.recirc.sw_if_index, is_add=0)
+        self.vapi.nat66_plugin_enable_disable(enable=0)
 
     def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
                             tep=None, n_tries=100, s_time=1):
index bbadf07..29425c0 100644 (file)
@@ -18,6 +18,20 @@ import "vnet/ip/ip_types.api";
 import "vnet/interface_types.api";
 import "plugins/nat/lib/nat_types.api";
 
+
+/** \brief Enable/disable NAT66 plugin
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+    @param outside_vrf - outside vrf id
+    @param enable - true if enable, false if disable
+*/
+autoreply define nat66_plugin_enable_disable {
+  u32 client_index;
+  u32 context;
+  u32 outside_vrf;
+  bool enable;
+};
+
 /** \brief Enable/disable NAT66 feature on the interface
     @param client_index - opaque cookie to identify the sender
     @param context - sender context, to match reply w/ request
index a8de3f6..ff8cace 100644 (file)
  * @brief NAT66 implementation
  */
 
+#include <nat/nat66/nat66.h>
 #include <vpp/app/version.h>
 #include <vnet/plugin/plugin.h>
-#include <nat/nat66/nat66.h>
-#include <vnet/fib/fib_table.h>
 #include <vnet/ip/reass/ip6_sv_reass.h>
 
 nat66_main_t nat66_main;
-fib_source_t nat_fib_src_hi;
-
-/* *INDENT-OFF* */
 
 /* Hook up input features */
 VNET_FEATURE_INIT (nat66_in2out, static) = {
@@ -42,39 +38,109 @@ VNET_FEATURE_INIT (nat66_out2in, static) = {
   .runs_after = VNET_FEATURES ("ip6-sv-reassembly-feature"),
 };
 
-/* *INDENT-ON* */
-
 clib_error_t *nat66_plugin_api_hookup (vlib_main_t * vm);
+
+#define fail_if_enabled()                                                     \
+  do                                                                          \
+    {                                                                         \
+      nat66_main_t *nm = &nat66_main;                                         \
+      if (PREDICT_FALSE (nm->enabled))                                        \
+       {                                                                     \
+         nat66_elog_warn ("plugin enabled");                                 \
+         return 1;                                                           \
+       }                                                                     \
+    }                                                                         \
+  while (0)
+
+#define fail_if_disabled()                                                    \
+  do                                                                          \
+    {                                                                         \
+      nat66_main_t *nm = &nat66_main;                                         \
+      if (PREDICT_FALSE (!nm->enabled))                                       \
+       {                                                                     \
+         nat66_elog_warn ("plugin disabled");                                \
+         return 1;                                                           \
+       }                                                                     \
+    }                                                                         \
+  while (0)
+
 static clib_error_t *
 nat66_init (vlib_main_t * vm)
 {
   nat66_main_t *nm = &nat66_main;
-  vlib_node_t *node;
+
+  clib_memset (nm, 0, sizeof (*nm));
+
+  nm->session_counters.name = "session counters";
+  nm->in2out_packets.name = "in2out";
+  nm->in2out_packets.stat_segment_name = "/nat64/in2out";
+  nm->out2in_packets.name = "out2in";
+  nm->out2in_packets.stat_segment_name = "/nat64/out2in";
+
+  nm->nat_fib_src_hi = fib_source_allocate ("nat66-hi", FIB_SOURCE_PRIORITY_HI,
+                                           FIB_SOURCE_BH_SIMPLE);
+  return nat66_plugin_api_hookup (vm);
+}
+
+int
+nat66_plugin_enable (u32 outside_vrf)
+{
+  nat66_main_t *nm = &nat66_main;
+
   u32 static_mapping_buckets = 1024;
   uword static_mapping_memory_size = 64 << 20;
 
-  node = vlib_get_node_by_name (vm, (u8 *) "nat66-in2out");
-  nm->in2out_node_index = node->index;
-
-  node = vlib_get_node_by_name (vm, (u8 *) "nat66-out2in");
-  nm->out2in_node_index = node->index;
+  fail_if_enabled ();
 
   clib_bihash_init_24_8 (&nm->sm_l, "nat66-static-map-by-local",
                         static_mapping_buckets, static_mapping_memory_size);
   clib_bihash_init_24_8 (&nm->sm_e, "nat66-static-map-by-external",
                         static_mapping_buckets, static_mapping_memory_size);
 
-  nm->session_counters.name = "session counters";
+  nm->outside_vrf_id = outside_vrf;
+  nm->outside_fib_index = fib_table_find_or_create_and_lock (
+    FIB_PROTOCOL_IP6, outside_vrf, nm->nat_fib_src_hi);
+  nm->enabled = 1;
+  return 0;
+}
 
-  nat_fib_src_hi = fib_source_allocate ("nat66-hi",
-                                       FIB_SOURCE_PRIORITY_HI,
-                                       FIB_SOURCE_BH_SIMPLE);
+int
+nat66_plugin_disable ()
+{
+  nat66_main_t *nm = &nat66_main;
+  nat66_interface_t *i, *temp;
+  int error = 0;
 
-  nm->in2out_packets.name = "in2out";
-  nm->in2out_packets.stat_segment_name = "/nat64/in2out";
-  nm->out2in_packets.name = "out2in";
-  nm->out2in_packets.stat_segment_name = "/nat64/out2in";
-  return nat66_plugin_api_hookup (vm);
+  temp = pool_dup (nm->interfaces);
+  pool_foreach (i, temp)
+    {
+      if (nat66_interface_is_inside (i))
+       error = nat66_interface_add_del (i->sw_if_index, 1, 0);
+
+      if (nat66_interface_is_outside (i))
+       error = nat66_interface_add_del (i->sw_if_index, 0, 0);
+
+      if (error)
+       {
+         nat66_elog_warn ("error occurred while removing interface");
+       }
+    }
+  pool_free (temp);
+  pool_free (nm->interfaces);
+
+  pool_free (nm->sm);
+  clib_bihash_free_24_8 (&nm->sm_l);
+  clib_bihash_free_24_8 (&nm->sm_e);
+
+  nm->interfaces = 0;
+  nm->sm = 0;
+
+  vlib_clear_combined_counters (&nm->session_counters);
+  vlib_clear_simple_counters (&nm->in2out_packets);
+  vlib_clear_simple_counters (&nm->out2in_packets);
+
+  nm->enabled = 0;
+  return error;
 }
 
 static void
@@ -93,7 +159,8 @@ nat66_interface_add_del (u32 sw_if_index, u8 is_inside, u8 is_add)
   nat66_interface_t *interface = 0, *i;
   const char *feature_name;
 
-  /* *INDENT-OFF* */
+  fail_if_disabled ();
+
   pool_foreach (i, nm->interfaces)
    {
     if (i->sw_if_index == sw_if_index)
@@ -102,7 +169,6 @@ nat66_interface_add_del (u32 sw_if_index, u8 is_inside, u8 is_add)
         break;
       }
   }
-  /* *INDENT-ON* */
 
   if (is_add)
     {
@@ -138,13 +204,11 @@ nat66_interfaces_walk (nat66_interface_walk_fn_t fn, void *ctx)
   nat66_main_t *nm = &nat66_main;
   nat66_interface_t *i = 0;
 
-  /* *INDENT-OFF* */
   pool_foreach (i, nm->interfaces)
    {
     if (fn (i, ctx))
       break;
   }
-  /* *INDENT-ON* */
 }
 
 nat66_static_mapping_t *
@@ -182,6 +246,8 @@ nat66_static_mapping_add_del (ip6_address_t * l_addr, ip6_address_t * e_addr,
   clib_bihash_kv_24_8_t kv, value;
   u32 fib_index = fib_table_find (FIB_PROTOCOL_IP6, vrf_id);
 
+  fail_if_disabled ();
+
   sm_key.addr.as_u64[0] = l_addr->as_u64[0];
   sm_key.addr.as_u64[1] = l_addr->as_u64[1];
   sm_key.fib_index = fib_index;
@@ -199,7 +265,7 @@ nat66_static_mapping_add_del (ip6_address_t * l_addr, ip6_address_t * e_addr,
        return VNET_API_ERROR_VALUE_EXIST;
 
       fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id,
-                                                    nat_fib_src_hi);
+                                                    nm->nat_fib_src_hi);
       pool_get (nm->sm, sm);
       clib_memset (sm, 0, sizeof (*sm));
       sm->l_addr.as_u64[0] = l_addr->as_u64[0];
@@ -243,7 +309,7 @@ nat66_static_mapping_add_del (ip6_address_t * l_addr, ip6_address_t * e_addr,
       kv.key[2] = sm_key.as_u64[2];
       if (clib_bihash_add_del_24_8 (&nm->sm_e, &kv, 0))
        nat66_elog_warn ("nat66-static-map-by-external delete key failed");
-      fib_table_unlock (sm->fib_index, FIB_PROTOCOL_IP6, nat_fib_src_hi);
+      fib_table_unlock (sm->fib_index, FIB_PROTOCOL_IP6, nm->nat_fib_src_hi);
       pool_put (nm->sm, sm);
     }
 
@@ -256,29 +322,13 @@ nat66_static_mappings_walk (nat66_static_mapping_walk_fn_t fn, void *ctx)
   nat66_main_t *nm = &nat66_main;
   nat66_static_mapping_t *sm = 0;
 
-  /* *INDENT-OFF* */
   pool_foreach (sm, nm->sm)
    {
     if (fn (sm, ctx))
       break;
   }
-  /* *INDENT-ON* */
-}
-
-/*static*/ void
-nat66_config (void)
-{
-  nat66_main_t *nm = &nat66_main;
-  u32 outside_ip6_vrf_id = 0;
-
-  nm->outside_vrf_id = outside_ip6_vrf_id;
-  nm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
-                                                            outside_ip6_vrf_id,
-                                                            nat_fib_src_hi);
-
 }
 
-/* *INDENT-OFF* */
 VLIB_PLUGIN_REGISTER () =
 {
  .version = VPP_BUILD_VER,
@@ -287,8 +337,6 @@ VLIB_PLUGIN_REGISTER () =
 
 VLIB_INIT_FUNCTION (nat66_init);
 
-/* *INDENT-ON* */
-
 /*
  * fd.io coding-style-patch-verification: ON
  *
index 42dd7ca..17a6923 100644 (file)
@@ -20,6 +20,7 @@
 #define __included_nat66_h__
 
 #include <vnet/ip/ip.h>
+#include <vnet/fib/fib_table.h>
 #include <vppinfra/bihash_24_8.h>
 
 typedef struct
@@ -48,6 +49,7 @@ typedef struct
   u32 sw_if_index;
   u8 flags;
 } nat66_interface_t;
+
 #define NAT66_INTERFACE_FLAG_IS_INSIDE 1
 #define NAT66_INTERFACE_FLAG_IS_OUTSIDE 2
 #define nat66_interface_is_inside(i) i->flags & NAT66_INTERFACE_FLAG_IS_INSIDE
@@ -65,16 +67,16 @@ typedef struct
   clib_bihash_24_8_t sm_e;
   /** Session counters */
   vlib_combined_counter_main_t session_counters;
-  /** node index **/
-  u32 in2out_node_index;
-  u32 out2in_node_index;
 
   u32 outside_vrf_id;
   u32 outside_fib_index;
+  fib_source_t nat_fib_src_hi;
 
   u16 msg_id_base;
   u8 log_level;
 
+  u8 enabled;
+
   vlib_simple_counter_main_t in2out_packets;
   vlib_simple_counter_main_t out2in_packets;;
 } nat66_main_t;
@@ -114,6 +116,8 @@ nat66_static_mapping_t *nat66_static_mapping_get (ip6_address_t * addr,
 int nat66_static_mapping_add_del (ip6_address_t * l_addr,
                                  ip6_address_t * e_addr, u32 vrf_id,
                                  u8 is_add);
+int nat66_plugin_enable (u32 outside_vrf);
+int nat66_plugin_disable ();
 
 #endif /* __included_nat66_h__ */
 
index 2a2b3cc..470c1fe 100644 (file)
 #define REPLY_MSG_ID_BASE nm->msg_id_base
 #include <vlibapi/api_helper_macros.h>
 
-/*************/
-/*** NAT66 ***/
-/*************/
+static void
+vl_api_nat66_plugin_enable_disable_t_handler (
+  vl_api_nat66_plugin_enable_disable_t *mp)
+{
+  nat66_main_t *nm = &nat66_main;
+  vl_api_nat66_plugin_enable_disable_reply_t *rmp;
+  int rv = 0;
+
+  if (mp->enable)
+    {
+      rv = nat66_plugin_enable (ntohl (mp->outside_vrf));
+    }
+  else
+    rv = nat66_plugin_disable ();
+
+  REPLY_MACRO (VL_API_NAT66_PLUGIN_ENABLE_DISABLE_REPLY);
+}
 
 static void
 vl_api_nat66_add_del_interface_t_handler (vl_api_nat66_add_del_interface_t *
@@ -96,6 +110,10 @@ static void
 vl_api_nat66_interface_dump_t_handler (vl_api_nat66_interface_dump_t * mp)
 {
   vl_api_registration_t *rp;
+  nat66_main_t *nm = &nat66_main;
+
+  if (PREDICT_FALSE (!nm->enabled))
+    return;
 
   rp = vl_api_client_index_to_registration (mp->client_index);
   if (rp == 0)
@@ -145,6 +163,10 @@ vl_api_nat66_static_mapping_dump_t_handler (vl_api_nat66_static_mapping_dump_t
                                            * mp)
 {
   vl_api_registration_t *rp;
+  nat66_main_t *nm = &nat66_main;
+
+  if (PREDICT_FALSE (!nm->enabled))
+    return;
 
   rp = vl_api_client_index_to_registration (mp->client_index);
   if (rp == 0)
@@ -167,8 +189,6 @@ clib_error_t *
 nat66_plugin_api_hookup (vlib_main_t * vm)
 {
   nat66_main_t *nm = &nat66_main;
-
   nm->msg_id_base = setup_message_id_table ();
-
   return 0;
 }
index da96387..4ba46cb 100644 (file)
 #include <nat/nat66/nat66.h>
 #include <vnet/fib/fib_table.h>
 
+static clib_error_t *
+nat66_enable_command_fn (vlib_main_t *vm, unformat_input_t *input,
+                        vlib_cli_command_t *cmd)
+{
+  nat66_main_t *nm = &nat66_main;
+  unformat_input_t _line_input, *line_input = &_line_input;
+  clib_error_t *error = 0;
+  u32 outside_vrf = 0;
+
+  if (nm->enabled)
+    return clib_error_return (0, "nat66 already enabled");
+
+  /* Get a line of input. */
+  if (!unformat_user (input, unformat_line_input, line_input))
+    {
+      if (nat66_plugin_enable (outside_vrf) != 0)
+       return clib_error_return (0, "nat66 enable failed");
+      return 0;
+    }
+
+  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (line_input, "outside-vrf %u", &outside_vrf))
+       ;
+      else
+       {
+         error = clib_error_return (0, "unknown input '%U'",
+                                    format_unformat_error, line_input);
+         goto done;
+       }
+    }
+
+  if (nat66_plugin_enable (outside_vrf) != 0)
+    error = clib_error_return (0, "nat66 enable failed");
+done:
+  unformat_free (line_input);
+  return error;
+}
+
+static clib_error_t *
+nat66_disable_command_fn (vlib_main_t *vm, unformat_input_t *input,
+                         vlib_cli_command_t *cmd)
+{
+  nat66_main_t *nm = &nat66_main;
+  clib_error_t *error = 0;
+
+  if (!nm->enabled)
+    return clib_error_return (0, "nat66 already disabled");
+
+  if (nat66_plugin_disable () != 0)
+    error = clib_error_return (0, "nat66 disable failed");
+
+  return error;
+}
+
 static clib_error_t *
 nat66_interface_feature_command_fn (vlib_main_t * vm,
                                    unformat_input_t * input,
@@ -27,6 +82,7 @@ nat66_interface_feature_command_fn (vlib_main_t * vm,
 {
   unformat_input_t _line_input, *line_input = &_line_input;
   vnet_main_t *vnm = vnet_get_main ();
+  nat66_main_t *nm = &nat66_main;
   clib_error_t *error = 0;
   u32 sw_if_index;
   u32 *inside_sw_if_indices = 0;
@@ -34,6 +90,9 @@ nat66_interface_feature_command_fn (vlib_main_t * vm,
   u8 is_add = 1;
   int i, rv;
 
+  if (!nm->enabled)
+    return clib_error_return (0, "nat66 disabled");
+
   /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -139,7 +198,6 @@ nat66_cli_interface_walk (nat66_interface_t * i, void *ctx)
 {
   vlib_main_t *vm = ctx;
   vnet_main_t *vnm = vnet_get_main ();
-
   vlib_cli_output (vm, " %U %s", format_vnet_sw_interface_name, vnm,
                   vnet_get_sw_interface (vnm, i->sw_if_index),
                   nat66_interface_is_inside (i) ? "in" : "out");
@@ -150,9 +208,11 @@ static clib_error_t *
 nat66_show_interfaces_command_fn (vlib_main_t * vm, unformat_input_t * input,
                                  vlib_cli_command_t * cmd)
 {
+  nat66_main_t *nm = &nat66_main;
+  if (!nm->enabled)
+    return clib_error_return (0, "nat66 disabled");
   vlib_cli_output (vm, "NAT66 interfaces:");
   nat66_interfaces_walk (nat66_cli_interface_walk, vm);
-
   return 0;
 }
 
@@ -161,6 +221,7 @@ nat66_add_del_static_mapping_command_fn (vlib_main_t * vm,
                                         unformat_input_t * input,
                                         vlib_cli_command_t * cmd)
 {
+  nat66_main_t *nm = &nat66_main;
   unformat_input_t _line_input, *line_input = &_line_input;
   clib_error_t *error = 0;
   u8 is_add = 1;
@@ -168,6 +229,9 @@ nat66_add_del_static_mapping_command_fn (vlib_main_t * vm,
   u32 vrf_id = 0;
   int rv;
 
+  if (!nm->enabled)
+    return clib_error_return (0, "nat66 disabled");
+
   /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -238,12 +302,44 @@ nat66_show_static_mappings_command_fn (vlib_main_t * vm,
                                       unformat_input_t * input,
                                       vlib_cli_command_t * cmd)
 {
+  nat66_main_t *nm = &nat66_main;
+  if (!nm->enabled)
+    return clib_error_return (0, "nat66 disabled");
   vlib_cli_output (vm, "NAT66 static mappings:");
   nat66_static_mappings_walk (nat66_cli_static_mapping_walk, vm);
   return 0;
 }
 
-/* *INDENT-OFF* */
+/*?
+ * @cliexpar
+ * @cliexstart{nat66 enable}
+ * Enable NAT66 plugin
+ * To enable NAT66 plugin
+ *  vpp# nat66 enable
+ * To enable NAT66 plugin with outside-vrf id 10
+ *  vpp# nat66 enable outside-vrf 10
+ * @cliexend
+?*/
+VLIB_CLI_COMMAND (nat66_enable_command, static) = {
+  .path = "nat66 enable",
+  .short_help = "nat66 enable [outside-vrf <vrf-id>]",
+  .function = nat66_enable_command_fn,
+};
+
+/*?
+ * @cliexpar
+ * @cliexstart{nat66 disable}
+ * Disable NAT66 plugin
+ * To disable NAT66 plugin
+ *  vpp# nat66 disable
+ * @cliexend
+?*/
+VLIB_CLI_COMMAND (nat66_disable_command, static) = {
+  .path = "nat66 disable",
+  .short_help = "nat66 disable",
+  .function = nat66_disable_command_fn,
+};
+
 /*?
  * @cliexpar
  * @cliexstart{set interface nat66}
index bd1b50b..acda72b 100644 (file)
@@ -32,14 +32,7 @@ from vpp_neighbor import VppNeighbor
 from vpp_papi import VppEnum
 
 
-class MethodHolder(VppTestCase):
-    """ NAT create capture and verify method holder """
-    @property
-    def config_flags(self):
-        return VppEnum.vl_api_nat_config_flags_t
-
-
-class TestNAT66(MethodHolder):
+class TestNAT66(VppTestCase):
     """ NAT66 Test Cases """
 
     @classmethod
@@ -47,7 +40,6 @@ class TestNAT66(MethodHolder):
         super(TestNAT66, cls).setUpClass()
 
         cls.nat_addr = 'fd01:ff::2'
-
         cls.create_pg_interfaces(range(2))
         cls.interfaces = list(cls.pg_interfaces)
 
@@ -56,9 +48,24 @@ class TestNAT66(MethodHolder):
             i.config_ip6()
             i.configure_ipv6_neighbors()
 
-    @classmethod
-    def tearDownClass(cls):
-        super(TestNAT66, cls).tearDownClass()
+    @property
+    def config_flags(self):
+        return VppEnum.vl_api_nat_config_flags_t
+
+    def plugin_enable(self):
+        self.vapi.nat66_plugin_enable_disable(enable=1)
+
+    def plugin_disable(self):
+        self.vapi.nat66_plugin_enable_disable(enable=0)
+
+    def setUp(self):
+        super(TestNAT66, self).setUp()
+        self.plugin_enable()
+
+    def tearDown(self):
+        super(TestNAT66, self).tearDown()
+        if not self.vpp_dead:
+            self.plugin_disable()
 
     def test_static(self):
         """ 1:1 NAT66 test """
@@ -167,30 +174,6 @@ class TestNAT66(MethodHolder):
             self.logger.error(ppp("Unexpected or invalid packet:", packet))
             raise
 
-    def clear_nat66(self):
-        """
-        Clear NAT66 configuration.
-        """
-        interfaces = self.vapi.nat66_interface_dump()
-        for intf in interfaces:
-            self.vapi.nat66_add_del_interface(is_add=0, flags=intf.flags,
-                                              sw_if_index=intf.sw_if_index)
-
-        static_mappings = self.vapi.nat66_static_mapping_dump()
-        for sm in static_mappings:
-            self.vapi.nat66_add_del_static_mapping(
-                local_ip_address=sm.local_ip_address,
-                external_ip_address=sm.external_ip_address, vrf_id=sm.vrf_id,
-                is_add=0)
-
-    def tearDown(self):
-        super(TestNAT66, self).tearDown()
-        self.clear_nat66()
-
-    def show_commands_at_teardown(self):
-        self.logger.info(self.vapi.cli("show nat66 interfaces"))
-        self.logger.info(self.vapi.cli("show nat66 static mappings"))
-
 
 if __name__ == '__main__':
     unittest.main(testRunner=VppTestRunner)