From 5f22499e8836066a268dcb3f4d16cfcd0244b2a2 Mon Sep 17 00:00:00 2001 From: Matus Fabian Date: Thu, 25 Jan 2018 21:59:16 -0800 Subject: [PATCH] NAT44: add opaque string tag to static mapping APIs (VPP-1147) Change-Id: I620e2081285ca8ac5c2da8efc12fe6f540ea4fd1 Signed-off-by: Matus Fabian --- src/plugins/nat/nat.api | 12 +++++++++++- src/plugins/nat/nat.c | 20 ++++++++++++++------ src/plugins/nat/nat.h | 6 ++++-- src/plugins/nat/nat44_cli.c | 6 +++--- src/plugins/nat/nat_api.c | 34 ++++++++++++++++++++++++++++++---- test/test_nat.py | 22 +++++++++++++++++++--- test/vpp_papi_provider.py | 11 ++++++++++- 7 files changed, 91 insertions(+), 20 deletions(-) diff --git a/src/plugins/nat/nat.api b/src/plugins/nat/nat.api index 02c1627b9ce..aff8f1d3818 100644 --- a/src/plugins/nat/nat.api +++ b/src/plugins/nat/nat.api @@ -13,7 +13,7 @@ * limitations under the License. */ -option version = "2.3.0"; +option version = "2.4.0"; /** * @file nat.api @@ -353,6 +353,7 @@ define nat44_interface_output_feature_details { @param twice_nat - if 1 translate external host address and port, only for 1:1 NAPT (addr_only must be 0) @param out2in_only - if 1 rule match only out2in direction + @param tag - opaque string tag */ autoreply define nat44_add_del_static_mapping { u32 client_index; @@ -368,6 +369,7 @@ autoreply define nat44_add_del_static_mapping { u32 vrf_id; u8 twice_nat; u8 out2in_only; + u8 tag[64]; }; /** \brief Dump NAT44 static mappings @@ -391,6 +393,7 @@ define nat44_static_mapping_dump { @param vfr_id - VRF ID @param twice_nat - if 1 translate external host address and port @param out2in_only - if 1 rule match only out2in direction + @param tag - opaque string tag */ define nat44_static_mapping_details { u32 context; @@ -404,6 +407,7 @@ define nat44_static_mapping_details { u32 vrf_id; u8 twice_nat; u8 out2in_only; + u8 tag[64]; }; /** \brief Add/delete NAT44 identity mapping @@ -417,6 +421,7 @@ define nat44_static_mapping_details { @param sw_if_index - interface (if set ip_address is ignored, ~0 means not used) @param vfr_id - VRF ID (if ~0 use default VRF) + @param tag - opaque string tag */ autoreply define nat44_add_del_identity_mapping { u32 client_index; @@ -428,6 +433,7 @@ autoreply define nat44_add_del_identity_mapping { u16 port; u32 sw_if_index; u32 vrf_id; + u8 tag[64]; }; /** \brief Dump NAT44 identity mappings @@ -447,6 +453,7 @@ define nat44_identity_mapping_dump { @param port - port number @param sw_if_index - interface @param vfr_id - VRF ID + @param tag - opaque string tag */ define nat44_identity_mapping_details { u32 context; @@ -456,6 +463,7 @@ define nat44_identity_mapping_details { u16 port; u32 sw_if_index; u32 vrf_id; + u8 tag[64]; }; /** \brief Add/delete NAT44 pool address from specific interfce @@ -572,6 +580,7 @@ autoreply manual_endian define nat44_add_del_lb_static_mapping { u32 vrf_id; u8 twice_nat; u8 out2in_only; + u8 tag[64]; u8 local_num; vl_api_nat44_lb_addr_port_t locals[local_num]; }; @@ -589,6 +598,7 @@ manual_endian define nat44_lb_static_mapping_details { u32 vrf_id; u8 twice_nat; u8 out2in_only; + u8 tag[64]; u8 local_num; vl_api_nat44_lb_addr_port_t locals[local_num]; }; diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index 5c324f2388a..95004da26d8 100644 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -623,7 +623,8 @@ snat_add_static_mapping_when_resolved (snat_main_t * sm, u32 vrf_id, snat_protocol_t proto, int addr_only, - int is_add) + int is_add, + u8 * tag) { snat_static_map_resolve_t *rp; @@ -636,6 +637,7 @@ snat_add_static_mapping_when_resolved (snat_main_t * sm, rp->proto = proto; rp->addr_only = addr_only; rp->is_add = is_add; + rp->tag = vec_dup (tag); } /** @@ -653,13 +655,14 @@ snat_add_static_mapping_when_resolved (snat_main_t * sm, * @param is_add If 0 delete static mapping, otherwise add. * @param twice_nat If 1 translate external host address and port. * @param out2in_only If 1 rule match only out2in direction + * @param tag - opaque string tag * * @returns */ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, u32 vrf_id, int addr_only, u32 sw_if_index, snat_protocol_t proto, int is_add, - u8 twice_nat, u8 out2in_only) + u8 twice_nat, u8 out2in_only, u8 * tag) { snat_main_t * sm = &snat_main; snat_static_mapping_t *m; @@ -686,7 +689,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, { snat_add_static_mapping_when_resolved (sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto, - addr_only, is_add); + addr_only, is_add, tag); return 0; } else @@ -770,6 +773,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, pool_get (sm->static_mappings, m); memset (m, 0, sizeof (*m)); + m->tag = vec_dup (tag); m->local_addr = l_addr; m->external_addr = e_addr; m->addr_only = addr_only; @@ -955,6 +959,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, } } + vec_free (m->tag); /* Delete static mapping from pool */ pool_put (sm->static_mappings, m); } @@ -986,7 +991,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, snat_protocol_t proto, u32 vrf_id, nat44_lb_addr_port_t *locals, u8 is_add, - u8 twice_nat, u8 out2in_only) + u8 twice_nat, u8 out2in_only, u8 *tag) { snat_main_t * sm = &snat_main; snat_static_mapping_t *m; @@ -1064,6 +1069,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, pool_get (sm->static_mappings, m); memset (m, 0, sizeof (*m)); + m->tag = vec_dup (tag); m->external_addr = e_addr; m->addr_only = 0; m->vrf_id = vrf_id; @@ -1243,6 +1249,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, } } vec_free(m->locals); + vec_free(m->tag); pool_put (sm->static_mappings, m); } @@ -1287,7 +1294,7 @@ snat_del_address (snat_main_t *sm, ip4_address_t addr, u8 delete_sm, m->local_port, m->external_port, m->vrf_id, m->addr_only, ~0, m->proto, 0, m->twice_nat, - m->out2in_only); + m->out2in_only, m->tag); })); } else @@ -2661,10 +2668,11 @@ match: ~0 /* sw_if_index */, rp->proto, rp->is_add, - 0, 0); + 0, 0, rp->tag); if (rv) clib_warning ("snat_add_static_mapping returned %d", rv); + vec_free (rp->tag); vec_add1 (indices_to_delete, j); } } diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h index bf975a14749..58bf8b340ce 100644 --- a/src/plugins/nat/nat.h +++ b/src/plugins/nat/nat.h @@ -222,6 +222,7 @@ typedef struct { u32 fib_index; snat_protocol_t proto; u32 worker_index; + u8 *tag; nat44_lb_addr_port_t *locals; } snat_static_mapping_t; @@ -240,6 +241,7 @@ typedef struct { int addr_only; int twice_nat; int is_add; + u8 *tag; } snat_static_map_resolve_t; typedef struct { @@ -548,7 +550,7 @@ void nat44_add_del_address_dpo (ip4_address_t addr, u8 is_add); int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, u32 vrf_id, int addr_only, u32 sw_if_index, snat_protocol_t proto, int is_add, - u8 twice_nat, u8 out2in_only); + u8 twice_nat, u8 out2in_only, u8 *tag); clib_error_t * snat_api_init(vlib_main_t * vm, snat_main_t * sm); int snat_set_workers (uword * bitmap); int snat_interface_add_del(u32 sw_if_index, u8 is_inside, int is_del); @@ -561,7 +563,7 @@ u8 * format_snat_protocol(u8 * s, va_list * args); int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, snat_protocol_t proto, u32 vrf_id, nat44_lb_addr_port_t *locals, u8 is_add, - u8 twice_nat, u8 out2in_only); + u8 twice_nat, u8 out2in_only, u8 *tag); int nat44_del_session (snat_main_t *sm, ip4_address_t *addr, u16 port, snat_protocol_t proto, u32 vrf_id, int is_in); void nat_free_session_data (snat_main_t * sm, snat_session_t * s, diff --git a/src/plugins/nat/nat44_cli.c b/src/plugins/nat/nat44_cli.c index 0aac1c0b6ce..5114615eb57 100644 --- a/src/plugins/nat/nat44_cli.c +++ b/src/plugins/nat/nat44_cli.c @@ -543,7 +543,7 @@ add_static_mapping_command_fn (vlib_main_t * vm, rv = snat_add_static_mapping (l_addr, e_addr, (u16) l_port, (u16) e_port, vrf_id, addr_only, sw_if_index, proto, is_add, - twice_nat, out2in_only); + twice_nat, out2in_only, 0); switch (rv) { @@ -618,7 +618,7 @@ add_identity_mapping_command_fn (vlib_main_t * vm, rv = snat_add_static_mapping (addr, addr, (u16) port, (u16) port, vrf_id, addr_only, sw_if_index, proto, is_add, - 0, 0); + 0, 0, 0); switch (rv) { @@ -715,7 +715,7 @@ add_lb_static_mapping_command_fn (vlib_main_t * vm, rv = nat44_add_del_lb_static_mapping (e_addr, (u16) e_port, proto, vrf_id, locals, is_add, twice_nat, - out2in_only); + out2in_only, 0); switch (rv) { diff --git a/src/plugins/nat/nat_api.c b/src/plugins/nat/nat_api.c index f23efa8d89f..3cb7399558f 100644 --- a/src/plugins/nat/nat_api.c +++ b/src/plugins/nat/nat_api.c @@ -696,6 +696,7 @@ static void u32 vrf_id, external_sw_if_index; int rv = 0; snat_protocol_t proto; + u8 *tag = 0; memcpy (&local_addr.as_u8, mp->local_ip_address, 4); memcpy (&external_addr.as_u8, mp->external_ip_address, 4); @@ -707,11 +708,16 @@ static void vrf_id = clib_net_to_host_u32 (mp->vrf_id); external_sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index); proto = ip_proto_to_snat_proto (mp->protocol); + mp->tag[sizeof (mp->tag) - 1] = 0; + tag = format (0, "%s", mp->tag); + vec_terminate_c_string (tag); rv = snat_add_static_mapping (local_addr, external_addr, local_port, external_port, vrf_id, mp->addr_only, external_sw_if_index, proto, mp->is_add, - mp->twice_nat, mp->out2in_only); + mp->twice_nat, mp->out2in_only, tag); + + vec_free (tag); REPLY_MACRO (VL_API_NAT44_ADD_DEL_STATIC_MAPPING_REPLY); } @@ -766,6 +772,8 @@ send_nat44_static_mapping_details (snat_static_mapping_t * m, rmp->context = context; rmp->twice_nat = m->twice_nat; rmp->out2in_only = m->out2in_only; + if (m->tag) + strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag)); vl_api_send_msg (reg, (u8 *) rmp); } @@ -791,6 +799,8 @@ send_nat44_static_map_resolve_details (snat_static_map_resolve_t * m, rmp->protocol = snat_proto_to_ip_proto (m->proto); rmp->context = context; rmp->twice_nat = m->twice_nat; + if (m->tag) + strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag)); vl_api_send_msg (reg, (u8 *) rmp); } @@ -847,6 +857,7 @@ static void u32 vrf_id, sw_if_index; int rv = 0; snat_protocol_t proto = ~0; + u8 *tag = 0; if (mp->addr_only == 0) { @@ -859,11 +870,15 @@ static void addr.as_u32 = 0; else memcpy (&addr.as_u8, mp->ip_address, 4); - + mp->tag[sizeof (mp->tag) - 1] = 0; + tag = format (0, "%s", mp->tag); + vec_terminate_c_string (tag); rv = snat_add_static_mapping (addr, addr, port, port, vrf_id, mp->addr_only, - sw_if_index, proto, mp->is_add, 0, 0); + sw_if_index, proto, mp->is_add, 0, 0, tag); + + vec_free (tag); REPLY_MACRO (VL_API_NAT44_ADD_DEL_IDENTITY_MAPPING_REPLY); } @@ -908,6 +923,8 @@ send_nat44_identity_mapping_details (snat_static_mapping_t * m, rmp->vrf_id = htonl (m->vrf_id); rmp->protocol = snat_proto_to_ip_proto (m->proto); rmp->context = context; + if (m->tag) + strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag)); vl_api_send_msg (reg, (u8 *) rmp); } @@ -930,6 +947,8 @@ send_nat44_identity_map_resolve_details (snat_static_map_resolve_t * m, rmp->vrf_id = htonl (m->vrf_id); rmp->protocol = snat_proto_to_ip_proto (m->proto); rmp->context = context; + if (m->tag) + strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag)); vl_api_send_msg (reg, (u8 *) rmp); } @@ -1238,19 +1257,24 @@ static void nat44_lb_addr_port_t *locals = 0; ip4_address_t e_addr; snat_protocol_t proto; + u8 *tag = 0; locals = unformat_nat44_lb_addr_port (mp->locals, mp->local_num); clib_memcpy (&e_addr, mp->external_addr, 4); proto = ip_proto_to_snat_proto (mp->protocol); + mp->tag[sizeof (mp->tag) - 1] = 0; + tag = format (0, "%s", mp->tag); + vec_terminate_c_string (tag); rv = nat44_add_del_lb_static_mapping (e_addr, clib_net_to_host_u16 (mp->external_port), proto, clib_net_to_host_u32 (mp->vrf_id), locals, mp->is_add, mp->twice_nat, - mp->out2in_only); + mp->out2in_only, tag); vec_free (locals); + vec_free (tag); REPLY_MACRO (VL_API_NAT44_ADD_DEL_LB_STATIC_MAPPING_REPLY); } @@ -1291,6 +1315,8 @@ send_nat44_lb_static_mapping_details (snat_static_mapping_t * m, rmp->context = context; rmp->twice_nat = m->twice_nat; rmp->out2in_only = m->out2in_only; + if (m->tag) + strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag)); locals = (vl_api_nat44_lb_addr_port_t *) rmp->locals; vec_foreach (ap, m->locals) diff --git a/test/test_nat.py b/test/test_nat.py index 46a6d42c0c5..f0614da2f3c 100644 --- a/test/test_nat.py +++ b/test/test_nat.py @@ -1030,6 +1030,7 @@ class TestNAT44(MethodHolder): protocol=sm.protocol, twice_nat=sm.twice_nat, out2in_only=sm.out2in_only, + tag=sm.tag, is_add=0) lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump() @@ -1041,6 +1042,7 @@ class TestNAT44(MethodHolder): vrf_id=lb_sm.vrf_id, twice_nat=lb_sm.twice_nat, out2in_only=lb_sm.out2in_only, + tag=lb_sm.tag, is_add=0, local_num=0, locals=[]) @@ -1069,7 +1071,7 @@ class TestNAT44(MethodHolder): def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0', local_port=0, external_port=0, vrf_id=0, is_add=1, external_sw_if_index=0xFFFFFFFF, - proto=0, twice_nat=0, out2in_only=0): + proto=0, twice_nat=0, out2in_only=0, tag=""): """ Add/delete NAT44 static mapping @@ -1083,6 +1085,7 @@ class TestNAT44(MethodHolder): :param proto: IP protocol (Mandatory if port specified) :param twice_nat: 1 if translate external host address and port :param out2in_only: if 1 rule is matching only out2in direction + :param tag: Opaque string tag """ addr_only = 1 if local_port and external_port: @@ -1100,6 +1103,7 @@ class TestNAT44(MethodHolder): proto, twice_nat, out2in_only, + tag, is_add) def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0): @@ -1376,6 +1380,9 @@ class TestNAT44(MethodHolder): self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index) self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index, is_inside=0) + sm = self.vapi.nat44_static_mapping_dump() + self.assertEqual(len(sm), 1) + self.assertEqual((sm[0].tag).split('\0', 1)[0], '') # in2out pkts = self.create_stream_in(self.pg0, self.pg1) @@ -1400,11 +1407,15 @@ class TestNAT44(MethodHolder): self.tcp_port_out = 6303 self.udp_port_out = 6304 self.icmp_id_out = 6305 + tag = "testTAG" - self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip) + self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag) self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index) self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index, is_inside=0) + sm = self.vapi.nat44_static_mapping_dump() + self.assertEqual(len(sm), 1) + self.assertEqual((sm[0].tag).split('\0', 1)[0], tag) # out2in pkts = self.create_stream_out(self.pg1, nat_ip) @@ -2338,16 +2349,20 @@ class TestNAT44(MethodHolder): def test_interface_addr_static_mapping(self): """ Static mapping with addresses from interface """ + tag = "testTAG" + self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index) self.nat44_add_static_mapping( '1.2.3.4', - external_sw_if_index=self.pg7.sw_if_index) + external_sw_if_index=self.pg7.sw_if_index, + tag=tag) # static mappings with external interface static_mappings = self.vapi.nat44_static_mapping_dump() self.assertEqual(1, len(static_mappings)) self.assertEqual(self.pg7.sw_if_index, static_mappings[0].external_sw_if_index) + self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag) # configure interface address and check static mappings self.pg7.config_ip4() @@ -2356,6 +2371,7 @@ class TestNAT44(MethodHolder): self.assertEqual(static_mappings[0].external_ip_address[0:4], self.pg7.local_ip4n) self.assertEqual(0xFFFFFFFF, static_mappings[0].external_sw_if_index) + self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag) # remove interface address and check static mappings self.pg7.unconfig_ip4() diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py index db0f8e61aed..b791444fdcd 100644 --- a/test/vpp_papi_provider.py +++ b/test/vpp_papi_provider.py @@ -1236,6 +1236,7 @@ class VppPapiProvider(object): protocol=0, twice_nat=0, out2in_only=0, + tag="", is_add=1): """Add/delete NAT44 static mapping @@ -1249,6 +1250,7 @@ class VppPapiProvider(object): :param protocol: IP protocol (Default value = 0) :param twice_nat: 1 if translate external host address and port :param out2in_only: if 1 rule is matching only out2in direction + :param tag: Opaque string tag :param is_add: 1 if add, 0 if delete (Default value = 1) """ return self.api( @@ -1263,7 +1265,8 @@ class VppPapiProvider(object): 'vrf_id': vrf_id, 'protocol': protocol, 'twice_nat': twice_nat, - 'out2in_only': out2in_only}) + 'out2in_only': out2in_only, + 'tag': tag}) def nat44_add_del_identity_mapping( self, @@ -1273,6 +1276,7 @@ class VppPapiProvider(object): addr_only=1, vrf_id=0, protocol=0, + tag='', is_add=1): """Add/delete NAT44 identity mapping @@ -1282,6 +1286,7 @@ class VppPapiProvider(object): :param addr_only: 1 if address only mapping, 0 if address and port :param vrf_id: VRF ID :param protocol: IP protocol (Default value = 0) + :param tag: Opaque string tag :param is_add: 1 if add, 0 if delete (Default value = 1) """ return self.api( @@ -1292,6 +1297,7 @@ class VppPapiProvider(object): 'port': port, 'sw_if_index': sw_if_index, 'vrf_id': vrf_id, + 'tag': tag, 'protocol': protocol}) def nat44_add_del_address_range( @@ -1424,12 +1430,14 @@ class VppPapiProvider(object): vrf_id=0, twice_nat=0, out2in_only=0, + tag='', local_num=0, locals=[], is_add=1): """Add/delete NAT44 load balancing static mapping :param twice_nat: 1 if translate external host address and port + :param tag: Opaque string tag :param is_add - 1 if add, 0 if delete """ return self.api( @@ -1441,6 +1449,7 @@ class VppPapiProvider(object): 'vrf_id': vrf_id, 'twice_nat': twice_nat, 'out2in_only': out2in_only, + 'tag': tag, 'local_num': local_num, 'locals': locals}) -- 2.16.6