From 6bc8c6493c8e7e1401130f8c9ca34c9b2915a7ad Mon Sep 17 00:00:00 2001 From: Martin Gálik Date: Wed, 19 Apr 2017 01:12:27 -0700 Subject: CGNAT: close session API and CLI commands. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I9c8636bd2c4b8da2907e8e4a4f2be1a2c3a8e0bb Signed-off-by: Martin Gálik --- src/plugins/snat/snat.api | 38 +++++++ src/plugins/snat/snat.c | 243 ++++++++++++++++++++++++++++++++++++++++++- src/plugins/snat/snat_test.c | 74 ++++++++++++- 3 files changed, 351 insertions(+), 4 deletions(-) (limited to 'src/plugins/snat') diff --git a/src/plugins/snat/snat.api b/src/plugins/snat/snat.api index 573b6753..5990eae5 100644 --- a/src/plugins/snat/snat.api +++ b/src/plugins/snat/snat.api @@ -527,3 +527,41 @@ define snat_det_get_timeouts_reply { u32 tcp_transitory; u32 icmp; }; + +/** \brief Close CGNAT session by outside address and port + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param is_ip4 - 1 if address type is IPv4 + @param out_addr - outside IP address + @param out_port - outside port + @param ext_addr - external host address + @param ext_port - external host port +*/ +autoreply define snat_det_close_session_out { + u32 client_index; + u32 context; + u8 is_ip4; + u8 out_addr[16]; + u16 out_port; + u8 ext_addr[16]; + u16 ext_port; +}; + +/** \brief Close CGNAT session by inside address and port + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param is_ip4 - 1 if address type is IPv4 + @param in_addr - inside IP address + @param in_port - inside port + @param ext_addr - external host address + @param ext_port - external host port +*/ +autoreply define snat_det_close_session_in { + u32 client_index; + u32 context; + u8 is_ip4; + u8 in_addr[16]; + u16 in_port; + u8 ext_addr[16]; + u16 ext_port; +}; diff --git a/src/plugins/snat/snat.c b/src/plugins/snat/snat.c index 8569b041..594afa62 100644 --- a/src/plugins/snat/snat.c +++ b/src/plugins/snat/snat.c @@ -1712,6 +1712,105 @@ static void *vl_api_snat_det_get_timeouts_t_print FINISH; } +static void +vl_api_snat_det_close_session_out_t_handler +(vl_api_snat_det_close_session_out_t * mp) +{ + snat_main_t * sm = &snat_main; + vl_api_snat_det_close_session_out_reply_t * rmp; + ip4_address_t out_addr, ext_addr, in_addr; + snat_det_out_key_t key; + snat_det_map_t * dm; + snat_det_session_t * ses; + int rv = 0; + + clib_memcpy(&out_addr, mp->out_addr, 4); + clib_memcpy(&ext_addr, mp->ext_addr, 4); + + dm = snat_det_map_by_out(sm, &out_addr); + if (!dm) + { + rv = VNET_API_ERROR_NO_SUCH_ENTRY; + goto send_reply; + } + snat_det_reverse(dm, &ext_addr, ntohs(mp->out_port), &in_addr); + key.ext_host_addr = ext_addr; + key.ext_host_port = mp->ext_port; + key.out_port = mp->out_port; + ses = snat_det_get_ses_by_out(dm, &in_addr, key.as_u64); + if (!ses) + { + rv = VNET_API_ERROR_NO_SUCH_ENTRY; + goto send_reply; + } + snat_det_ses_close(dm, ses); + +send_reply: + REPLY_MACRO (VL_API_SNAT_DET_CLOSE_SESSION_OUT_REPLY); +} + +static void *vl_api_snat_det_close_session_out_t_print +(vl_api_snat_det_close_session_out_t *mp, void * handle) +{ + u8 * s; + + s = format (0, "SCRIPT: snat_det_close_session_out "); + s = format (s, "out_addr %U out_port %d " + "ext_addr %U ext_port %d\n", + format_ip4_address, mp->out_addr, ntohs(mp->out_port), + format_ip4_address, mp->ext_addr, ntohs(mp->ext_port)); + + FINISH; +} + +static void +vl_api_snat_det_close_session_in_t_handler +(vl_api_snat_det_close_session_in_t * mp) +{ + snat_main_t * sm = &snat_main; + vl_api_snat_det_close_session_in_reply_t * rmp; + ip4_address_t in_addr, ext_addr; + snat_det_out_key_t key; + snat_det_map_t * dm; + snat_det_session_t * ses; + int rv = 0; + + clib_memcpy(&in_addr, mp->in_addr, 4); + clib_memcpy(&ext_addr, mp->ext_addr, 4); + + dm = snat_det_map_by_user(sm, &in_addr); + if (!dm) + { + rv = VNET_API_ERROR_NO_SUCH_ENTRY; + goto send_reply; + } + key.ext_host_addr = ext_addr; + key.ext_host_port = mp->ext_port; + ses = snat_det_find_ses_by_in(dm, &in_addr, mp->in_port, key); + if (!ses) + { + rv = VNET_API_ERROR_NO_SUCH_ENTRY; + goto send_reply; + } + snat_det_ses_close(dm, ses); + +send_reply: + REPLY_MACRO (VL_API_SNAT_DET_CLOSE_SESSION_OUT_REPLY); +} + +static void *vl_api_snat_det_close_session_in_t_print +(vl_api_snat_det_close_session_in_t *mp, void * handle) +{ + u8 * s; + s = format (0, "SCRIPT: snat_det_close_session_in "); + s = format (s, "in_addr %U in_port %d " + "ext_addr %U ext_port %d\n", + format_ip4_address, mp->in_addr, ntohs(mp->in_port), + format_ip4_address, mp->ext_addr, ntohs(mp->ext_port)); + + FINISH; +} + /* List of message types that this plugin understands */ #define foreach_snat_plugin_api_msg \ _(SNAT_ADD_ADDRESS_RANGE, snat_add_address_range) \ @@ -1734,7 +1833,9 @@ _(SNAT_DET_FORWARD, snat_det_forward) \ _(SNAT_DET_REVERSE, snat_det_reverse) \ _(SNAT_DET_MAP_DUMP, snat_det_map_dump) \ _(SNAT_DET_SET_TIMEOUTS, snat_det_set_timeouts) \ -_(SNAT_DET_GET_TIMEOUTS, snat_det_get_timeouts) +_(SNAT_DET_GET_TIMEOUTS, snat_det_get_timeouts) \ +_(SNAT_DET_CLOSE_SESSION_OUT, snat_det_close_session_out) \ +_(SNAT_DET_CLOSE_SESSION_IN, snat_det_close_session_in) /* Set up the API message handling tables */ @@ -3488,3 +3589,143 @@ VLIB_CLI_COMMAND (set_timeout_command, static) = { "set snat deterministic timeout [udp | tcp-established " "tcp-transitory | icmp | reset]", }; + +static clib_error_t * +snat_det_close_session_out_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; + ip4_address_t out_addr, ext_addr, in_addr; + u16 out_port, ext_port; + snat_det_map_t * dm; + snat_det_session_t * ses; + snat_det_out_key_t key; + clib_error_t *error = 0; + + /* 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:%d %U:%d", + unformat_ip4_address, &out_addr, &out_port, + unformat_ip4_address, &ext_addr, &ext_port)) + ; + else + { + error = clib_error_return (0, "unknown input '%U'", + format_unformat_error, line_input); + goto done; + } + } + + unformat_free (line_input); + + dm = snat_det_map_by_out(sm, &out_addr); + if (!dm) + vlib_cli_output (vm, "no match"); + else + { + snat_det_reverse(dm, &ext_addr, out_port, &in_addr); + key.ext_host_addr = out_addr; + key.ext_host_port = ntohs(ext_port); + key.out_port = ntohs(out_port); + ses = snat_det_get_ses_by_out(dm, &out_addr, key.as_u64); + if (!ses) + vlib_cli_output (vm, "no match"); + else + snat_det_ses_close(dm, ses); + } + +done: + unformat_free (line_input); + + return error; +} + +/*? + * @cliexpar + * @cliexstart{snat deterministic close session out} + * Close session using outside ip address and port + * and external ip address and port, use: + * vpp# snat deterministic close session out 1.1.1.1:1276 2.2.2.2:2387 + * @cliexend +?*/ +VLIB_CLI_COMMAND (snat_det_close_sesion_out_command, static) = { + .path = "snat deterministic close session out", + .short_help = "snat deterministic close session out " + ": :", + .function = snat_det_close_session_out_fn, +}; + +static clib_error_t * +snat_det_close_session_in_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; + ip4_address_t in_addr, ext_addr; + u16 in_port, ext_port; + snat_det_map_t * dm; + snat_det_session_t * ses; + snat_det_out_key_t key; + clib_error_t *error = 0; + + /* 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:%d %U:%d", + unformat_ip4_address, &in_addr, &in_port, + unformat_ip4_address, &ext_addr, &ext_port)) + ; + else + { + error = clib_error_return (0, "unknown input '%U'", + format_unformat_error, line_input); + goto done; + } + } + + unformat_free (line_input); + + dm = snat_det_map_by_user (sm, &in_addr); + if (!dm) + vlib_cli_output (vm, "no match"); + else + { + key.ext_host_addr = ext_addr; + key.ext_host_port = ntohs (ext_port); + ses = snat_det_find_ses_by_in (dm, &in_addr, ntohs(in_port), key); + if (!ses) + vlib_cli_output (vm, "no match"); + else + snat_det_ses_close(dm, ses); + } + +done: + unformat_free(line_input); + + return error; +} + +/*? + * @cliexpar + * @cliexstart{snat deterministic close_session_in} + * Close session using inside ip address and port + * and external ip address and port, use: + * vpp# snat deterministic close session in 3.3.3.3:3487 2.2.2.2:2387 + * @cliexend +?*/ +VLIB_CLI_COMMAND (snat_det_close_session_in_command, static) = { + .path = "snat deterministic close session in", + .short_help = "snat deterministic close session in " + ": :", + .function = snat_det_close_session_in_fn, +}; diff --git a/src/plugins/snat/snat_test.c b/src/plugins/snat/snat_test.c index 4117d944..14e8d199 100644 --- a/src/plugins/snat/snat_test.c +++ b/src/plugins/snat/snat_test.c @@ -69,7 +69,9 @@ _(snat_set_workers_reply) \ _(snat_add_del_interface_addr_reply) \ _(snat_ipfix_enable_disable_reply) \ _(snat_add_det_map_reply) \ -_(snat_det_set_timeouts_reply) +_(snat_det_set_timeouts_reply) \ +_(snat_det_close_session_out_reply) \ +_(snat_det_close_session_in_reply) #define _(n) \ static void vl_api_##n##_t_handler \ @@ -115,7 +117,11 @@ _(SNAT_DET_FORWARD_REPLY, snat_det_forward_reply) \ _(SNAT_DET_REVERSE_REPLY, snat_det_reverse_reply) \ _(SNAT_DET_MAP_DETAILS, snat_det_map_details) \ _(SNAT_DET_SET_TIMEOUTS_REPLY, snat_det_set_timeouts_reply) \ -_(SNAT_DET_GET_TIMEOUTS_REPLY, snat_det_get_timeouts_reply) +_(SNAT_DET_GET_TIMEOUTS_REPLY, snat_det_get_timeouts_reply) \ +_(SNAT_DET_CLOSE_SESSION_OUT_REPLY, \ + snat_det_close_session_out_reply) \ +_(SNAT_DET_CLOSE_SESSION_IN_REPLY, \ + snat_det_close_session_in_reply) static int api_snat_add_address_range (vat_main_t * vam) { @@ -969,6 +975,64 @@ static int api_snat_det_get_timeouts(vat_main_t * vam) return ret; } +static int api_snat_det_close_session_out (vat_main_t * vam) +{ + unformat_input_t * i = vam->input; + vl_api_snat_det_close_session_out_t * mp; + ip4_address_t out_addr, ext_addr; + u16 out_port, ext_port; + int ret; + + if (unformat (i, "%U:%d %U:%d", + unformat_ip4_address, &out_addr, &out_port, + unformat_ip4_address, &ext_addr, &ext_port)) + ; + else + { + clib_warning("unknown input '%U'", format_unformat_error, i); + return -99; + } + + M(SNAT_DET_CLOSE_SESSION_OUT, mp); + clib_memcpy(mp->out_addr, &out_addr, 4); + mp->out_port = ntohs(out_port); + clib_memcpy(mp->ext_addr, &ext_addr, 4); + mp->ext_port = ntohs(ext_port); + + S(mp); + W (ret); + return ret; +} + +static int api_snat_det_close_session_in (vat_main_t * vam) +{ + unformat_input_t * i = vam->input; + vl_api_snat_det_close_session_in_t * mp; + ip4_address_t in_addr, ext_addr; + u16 in_port, ext_port; + int ret; + + if (unformat (i, "%U:%d %U:%d", + unformat_ip4_address, &in_addr, &in_port, + unformat_ip4_address, &ext_addr, &ext_port)) + ; + else + { + clib_warning("unknown input '%U'", format_unformat_error, i); + return -99; + } + + M(SNAT_DET_CLOSE_SESSION_IN, mp); + clib_memcpy(mp->in_addr, &in_addr, 4); + mp->in_port = ntohs(in_port); + clib_memcpy(mp->ext_addr, &ext_addr, 4); + mp->ext_port = ntohs(ext_port); + + S(mp); + W (ret); + return ret; +} + /* * List of messages that the api test plugin sends, * and that the data plane plugin processes @@ -1001,7 +1065,11 @@ _(snat_det_reverse, " ") \ _(snat_det_map_dump, "") \ _(snat_det_set_timeouts, "[udp | tcp_established | " \ "tcp_transitory | icmp ]") \ -_(snat_det_get_timeouts, "") +_(snat_det_get_timeouts, "") \ +_(snat_det_close_session_out, ": " \ + ":") \ +_(snat_det_close_session_in, ": " \ + ":") static void snat_vat_api_hookup (vat_main_t *vam) -- cgit 1.2.3-korg