diff options
author | Matus Fabian <matfabia@cisco.com> | 2017-10-26 03:37:38 -0700 |
---|---|---|
committer | Ole Trøan <otroan@employees.org> | 2017-10-26 17:35:28 +0000 |
commit | 5ba86f72439a627f2084bcafb221ad77f4990168 (patch) | |
tree | ba76c4e83d3dbaa6c0b39854da385ff511cc4b18 /src/plugins/nat | |
parent | 0404c682613c163c54d787a86e4b281bd3bba340 (diff) |
NAT: delete session API/CLI (VPP-1041)
Administratively delete NAT44 session for specific inside/outside addresses and port pair.
Change-Id: If5ab500ac3592c7153d6d8f2cc0297df7309fbc3
Signed-off-by: Matus Fabian <matfabia@cisco.com>
Diffstat (limited to 'src/plugins/nat')
-rw-r--r-- | src/plugins/nat/nat.api | 20 | ||||
-rw-r--r-- | src/plugins/nat/nat.c | 113 | ||||
-rw-r--r-- | src/plugins/nat/nat.h | 2 | ||||
-rw-r--r-- | src/plugins/nat/nat_api.c | 37 |
4 files changed, 172 insertions, 0 deletions
diff --git a/src/plugins/nat/nat.api b/src/plugins/nat/nat.api index fe408211d83..98a6f0673e4 100644 --- a/src/plugins/nat/nat.api +++ b/src/plugins/nat/nat.api @@ -1061,6 +1061,26 @@ manual_endian define nat44_lb_static_mapping_details { vl_api_nat44_lb_addr_port_t locals[local_num]; }; +/** \brief Delete NAT44 session + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param is_in - 1 if inside network addres and port pari, 0 if outside + @param ip_address - IPv4 address + @param protocol - IP protocol + @param port - port number + @param vfr_id - VRF ID +*/ +autoreply define nat44_del_session { + u32 client_index; + u32 context; + u8 is_in; + u8 address[4]; + u8 protocol; + u16 port; + u32 vrf_id; +}; + + /* * Deterministic NAT (CGN) APIs */ diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index 50ab317759e..189c5940d9c 100644 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -3075,6 +3075,119 @@ VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = { .function = snat_add_interface_address_command_fn, }; +int +nat44_del_session (snat_main_t *sm, ip4_address_t *addr, u16 port, + snat_protocol_t proto, u32 vrf_id, int is_in) +{ + snat_main_per_thread_data_t *tsm; + clib_bihash_kv_8_8_t kv, value; + ip4_header_t ip; + u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id); + snat_session_key_t key; + snat_session_t *s; + clib_bihash_8_8_t *t; + snat_user_key_t u_key; + snat_user_t *u; + + ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32; + if (sm->num_workers) + tsm = + vec_elt_at_index (sm->per_thread_data, + sm->worker_in2out_cb (&ip, fib_index)); + else + tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); + + key.addr.as_u32 = addr->as_u32; + key.port = clib_host_to_net_u16 (port); + key.protocol = proto; + key.fib_index = fib_index; + kv.key = key.as_u64; + t = is_in ? &tsm->in2out : &tsm->out2in; + if (!clib_bihash_search_8_8 (t, &kv, &value)) + { + s = pool_elt_at_index (tsm->sessions, value.value); + kv.key = s->in2out.as_u64; + clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 0); + kv.key = s->out2in.as_u64; + clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 0); + u_key.addr = s->in2out.addr; + u_key.fib_index = s->in2out.fib_index; + kv.key = u_key.as_u64; + if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value)) + { + u = pool_elt_at_index (tsm->users, value.value); + u->nsessions--; + } + clib_dlist_remove (tsm->list_pool, s->per_user_index); + pool_put (tsm->sessions, s); + return 0; + } + + return VNET_API_ERROR_NO_SUCH_ENTRY; +} + +static clib_error_t * +nat44_del_session_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + snat_main_t *sm = &snat_main; + unformat_input_t _line_input, *line_input = &_line_input; + int is_in = 0; + clib_error_t *error = 0; + ip4_address_t addr; + u32 port = 0, vrf_id = sm->outside_vrf_id; + snat_protocol_t proto; + int rv; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%U:%u %U", unformat_ip4_address, &addr, &port, + unformat_snat_protocol, &proto)) + ; + else if (unformat (line_input, "in")) + { + is_in = 1; + vrf_id = sm->inside_vrf_id; + } + else if (unformat (line_input, "vrf %u", &vrf_id)) + ; + else + { + error = clib_error_return (0, "unknown input '%U'", + format_unformat_error, line_input); + goto done; + } + } + + rv = nat44_del_session(sm, &addr, port, proto, vrf_id, is_in); + + switch (rv) + { + case 0: + break; + + default: + error = clib_error_return (0, "nat44_del_session returned %d", rv); + goto done; + } + +done: + unformat_free (line_input); + + return error; +} + +VLIB_CLI_COMMAND (nat44_del_session_command, static) = { + .path = "nat44 del session", + .short_help = "nat44 del session in|out <addr>:<port> tcp|udp|icmp [vrf <id>]", + .function = nat44_del_session_command_fn, +}; + static clib_error_t * snat_det_map_command_fn (vlib_main_t * vm, unformat_input_t * input, diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h index d4ad72520da..9c50a0b77ec 100644 --- a/src/plugins/nat/nat.h +++ b/src/plugins/nat/nat.h @@ -507,6 +507,8 @@ 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); +int nat44_del_session (snat_main_t *sm, ip4_address_t *addr, u16 port, + snat_protocol_t proto, u32 vrf_id, int is_in); static_always_inline u8 icmp_is_error_message (icmp46_header_t * icmp) diff --git a/src/plugins/nat/nat_api.c b/src/plugins/nat/nat_api.c index 96f69eba186..f80a5067a43 100644 --- a/src/plugins/nat/nat_api.c +++ b/src/plugins/nat/nat_api.c @@ -2277,6 +2277,42 @@ static void *vl_api_nat44_lb_static_mapping_dump_t_print FINISH; } +static void +vl_api_nat44_del_session_t_handler (vl_api_nat44_del_session_t * mp) +{ + snat_main_t *sm = &snat_main; + vl_api_nat44_del_session_reply_t *rmp; + ip4_address_t addr; + u16 port; + u32 vrf_id; + int rv = 0; + snat_protocol_t proto; + + memcpy (&addr.as_u8, mp->address, 4); + port = clib_net_to_host_u16 (mp->port); + vrf_id = clib_net_to_host_u32 (mp->vrf_id); + proto = ip_proto_to_snat_proto (mp->protocol); + + rv = nat44_del_session (sm, &addr, port, proto, vrf_id, mp->is_in); + + REPLY_MACRO (VL_API_NAT44_DEL_SESSION_REPLY); +} + +static void * +vl_api_nat44_del_session_t_print (vl_api_nat44_del_session_t * mp, + void *handle) +{ + u8 *s; + + s = format (0, "SCRIPT: nat44_add_del_static_mapping "); + s = format (s, "addr %U port %d protocol %d vrf_id %d is_in %d", + format_ip4_address, mp->address, + clib_net_to_host_u16 (mp->port), + mp->protocol, clib_net_to_host_u32 (mp->vrf_id), mp->is_in); + + FINISH; +} + /*******************************/ /*** Deterministic NAT (CGN) ***/ /*******************************/ @@ -3304,6 +3340,7 @@ _(NAT44_INTERFACE_OUTPUT_FEATURE_DUMP, \ nat44_interface_output_feature_dump) \ _(NAT44_ADD_DEL_LB_STATIC_MAPPING, nat44_add_del_lb_static_mapping) \ _(NAT44_LB_STATIC_MAPPING_DUMP, nat44_lb_static_mapping_dump) \ +_(NAT44_DEL_SESSION, nat44_del_session) \ _(NAT_DET_ADD_DEL_MAP, nat_det_add_del_map) \ _(NAT_DET_FORWARD, nat_det_forward) \ _(NAT_DET_REVERSE, nat_det_reverse) \ |