From: Vladislav Grishenko Date: Sun, 4 Dec 2022 10:02:03 +0000 (+0500) Subject: nat: disable nat44-ed/ei features on interface deletion X-Git-Tag: v23.06-rc0~66 X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;h=3abb32c6fe038d757493381b9ea19c19682ca026;p=vpp.git nat: disable nat44-ed/ei features on interface deletion After deleting a sw interface with nat44 features, the next created sw interface will get the same sw_index reused and therefore will erroneously have the same nat features enabled. Type: fix Change-Id: I1d84f842ab7ab2a757668ae1a111efe67e1e924d Signed-off-by: Vladislav Grishenko --- diff --git a/src/plugins/nat/nat44-ed/nat44_ed.c b/src/plugins/nat/nat44-ed/nat44_ed.c index 348fff2619d..82b9de1c3f0 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed.c +++ b/src/plugins/nat/nat44-ed/nat44_ed.c @@ -2587,6 +2587,55 @@ nat44_ed_del_output_interfaces () return error; } +static clib_error_t * +nat44_ed_sw_interface_add_del (vnet_main_t *vnm, u32 sw_if_index, u32 is_add) +{ + snat_main_t *sm = &snat_main; + snat_interface_t *i; + int error = 0; + + if (is_add) + return 0; + + if (!sm->enabled) + return 0; + + i = nat44_ed_get_interface (sm->interfaces, sw_if_index); + if (i) + { + bool is_inside = nat44_ed_is_interface_inside (i); + bool is_outside = nat44_ed_is_interface_outside (i); + + if (is_inside) + { + error |= nat44_ed_del_interface (sw_if_index, 1); + } + if (is_outside) + { + error |= nat44_ed_del_interface (sw_if_index, 0); + } + + if (error) + { + nat_log_err ("error occurred while removing interface"); + } + } + + i = nat44_ed_get_interface (sm->output_feature_interfaces, sw_if_index); + if (i) + { + error = nat44_ed_del_output_interface (sw_if_index); + if (error) + { + nat_log_err ("error occurred while removing output interface"); + } + } + + return 0; +} + +VNET_SW_INTERFACE_ADD_DEL_FUNCTION (nat44_ed_sw_interface_add_del); + int nat44_ed_del_static_mappings () { diff --git a/src/plugins/nat/nat44-ei/nat44_ei.c b/src/plugins/nat/nat44-ei/nat44_ei.c index 171ca7dcb4c..e16625a2946 100644 --- a/src/plugins/nat/nat44-ei/nat44_ei.c +++ b/src/plugins/nat/nat44-ei/nat44_ei.c @@ -1183,6 +1183,55 @@ nat44_ei_del_output_interfaces () return error; } +static clib_error_t * +nat44_ei_sw_interface_add_del (vnet_main_t *vnm, u32 sw_if_index, u32 is_add) +{ + nat44_ei_main_t *nm = &nat44_ei_main; + nat44_ei_interface_t *i; + int error = 0; + + if (is_add) + return 0; + + if (!nm->enabled) + return 0; + + i = nat44_ei_get_interface (nm->interfaces, sw_if_index); + if (i) + { + bool is_inside = nat44_ei_interface_is_inside (i); + bool is_outside = nat44_ei_interface_is_outside (i); + + if (is_inside) + { + error |= nat44_ei_del_interface (sw_if_index, 1); + } + if (is_outside) + { + error |= nat44_ei_del_interface (sw_if_index, 0); + } + + if (error) + { + nat44_ei_log_err ("error occurred while removing interface"); + } + } + + i = nat44_ei_get_interface (nm->output_feature_interfaces, sw_if_index); + if (i) + { + error = nat44_ei_del_output_interface (sw_if_index); + if (error) + { + nat44_ei_log_err ("error occurred while removing output interface"); + } + } + + return 0; +} + +VNET_SW_INTERFACE_ADD_DEL_FUNCTION (nat44_ei_sw_interface_add_del); + int nat44_ei_del_static_mappings () { diff --git a/test/test_nat44_ed.py b/test/test_nat44_ed.py index 6b0eedcec20..8a8c96870f4 100644 --- a/test/test_nat44_ed.py +++ b/test/test_nat44_ed.py @@ -6,7 +6,7 @@ from random import randint, choice import scapy.compat from framework import tag_fixme_ubuntu2204, is_distro_ubuntu2204 -from framework import VppTestCase, VppTestRunner +from framework import VppTestCase, VppTestRunner, VppLoInterface from scapy.data import IP_PROTOS from scapy.layers.inet import IP, TCP, UDP, ICMP, GRE from scapy.layers.inet import IPerror, TCPerror @@ -2552,6 +2552,51 @@ class TestNAT44ED(VppTestCase): in_if.unconfig() out_if.unconfig() + def test_delete_interface(self): + """NAT44ED delete nat interface""" + + self.nat_add_address(self.nat_addr) + + interfaces = self.create_loopback_interfaces(4) + self.nat_add_outside_interface(interfaces[0]) + self.nat_add_inside_interface(interfaces[1]) + self.nat_add_outside_interface(interfaces[2]) + self.nat_add_inside_interface(interfaces[2]) + self.vapi.nat44_ed_add_del_output_interface( + sw_if_index=interfaces[3].sw_if_index, is_add=1 + ) + + nat_sw_if_indices = [ + i.sw_if_index + for i in self.vapi.nat44_interface_dump() + + list(self.vapi.vpp.details_iter(self.vapi.nat44_ed_output_interface_get)) + ] + self.assertEqual(len(nat_sw_if_indices), len(interfaces)) + + loopbacks = [] + for i in interfaces: + # delete nat-enabled interface + self.assertIn(i.sw_if_index, nat_sw_if_indices) + i.remove_vpp_config() + + # create interface with the same index + lo = VppLoInterface(self) + loopbacks.append(lo) + self.assertEqual(lo.sw_if_index, i.sw_if_index) + + # check interface is not nat-enabled + nat_sw_if_indices = [ + i.sw_if_index + for i in self.vapi.nat44_interface_dump() + + list( + self.vapi.vpp.details_iter(self.vapi.nat44_ed_output_interface_get) + ) + ] + self.assertNotIn(lo.sw_if_index, nat_sw_if_indices) + + for i in loopbacks: + i.remove_vpp_config() + @tag_fixme_ubuntu2204 class TestNAT44EDMW(TestNAT44ED): diff --git a/test/test_nat44_ei.py b/test/test_nat44_ei.py index 259c445ea5b..955dbb52547 100644 --- a/test/test_nat44_ei.py +++ b/test/test_nat44_ei.py @@ -9,7 +9,7 @@ from io import BytesIO import scapy.compat from framework import tag_fixme_debian11, is_distro_debian11 -from framework import VppTestCase, VppTestRunner +from framework import VppTestCase, VppTestRunner, VppLoInterface from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder from scapy.all import ( bind_layers, @@ -4061,6 +4061,59 @@ class TestNAT44EI(MethodHolder): # a nonzero default should be reported for user_sessions self.assertNotEqual(nat44_ei_config.user_sessions, 0) + def test_delete_interface(self): + """NAT44EI delete nat interface""" + + self.nat44_add_address(self.nat_addr) + + interfaces = self.create_loopback_interfaces(4) + + self.vapi.nat44_ei_interface_add_del_feature( + sw_if_index=interfaces[0].sw_if_index, is_add=1 + ) + flags = self.config_flags.NAT44_EI_IF_INSIDE + self.vapi.nat44_ei_interface_add_del_feature( + sw_if_index=interfaces[1].sw_if_index, flags=flags, is_add=1 + ) + flags |= self.config_flags.NAT44_EI_IF_OUTSIDE + self.vapi.nat44_ei_interface_add_del_feature( + sw_if_index=interfaces[2].sw_if_index, flags=flags, is_add=1 + ) + self.vapi.nat44_ei_add_del_output_interface( + sw_if_index=interfaces[3].sw_if_index, is_add=1 + ) + + nat_sw_if_indices = [ + i.sw_if_index + for i in self.vapi.nat44_ei_interface_dump() + + list(self.vapi.vpp.details_iter(self.vapi.nat44_ei_output_interface_get)) + ] + self.assertEqual(len(nat_sw_if_indices), len(interfaces)) + + loopbacks = [] + for i in interfaces: + # delete nat-enabled interface + self.assertIn(i.sw_if_index, nat_sw_if_indices) + i.remove_vpp_config() + + # create interface with the same index + lo = VppLoInterface(self) + loopbacks.append(lo) + self.assertEqual(lo.sw_if_index, i.sw_if_index) + + # check interface is not nat-enabled + nat_sw_if_indices = [ + i.sw_if_index + for i in self.vapi.nat44_ei_interface_dump() + + list( + self.vapi.vpp.details_iter(self.vapi.nat44_ei_output_interface_get) + ) + ] + self.assertNotIn(lo.sw_if_index, nat_sw_if_indices) + + for i in loopbacks: + i.remove_vpp_config() + class TestNAT44Out2InDPO(MethodHolder): """NAT44EI Test Cases using out2in DPO"""