diff options
Diffstat (limited to 'src/plugins/nat')
-rw-r--r-- | src/plugins/nat/dslite_in2out.c | 1 | ||||
-rwxr-xr-x | src/plugins/nat/in2out.c | 11 | ||||
-rw-r--r-- | src/plugins/nat/nat.api | 35 | ||||
-rwxr-xr-x | src/plugins/nat/nat.c | 1 | ||||
-rw-r--r-- | src/plugins/nat/nat.h | 4 | ||||
-rw-r--r-- | src/plugins/nat/nat44_cli.c | 76 | ||||
-rw-r--r-- | src/plugins/nat/nat64_in2out.c | 1 | ||||
-rw-r--r-- | src/plugins/nat/nat_api.c | 59 | ||||
-rw-r--r-- | src/plugins/nat/nat_inlines.h | 48 |
9 files changed, 236 insertions, 0 deletions
diff --git a/src/plugins/nat/dslite_in2out.c b/src/plugins/nat/dslite_in2out.c index bf51ca23051..8f5a0c0e248 100644 --- a/src/plugins/nat/dslite_in2out.c +++ b/src/plugins/nat/dslite_in2out.c @@ -377,6 +377,7 @@ dslite_in2out_node_fn_inline (vlib_main_t * vm, vlib_node_runtime_t * node, sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t, length); + mss_clamping (&snat_main, tcp0, &sum0); tcp0->checksum = ip_csum_fold (sum0); } else diff --git a/src/plugins/nat/in2out.c b/src/plugins/nat/in2out.c index 22a346855c6..661d8c1bef9 100755 --- a/src/plugins/nat/in2out.c +++ b/src/plugins/nat/in2out.c @@ -1336,6 +1336,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t /* cheat */, length /* changed member */); + mss_clamping (sm, tcp0, &sum0); tcp0->checksum = ip_csum_fold(sum0); } else @@ -1496,6 +1497,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, sum1 = ip_csum_update (sum1, old_port1, new_port1, ip4_header_t /* cheat */, length /* changed member */); + mss_clamping (sm, tcp1, &sum1); tcp1->checksum = ip_csum_fold(sum1); } else @@ -1693,6 +1695,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t /* cheat */, length /* changed member */); + mss_clamping (sm, tcp0, &sum0); tcp0->checksum = ip_csum_fold(sum0); } else @@ -3354,6 +3357,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm, tcp0->dst_port = s0->ext_host_port; ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32; } + mss_clamping (sm, tcp0, &sum0); tcp0->checksum = ip_csum_fold(sum0); if (nat44_set_tcp_session_state_i2o (sm, s0, tcp0, thread_index)) goto trace00; @@ -3539,6 +3543,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm, ip1->dst_address.as_u32 = s1->ext_host_addr.as_u32; } tcp1->checksum = ip_csum_fold(sum1); + mss_clamping (sm, tcp1, &sum1); if (nat44_set_tcp_session_state_i2o (sm, s1, tcp1, thread_index)) goto trace01; } @@ -3751,6 +3756,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm, tcp0->dst_port = s0->ext_host_port; ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32; } + mss_clamping (sm, tcp0, &sum0); tcp0->checksum = ip_csum_fold(sum0); if (nat44_set_tcp_session_state_i2o (sm, s0, tcp0, thread_index)) goto trace0; @@ -4122,6 +4128,7 @@ snat_det_in2out_node_fn (vlib_main_t * vm, sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t /* cheat */, length /* changed member */); + mss_clamping (sm, tcp0, &sum0); tcp0->checksum = ip_csum_fold(sum0); } else @@ -4272,6 +4279,7 @@ snat_det_in2out_node_fn (vlib_main_t * vm, sum1 = ip_csum_update (sum1, old_port1, new_port1, ip4_header_t /* cheat */, length /* changed member */); + mss_clamping (sm, tcp1, &sum1); tcp1->checksum = ip_csum_fold(sum1); } else @@ -4458,6 +4466,7 @@ snat_det_in2out_node_fn (vlib_main_t * vm, sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t /* cheat */, length /* changed member */); + mss_clamping (sm, tcp0, &sum0); tcp0->checksum = ip_csum_fold(sum0); } else @@ -5354,6 +5363,7 @@ snat_in2out_fast_static_map_fn (vlib_main_t * vm, sum0 = ip_csum_update (sum0, old_port0, new_port0, ip4_header_t /* cheat */, length /* changed member */); + mss_clamping (sm, tcp0, &sum0); tcp0->checksum = ip_csum_fold(sum0); } else @@ -5371,6 +5381,7 @@ snat_in2out_fast_static_map_fn (vlib_main_t * vm, sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t, dst_address /* changed member */); + mss_clamping (sm, tcp0, &sum0); tcp0->checksum = ip_csum_fold(sum0); } } diff --git a/src/plugins/nat/nat.api b/src/plugins/nat/nat.api index 1ff288dba2a..6e2d8e57853 100644 --- a/src/plugins/nat/nat.api +++ b/src/plugins/nat/nat.api @@ -332,6 +332,41 @@ define nat_get_addr_and_port_alloc_alg_reply { u16 end_port; }; +/** \brief Set TCP MSS rewriting configuration + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param mss_value - MSS value to be used for MSS rewriting + @param enable - disable(0)/enable(1) MSS rewriting feature +*/ +autoreply define nat_set_mss_clamping { + u32 client_index; + u32 context; + u16 mss_value; + u8 enable; +}; + +/** \brief Get TCP MSS rewriting configuration + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ +define nat_get_mss_clamping { + u32 client_index; + u32 context; +}; + +/** \brief Get TCP MSS rewriting configuration reply + @param context - sender context, to match reply w/ request + @param retval - return code + @param mss_value - MSS value to be used for MSS rewriting + @param enable - disable(0)/enable(1) MSS rewriting feature +*/ +define nat_get_mss_clamping_reply { + u32 context; + i32 retval; + u16 mss_value; + u8 enable; +}; + /* * NAT44 APIs */ diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index ac81a9930dc..03e264eda3b 100755 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -2078,6 +2078,7 @@ static clib_error_t * snat_init (vlib_main_t * vm) sm->log_class = vlib_log_register_class ("nat", 0); error_drop_node = vlib_get_node_by_name (vm, (u8 *) "error-drop"); sm->error_node_index = error_drop_node->index; + sm->mss_clamping = 0; p = hash_get_mem (tm->thread_registrations_by_name, "workers"); if (p) diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h index d8d0b2a9c4d..06a61626333 100644 --- a/src/plugins/nat/nat.h +++ b/src/plugins/nat/nat.h @@ -439,6 +439,10 @@ typedef struct snat_main_s { u32 tcp_transitory_timeout; u32 icmp_timeout; + /* TCP MSS clamping */ + u16 mss_clamping; + u16 mss_value_net; + /* API message ID base */ u16 msg_id_base; diff --git a/src/plugins/nat/nat44_cli.c b/src/plugins/nat/nat44_cli.c index 17a3827dee6..4f02896f4b9 100644 --- a/src/plugins/nat/nat44_cli.c +++ b/src/plugins/nat/nat44_cli.c @@ -292,6 +292,56 @@ nat44_show_alloc_addr_and_port_alg_command_fn (vlib_main_t * vm, } static clib_error_t * +nat_set_mss_clamping_command_fn (vlib_main_t * vm, unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + snat_main_t *sm = &snat_main; + clib_error_t *error = 0; + u32 mss; + + /* 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, "disable")) + sm->mss_clamping = 0; + else if (unformat (line_input, "%d", &mss)) + { + sm->mss_clamping = (u16) mss; + sm->mss_value_net = clib_host_to_net_u16 (sm->mss_clamping); + } + else + { + error = clib_error_return (0, "unknown input '%U'", + format_unformat_error, line_input); + goto done; + } + } + +done: + unformat_free (line_input); + + return error; +} + +static clib_error_t * +nat_show_mss_clamping_command_fn (vlib_main_t * vm, unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + snat_main_t *sm = &snat_main; + + if (sm->mss_clamping) + vlib_cli_output (vm, "mss-clamping %d", sm->mss_clamping); + else + vlib_cli_output (vm, "mss-clamping disabled"); + + return 0; +} + +static clib_error_t * add_address_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { @@ -1704,6 +1754,32 @@ VLIB_CLI_COMMAND (nat44_show_alloc_addr_and_port_alg_command, static) = { /*? * @cliexpar + * @cliexstart{nat mss-clamping} + * Set TCP MSS rewriting configuration + * To enable TCP MSS rewriting use: + * vpp# nat mss-clamping 1452 + * To disbale TCP MSS rewriting use: + * vpp# nat mss-clamping disable +?*/ +VLIB_CLI_COMMAND (nat_set_mss_clamping_command, static) = { + .path = "nat mss-clamping", + .short_help = "nat mss-clamping <mss-value>|disable", + .function = nat_set_mss_clamping_command_fn, +}; + +/*? + * @cliexpar + * @cliexstart{nat mss-clamping} + * Show TCP MSS rewriting configuration +?*/ +VLIB_CLI_COMMAND (nat_show_mss_clamping_command, static) = { + .path = "show nat mss-clamping", + .short_help = "show nat mss-clamping", + .function = nat_show_mss_clamping_command_fn, +}; + +/*? + * @cliexpar * @cliexstart{show nat44 hash tables} * Show NAT44 hash tables * @cliexend diff --git a/src/plugins/nat/nat64_in2out.c b/src/plugins/nat/nat64_in2out.c index ddbf5850c7c..e843fcf6730 100644 --- a/src/plugins/nat/nat64_in2out.c +++ b/src/plugins/nat/nat64_in2out.c @@ -239,6 +239,7 @@ nat64_in2out_tcp_udp_set_cb (ip6_header_t * ip6, ip4_header_t * ip4, checksum = &tcp->checksum; csum = ip_csum_sub_even (*checksum, sport); csum = ip_csum_add_even (csum, udp->src_port); + mss_clamping (nm->sm, tcp, &csum); *checksum = ip_csum_fold (csum); } diff --git a/src/plugins/nat/nat_api.c b/src/plugins/nat/nat_api.c index 2994f8001f4..4c532ed7e2b 100644 --- a/src/plugins/nat/nat_api.c +++ b/src/plugins/nat/nat_api.c @@ -573,6 +573,63 @@ static void *vl_api_nat_get_addr_and_port_alloc_alg_t_print FINISH; } +static void +vl_api_nat_set_mss_clamping_t_handler (vl_api_nat_set_mss_clamping_t * mp) +{ + snat_main_t *sm = &snat_main; + vl_api_nat_set_mss_clamping_reply_t *rmp; + int rv = 0; + + if (mp->enable) + { + sm->mss_clamping = ntohs (mp->mss_value); + sm->mss_value_net = mp->mss_value; + } + else + sm->mss_clamping = 0; + + REPLY_MACRO (VL_API_NAT_SET_MSS_CLAMPING_REPLY); +} + +static void * +vl_api_nat_set_mss_clamping_t_print (vl_api_nat_set_mss_clamping_t * mp, + void *handle) +{ + u8 *s; + + s = format (0, "SCRIPT: nat_set_mss_clamping enable %d mss_value %d\n", + mp->enable, ntohs (mp->mss_value)); + + FINISH; +} + +static void +vl_api_nat_get_mss_clamping_t_handler (vl_api_nat_get_mss_clamping_t * mp) +{ + snat_main_t *sm = &snat_main; + vl_api_nat_get_mss_clamping_reply_t *rmp; + int rv = 0; + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_NAT_GET_MSS_CLAMPING_REPLY, + ({ + rmp->enable = sm->mss_clamping ? 1 : 0; + rmp->mss_value = htons (sm->mss_clamping); + })) + /* *INDENT-ON* */ +} + +static void * +vl_api_nat_get_mss_clamping_t_print (vl_api_nat_get_mss_clamping_t * mp, + void *handle) +{ + u8 *s; + + s = format (0, "SCRIPT: nat_get_mss_clamping"); + + FINISH; +} + /*************/ /*** NAT44 ***/ /*************/ @@ -3083,6 +3140,8 @@ _(NAT_SET_TIMEOUTS, nat_set_timeouts) \ _(NAT_GET_TIMEOUTS, nat_get_timeouts) \ _(NAT_SET_ADDR_AND_PORT_ALLOC_ALG, nat_set_addr_and_port_alloc_alg) \ _(NAT_GET_ADDR_AND_PORT_ALLOC_ALG, nat_get_addr_and_port_alloc_alg) \ +_(NAT_SET_MSS_CLAMPING, nat_set_mss_clamping) \ +_(NAT_GET_MSS_CLAMPING, nat_get_mss_clamping) \ _(NAT44_ADD_DEL_ADDRESS_RANGE, nat44_add_del_address_range) \ _(NAT44_INTERFACE_ADD_DEL_FEATURE, nat44_interface_add_del_feature) \ _(NAT44_ADD_DEL_STATIC_MAPPING, nat44_add_del_static_mapping) \ diff --git a/src/plugins/nat/nat_inlines.h b/src/plugins/nat/nat_inlines.h index adfb1d51954..8922c05c393 100644 --- a/src/plugins/nat/nat_inlines.h +++ b/src/plugins/nat/nat_inlines.h @@ -328,6 +328,54 @@ make_sm_kv (clib_bihash_kv_8_8_t * kv, ip4_address_t * addr, u8 proto, kv->value = ~0ULL; } +always_inline void +mss_clamping (snat_main_t * sm, tcp_header_t * tcp, ip_csum_t * sum) +{ + u8 *data; + u8 opt_len, opts_len, kind; + u16 mss; + + if (!(sm->mss_clamping && tcp_syn (tcp))) + return; + + opts_len = (tcp_doff (tcp) << 2) - sizeof (tcp_header_t); + data = (u8 *) (tcp + 1); + for (; opts_len > 0; opts_len -= opt_len, data += opt_len) + { + kind = data[0]; + + if (kind == TCP_OPTION_EOL) + break; + else if (kind == TCP_OPTION_NOOP) + { + opt_len = 1; + continue; + } + else + { + if (opts_len < 2) + return; + opt_len = data[1]; + + if (opt_len < 2 || opt_len > opts_len) + return; + } + + if (kind == TCP_OPTION_MSS) + { + mss = *(u16 *) (data + 2); + if (clib_net_to_host_u16 (mss) > sm->mss_clamping) + { + *sum = + ip_csum_update (*sum, mss, sm->mss_value_net, ip4_header_t, + length); + clib_memcpy (data + 2, &sm->mss_value_net, 2); + } + return; + } + } +} + #endif /* __included_nat_inlines_h__ */ /* |