mss_clamp: TCP MSS clamping plugin

Type: feature

Configure TCP MSS clamping on an interface as follows:
set interface tcp-mss-clamp [rx|tx] <interface-name>
  ip4 [enable|disable|rx|tx] ip4-mss <size>
  ip6 [enable|disable|rx|tx] ip6-mss <size>

Change-Id: I45b04e50a0b70a33e14a9066f981c651292ebffb
Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
Signed-off-by: Miklos Tirpak <miklos.tirpak@gmail.com>
Signed-off-by: Matthew Smith <mgsmith@netgate.com>
This commit is contained in:
Neale Ranns
2018-10-04 06:40:30 -07:00
committed by Damjan Marion
parent ab9f57355f
commit bf55e9931c
8 changed files with 1336 additions and 0 deletions
+5
View File
@@ -512,6 +512,11 @@ M: Hongjun Ni <hongjun.ni@intel.com>
M: Vengada <venggovi@cisco.com>
F: src/plugins/nsh/
Plugin - TCP MSS Clamping
I: mss_clamp
M: Miklos Tirpak <miklos.tirpak@emnify.com>
F: src/plugins/mss_clamp/
Plugin - Time-based MAC filter
I: mactime
Y: src/plugins/mactime/FEATURE.yaml
+30
View File
@@ -0,0 +1,30 @@
# Copyright (c) <current-year> <your-organization>
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
add_vpp_plugin(mss_clamp
SOURCES
mss_clamp.c
mss_clamp_api.c
mss_clamp_node.c
MULTIARCH_SOURCES
mss_clamp_node.c
API_FILES
mss_clamp.api
INSTALL_HEADERS
mss_clamp.h
)
+112
View File
@@ -0,0 +1,112 @@
/* Hey Emacs use -*- mode: C -*- */
/*
* Copyright (c) 2016 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
option version = "1.0.0";
import "vnet/interface_types.api";
/** \brief TCP MSS Clamping direction flag
*/
enumflag mss_clamp_dir : u8 {
MSS_CLAMP_DIR_NONE = 0x0,
MSS_CLAMP_DIR_RX = 0x1,
MSS_CLAMP_DIR_TX = 0x2,
};
/** \brief Enable/Disable TCP MSS Clamping feature on an interface
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param sw_if_index - interface index on which clamping will be applied
@param ipv4_mss - Maximum Segment Size for IPv4/TCP
@param ipv6_mss - Maximum Segment Size for IPv6/TCP
@param ipv4_direction - Direction clamping is enabled on (IPv4/TCP)
@param ipv6_direction - Direction clamping is enabled on (IPv6/TCP)
*/
autoreply define mss_clamp_enable_disable {
u32 client_index;
u32 context;
vl_api_interface_index_t sw_if_index;
u16 ipv4_mss;
u16 ipv6_mss;
vl_api_mss_clamp_dir_t ipv4_direction;
vl_api_mss_clamp_dir_t ipv6_direction;
};
/** \brief Get the list of configured mss values
@param client_index - opaque cookie to identify the sender
*/
service {
rpc mss_clamp_get returns mss_clamp_get_reply
stream mss_clamp_details;
};
/** \brief Get the TCP MSS Clamping feature settings
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param cursor - cursor to continue when there is more to read
@param sw_if_index - interface index to filter the result,
~0 means no filter
*/
define mss_clamp_get {
u32 client_index;
u32 context;
u32 cursor;
vl_api_interface_index_t sw_if_index;
};
/** \brief Reply for get TCP MSS Clamping feature settings request
@param context - returned sender context, to match reply w/ request
@param retval - return code
@param cursor - cursor to continue when there is more to read
*/
define mss_clamp_get_reply {
u32 context;
i32 retval;
u32 cursor;
};
/** \brief Configured MSS values on an interface
@param context - returned sender context, to match reply w/ request
@param sw_if_index - interface index on which clamping is applied
@param ipv4_mss - Maximum Segment Size for IPv4/TCP
@param ipv6_mss - Maximum Segment Size for IPv6/TCP
@param ipv4_direction - Direction clamping is enabled on (IPv4/TCP)
@param ipv6_direction - Direction clamping is enabled on (IPv6/TCP)
*/
define mss_clamp_details {
u32 context;
vl_api_interface_index_t sw_if_index;
u16 ipv4_mss;
u16 ipv6_mss;
vl_api_mss_clamp_dir_t ipv4_direction;
vl_api_mss_clamp_dir_t ipv6_direction;
};
counters mss_clamp {
clamped {
severity info;
type counter64;
units "packets";
description "packets clamped";
};
};
paths {
"/err/tcp-mss-clamping-ip4-in" "mss-clamp";
"/err/tcp-mss-clamping-ip4-out" "mss-clamp";
"/err/tcp-mss-clamping-ip6-in" "mss-clamp";
"/err/tcp-mss-clamping-ip6-out" "mss-clamp";
};
+292
View File
@@ -0,0 +1,292 @@
/*
* mss_clamp.c - TCP MSS clamping plug-in
*
* Copyright (c) 2018 Cisco and/or its affiliates
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <vnet/vnet.h>
#include <vnet/plugin/plugin.h>
#include <mss_clamp/mss_clamp.h>
#include <mss_clamp/mss_clamp.api_types.h>
mssc_main_t mssc_main;
/* Action function shared between message handler and debug CLI */
static void
mssc_enable_disable_feat (u32 sw_if_index, u8 dir4, u8 dir6, int enable)
{
if (dir4 == MSS_CLAMP_DIR_NONE && dir6 == MSS_CLAMP_DIR_NONE)
return;
// ip4
if ((dir4 & MSS_CLAMP_DIR_RX) != MSS_CLAMP_DIR_NONE)
vnet_feature_enable_disable ("ip4-unicast", "tcp-mss-clamping-ip4-in",
sw_if_index, enable, 0, 0);
if ((dir4 & MSS_CLAMP_DIR_TX) != MSS_CLAMP_DIR_NONE)
vnet_feature_enable_disable ("ip4-output", "tcp-mss-clamping-ip4-out",
sw_if_index, enable, 0, 0);
// ip6
if ((dir6 & MSS_CLAMP_DIR_RX) != MSS_CLAMP_DIR_NONE)
vnet_feature_enable_disable ("ip6-unicast", "tcp-mss-clamping-ip6-in",
sw_if_index, enable, 0, 0);
if ((dir6 & MSS_CLAMP_DIR_TX) != MSS_CLAMP_DIR_NONE)
vnet_feature_enable_disable ("ip6-output", "tcp-mss-clamping-ip6-out",
sw_if_index, enable, 0, 0);
}
int
mssc_enable_disable (u32 sw_if_index, u8 dir4, u8 dir6, u16 mss4, u16 mss6)
{
mssc_main_t *cm = &mssc_main;
u8 *dir_enabled4, *dir_enabled6;
int rv = 0;
if (dir4 == MSS_CLAMP_DIR_NONE)
mss4 = MSS_CLAMP_UNSET;
if (dir6 == MSS_CLAMP_DIR_NONE)
mss6 = MSS_CLAMP_UNSET;
vec_validate_init_empty (cm->dir_enabled4, sw_if_index, MSS_CLAMP_DIR_NONE);
vec_validate_init_empty (cm->dir_enabled6, sw_if_index, MSS_CLAMP_DIR_NONE);
vec_validate_init_empty (cm->max_mss4, sw_if_index, MSS_CLAMP_UNSET);
vec_validate_init_empty (cm->max_mss6, sw_if_index, MSS_CLAMP_UNSET);
cm->max_mss4[sw_if_index] = mss4;
cm->max_mss6[sw_if_index] = mss6;
dir_enabled4 = &cm->dir_enabled4[sw_if_index];
dir_enabled6 = &cm->dir_enabled6[sw_if_index];
// Disable the directions that are no longer needed
mssc_enable_disable_feat (sw_if_index, (*dir_enabled4) & ~dir4,
(*dir_enabled6) & ~dir6, 0);
// Enable the new directions
mssc_enable_disable_feat (sw_if_index, ~(*dir_enabled4) & dir4,
~(*dir_enabled6) & dir6, 1);
*dir_enabled4 = dir4;
*dir_enabled6 = dir6;
return rv;
}
int
mssc_get_mss (u32 sw_if_index, u8 *dir4, u8 *dir6, u16 *mss4, u16 *mss6)
{
mssc_main_t *cm = &mssc_main;
int rv = VNET_API_ERROR_FEATURE_DISABLED;
if (vec_len (cm->dir_enabled4) > sw_if_index &&
MSS_CLAMP_DIR_NONE != cm->dir_enabled4[sw_if_index])
{
*mss4 = cm->max_mss4[sw_if_index];
*dir4 = cm->dir_enabled4[sw_if_index];
rv = 0;
}
else
{
*mss4 = MSS_CLAMP_DIR_NONE;
*dir4 = 0;
}
if (vec_len (cm->dir_enabled6) > sw_if_index &&
MSS_CLAMP_DIR_NONE != cm->dir_enabled6[sw_if_index])
{
*mss6 = cm->max_mss6[sw_if_index];
*dir6 = cm->dir_enabled6[sw_if_index];
rv = 0;
}
else
{
*mss6 = MSS_CLAMP_DIR_NONE;
*dir6 = 0;
}
return rv;
}
static uword
unformat_mssc_dir (unformat_input_t *input, va_list *args)
{
u8 *result = va_arg (*args, u8 *);
u8 dir = MSS_CLAMP_DIR_RX | MSS_CLAMP_DIR_TX;
if (unformat (input, "disable"))
dir = MSS_CLAMP_DIR_NONE;
else if (unformat (input, "enable"))
dir = MSS_CLAMP_DIR_RX | MSS_CLAMP_DIR_TX;
else if (unformat (input, "rx"))
dir = MSS_CLAMP_DIR_RX;
else if (unformat (input, "tx"))
dir = MSS_CLAMP_DIR_TX;
else
return 0;
*result = dir;
return 1;
}
static clib_error_t *
mssc_enable_command_fn (vlib_main_t *vm, unformat_input_t *input,
vlib_cli_command_t *cmd)
{
u32 sw_if_index = ~0;
u8 dir4 = ~0, dir6 = ~0;
u32 mss4 = ~0, mss6 = ~0;
int rv;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (input, "ip4 %U", unformat_mssc_dir, &dir4))
;
else if (unformat (input, "ip6 %U", unformat_mssc_dir, &dir6))
;
else if (unformat (input, "ip4-mss %d", &mss4))
;
else if (unformat (input, "ip6-mss %d", &mss6))
;
else if (unformat (input, "%U", unformat_vnet_sw_interface,
vnet_get_main (), &sw_if_index))
;
else
break;
}
if (sw_if_index == ~0)
return clib_error_return (0, "Please specify an interface");
if (dir4 == (u8) ~0 || dir6 == (u8) ~0)
return clib_error_return (
0, "Please specify the MSS clamping direction for ip4 and ip6");
if (dir4 != MSS_CLAMP_DIR_NONE)
{
if (mss4 == ~0)
return clib_error_return (
0, "Please specify the Max Segment Size for ip4");
if (mss4 >= MSS_CLAMP_UNSET)
return clib_error_return (0, "Invalid Max Segment Size");
}
if (dir6 != MSS_CLAMP_DIR_NONE)
{
if (mss6 == ~0)
return clib_error_return (
0, "Please specify the Max Segment Size for ip6");
if (mss6 >= MSS_CLAMP_UNSET)
return clib_error_return (0, "Invalid Max Segment Size");
}
rv = mssc_enable_disable (sw_if_index, dir4, dir6, mss4, mss6);
if (rv)
return clib_error_return (0, "Failed: %d = %U", rv, format_vnet_api_errno,
rv);
return (NULL);
}
VLIB_CLI_COMMAND (mssc_enable_disable_command, static) = {
.path = "set interface tcp-mss-clamp",
.short_help = "set interface tcp-mss-clamp <interface-name> "
"ip4 [enable|disable|rx|tx] ip4-mss <size> "
"ip6 [enable|disable|rx|tx] ip6-mss <size>",
.function = mssc_enable_command_fn,
};
static u8 *
format_mssc_clamping (u8 *s, va_list *args)
{
u8 dir = va_arg (*args, u32);
u16 mss = va_arg (*args, u32);
#define DIR2S(d) \
(((d) == (MSS_CLAMP_DIR_RX | MSS_CLAMP_DIR_TX)) ? \
"" : \
(((d) == MSS_CLAMP_DIR_RX) ? " [RX]" : " [TX]"))
if (MSS_CLAMP_DIR_NONE == dir)
{
return format (s, "disabled");
}
u32 mss_u32 = mss;
return format (s, "%d%s", mss_u32, DIR2S (dir));
}
static clib_error_t *
mssc_show_command_fn (vlib_main_t *vm, unformat_input_t *input,
vlib_cli_command_t *cmd)
{
mssc_main_t *cm = &mssc_main;
u32 sw_if_index = ~0;
u32 ii;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (input, "%U", unformat_vnet_sw_interface, vnet_get_main (),
&sw_if_index))
;
else
break;
}
if (sw_if_index == ~0)
{
vec_foreach_index (ii, cm->dir_enabled4)
{
u8 dir4 = cm->dir_enabled4[ii];
u8 dir6 = cm->dir_enabled6[ii];
if (MSS_CLAMP_DIR_NONE != dir4 || MSS_CLAMP_DIR_NONE != dir6)
{
u16 mss4 = cm->max_mss4[ii];
u16 mss6 = cm->max_mss6[ii];
vlib_cli_output (vm, "%U: ip4: %U ip6: %U",
format_vnet_sw_if_index_name, vnet_get_main (),
ii, format_mssc_clamping, dir4, mss4,
format_mssc_clamping, dir6, mss6);
}
}
}
else
{
u16 mss4, mss6;
u8 dir4, dir6;
mssc_get_mss (sw_if_index, &dir4, &dir6, &mss4, &mss6);
vlib_cli_output (vm, "%U: ip4: %U ip6: %U", format_vnet_sw_if_index_name,
vnet_get_main (), sw_if_index, format_mssc_clamping,
dir4, mss4, format_mssc_clamping, dir6, mss6);
}
return (NULL);
}
VLIB_CLI_COMMAND (mssc_show_command, static) = {
.path = "show interface tcp-mss-clamp",
.short_help = "show interface tcp-mss-clamp [interface-name]",
.long_help = "show TCP MSS clamping configurations",
.function = mssc_show_command_fn,
};
static clib_error_t *
mssc_init (vlib_main_t *vm)
{
return NULL;
}
VLIB_INIT_FUNCTION (mssc_init);
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
+55
View File
@@ -0,0 +1,55 @@
/*
* mss_clamp.h - TCP MSS clamping plug-in header file
*
* Copyright (c) 2018 Cisco and/or its affiliates
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __included_mss_clamp_h__
#define __included_mss_clamp_h__
#include <stdbool.h> /* for bool in .api */
#include <vnet/vnet.h>
extern int mssc_enable_disable (u32 sw_if_index, u8 dir4, u8 dir6, u16 mss4,
u16 mss6);
extern int mssc_get_mss (u32 sw_if_index, u8 *dir4, u8 *dir6, u16 *mss4,
u16 *mss6);
typedef struct
{
/* Maximum segment size per interface for IPv4/IPv6 */
u16 *max_mss4;
u16 *max_mss6;
/* Direction the feature is enabled for IPv4/IPv6 (rx, tx, both) */
u8 *dir_enabled4;
u8 *dir_enabled6;
/* API message ID base */
u16 msg_id_base;
} mssc_main_t;
extern mssc_main_t mssc_main;
#define MSS_CLAMP_UNSET 0xffff
#endif /* __included_mss_clamp_h__ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
+136
View File
@@ -0,0 +1,136 @@
/*
* mss_clamp_api.c - TCP MSS clamping plug-in
*
* Copyright (c) <current-year> <your-organization>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <vnet/vnet.h>
#include <vnet/plugin/plugin.h> /* VLIB_PLUGIN_REGISTER */
#include <mss_clamp/mss_clamp.h>
#include <mss_clamp/mss_clamp.api_enum.h>
#include <mss_clamp/mss_clamp.api_types.h>
#include <vlibapi/api.h>
#include <vlibmemory/api.h>
#include <vpp/app/version.h> /* VPP_BUILD_VER */
#define REPLY_MSG_ID_BASE cm->msg_id_base
#include <vlibapi/api_helper_macros.h>
/* API message handler */
static void
vl_api_mss_clamp_enable_disable_t_handler (
vl_api_mss_clamp_enable_disable_t *mp)
{
mssc_main_t *cm = &mssc_main;
vl_api_mss_clamp_enable_disable_reply_t *rmp;
int rv;
VALIDATE_SW_IF_INDEX (mp);
rv = mssc_enable_disable (ntohl (mp->sw_if_index), mp->ipv4_direction,
mp->ipv6_direction, ntohs (mp->ipv4_mss),
ntohs (mp->ipv6_mss));
BAD_SW_IF_INDEX_LABEL;
REPLY_MACRO (VL_API_MSS_CLAMP_ENABLE_DISABLE_REPLY);
}
static void
send_mss_clamp_details (u32 sw_if_index, vl_api_registration_t *rp,
u32 context)
{
mssc_main_t *cm = &mssc_main;
vl_api_mss_clamp_details_t *rmp;
u16 mss4, mss6;
u8 dir4, dir6;
int rv;
mss4 = mss6 = 0;
dir4 = dir6 = MSS_CLAMP_DIR_NONE;
rv = mssc_get_mss (sw_if_index, &dir4, &dir6, &mss4, &mss6);
if (rv == VNET_API_ERROR_FEATURE_DISABLED)
return;
REPLY_MACRO_DETAILS4 (VL_API_MSS_CLAMP_DETAILS, rp, context, ({
rmp->sw_if_index = htonl (sw_if_index);
rmp->ipv4_mss = htons (mss4);
rmp->ipv6_mss = htons (mss6);
rmp->ipv4_direction = dir4;
rmp->ipv6_direction = dir6;
}));
}
static void
vl_api_mss_clamp_get_t_handler (vl_api_mss_clamp_get_t *mp)
{
mssc_main_t *cm = &mssc_main;
vl_api_mss_clamp_get_reply_t *rmp;
int rv = 0;
u32 sw_if_index = ntohl (mp->sw_if_index);
vl_api_registration_t *reg;
reg = vl_api_client_index_to_registration (mp->client_index);
if (!reg)
return;
if (sw_if_index == ~0)
{
if (vec_len (cm->dir_enabled4) == 0)
{
REPLY_MACRO2 (VL_API_MSS_CLAMP_GET_REPLY, ({ rmp->cursor = ~0; }));
return;
}
REPLY_AND_DETAILS_MACRO (
VL_API_MSS_CLAMP_GET_REPLY, cm->dir_enabled4,
({ send_mss_clamp_details (cursor, reg, mp->context); }));
}
else
{
VALIDATE_SW_IF_INDEX (mp);
send_mss_clamp_details (sw_if_index, reg, mp->context);
BAD_SW_IF_INDEX_LABEL;
REPLY_MACRO2 (VL_API_MSS_CLAMP_GET_REPLY, ({ rmp->cursor = ~0; }));
}
}
/* API definitions */
#include <vnet/format_fns.h>
#include <mss_clamp/mss_clamp.api.c>
/* Set up the API message handling tables */
static clib_error_t *
mssc_api_hookup (vlib_main_t *vm)
{
mssc_main_t *cm = &mssc_main;
cm->msg_id_base = setup_message_id_table ();
return 0;
}
VLIB_API_INIT_FUNCTION (mssc_api_hookup);
VLIB_PLUGIN_REGISTER () = {
.version = VPP_BUILD_VER,
.description = "TCP MSS clamping plugin",
};
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,295 @@
#!/usr/bin/env python3
import unittest
from framework import VppTestCase, VppTestRunner
from scapy.layers.inet import IP, TCP
from scapy.layers.inet6 import IPv6
from scapy.layers.l2 import Ether
from scapy.packet import Raw
class TestMSSClamp(VppTestCase):
""" TCP MSS Clamping Test Case """
def setUp(self):
super(TestMSSClamp, self).setUp()
# create 2 pg interfaces
self.create_pg_interfaces(range(2))
for i in self.pg_interfaces:
i.admin_up()
i.config_ip4()
i.resolve_arp()
i.config_ip6()
i.resolve_ndp()
def tearDown(self):
for i in self.pg_interfaces:
i.unconfig_ip4()
i.unconfig_ip6()
i.admin_down()
super(TestMSSClamp, self).tearDown()
def verify_pkt(self, rx, expected_mss):
# check that the MSS size equals the expected value
# and the IP and TCP checksums are correct
tcp = rx[TCP]
tcp_csum = tcp.chksum
del tcp.chksum
ip_csum = 0
if (rx.haslayer(IP)):
ip_csum = rx[IP].chksum
del rx[IP].chksum
opt = tcp.options
self.assertEqual(opt[0][0], 'MSS')
self.assertEqual(opt[0][1], expected_mss)
# recalculate checksums
rx = rx.__class__(bytes(rx))
tcp = rx[TCP]
self.assertEqual(tcp_csum, tcp.chksum)
if (rx.haslayer(IP)):
self.assertEqual(ip_csum, rx[IP].chksum)
def send_and_verify_ip4(self, src_pg, dst_pg, mss, expected_mss):
# IPv4 TCP packet with the requested MSS option.
# from a host on src_pg to a host on dst_pg.
p = (Ether(dst=src_pg.local_mac,
src=src_pg.remote_mac) /
IP(src=src_pg.remote_ip4,
dst=dst_pg.remote_ip4) /
TCP(sport=1234, dport=1234,
flags="S",
options=[('MSS', (mss)), ('EOL', None)]) /
Raw('\xa5' * 100))
rxs = self.send_and_expect(src_pg, p * 65, dst_pg)
for rx in rxs:
self.verify_pkt(rx, expected_mss)
def send_and_verify_ip6(self, src_pg, dst_pg, mss, expected_mss):
#
# IPv6 TCP packet with the requested MSS option.
# from a host on src_pg to a host on dst_pg.
#
p = (Ether(dst=src_pg.local_mac,
src=src_pg.remote_mac) /
IPv6(src=src_pg.remote_ip6,
dst=dst_pg.remote_ip6) /
TCP(sport=1234, dport=1234,
flags="S",
options=[('MSS', (mss)), ('EOL', None)]) /
Raw('\xa5' * 100))
rxs = self.send_and_expect(src_pg, p * 65, dst_pg)
for rx in rxs:
self.verify_pkt(rx, expected_mss)
def test_tcp_mss_clamping_ip4_tx(self):
""" IP4 TCP MSS Clamping TX """
# enable the TCP MSS clamping feature to lower the MSS to 1424.
self.vapi.mss_clamp_enable_disable(self.pg1.sw_if_index,
ipv4_mss=1424, ipv6_mss=0,
ipv4_direction=3, ipv6_direction=0)
# Verify that the feature is enabled.
rv, reply = self.vapi.mss_clamp_get(sw_if_index=self.pg1.sw_if_index)
self.assertEqual(reply[0].ipv4_mss, 1424)
self.assertEqual(reply[0].ipv4_direction, 3)
# Send syn packets and verify that the MSS value is lowered.
self.send_and_verify_ip4(self.pg0, self.pg1, 1460, 1424)
# check the stats
stats = self.statistics.get_counter(
'/err/tcp-mss-clamping-ip4-out/clamped')
self.assertEqual(sum(stats), 65)
# Send syn packets with small enough MSS values and verify they are
# unchanged.
self.send_and_verify_ip4(self.pg0, self.pg1, 1400, 1400)
# enable the the feature only in TX direction
# and change the max MSS value
self.vapi.mss_clamp_enable_disable(self.pg1.sw_if_index,
ipv4_mss=1420, ipv6_mss=0,
ipv4_direction=2, ipv6_direction=0)
# Send syn packets and verify that the MSS value is lowered.
self.send_and_verify_ip4(self.pg0, self.pg1, 1460, 1420)
# enable the the feature only in RX direction
self.vapi.mss_clamp_enable_disable(self.pg1.sw_if_index,
ipv4_mss=1424, ipv6_mss=0,
ipv4_direction=1, ipv6_direction=0)
# Send the packets again and ensure they are unchanged.
self.send_and_verify_ip4(self.pg0, self.pg1, 1460, 1460)
# disable the feature
self.vapi.mss_clamp_enable_disable(self.pg1.sw_if_index,
ipv4_mss=0, ipv6_mss=0,
ipv4_direction=0, ipv6_direction=0)
# Send the packets again and ensure they are unchanged.
self.send_and_verify_ip4(self.pg0, self.pg1, 1460, 1460)
def test_tcp_mss_clamping_ip4_rx(self):
""" IP4 TCP MSS Clamping RX """
# enable the TCP MSS clamping feature to lower the MSS to 1424.
self.vapi.mss_clamp_enable_disable(self.pg1.sw_if_index,
ipv4_mss=1424, ipv6_mss=0,
ipv4_direction=3, ipv6_direction=0)
# Verify that the feature is enabled.
rv, reply = self.vapi.mss_clamp_get(sw_if_index=self.pg1.sw_if_index)
self.assertEqual(reply[0].ipv4_mss, 1424)
self.assertEqual(reply[0].ipv4_direction, 3)
# Send syn packets and verify that the MSS value is lowered.
self.send_and_verify_ip4(self.pg1, self.pg0, 1460, 1424)
# check the stats
stats = self.statistics.get_counter(
'/err/tcp-mss-clamping-ip4-in/clamped')
self.assertEqual(sum(stats), 65)
# Send syn packets with small enough MSS values and verify they are
# unchanged.
self.send_and_verify_ip4(self.pg1, self.pg0, 1400, 1400)
# enable the the feature only in RX direction
# and change the max MSS value
self.vapi.mss_clamp_enable_disable(self.pg1.sw_if_index,
ipv4_mss=1420, ipv6_mss=0,
ipv4_direction=1, ipv6_direction=0)
# Send syn packets and verify that the MSS value is lowered.
self.send_and_verify_ip4(self.pg1, self.pg0, 1460, 1420)
# enable the the feature only in TX direction
self.vapi.mss_clamp_enable_disable(self.pg1.sw_if_index,
ipv4_mss=1424, ipv6_mss=0,
ipv4_direction=2, ipv6_direction=0)
# Send the packets again and ensure they are unchanged.
self.send_and_verify_ip4(self.pg1, self.pg0, 1460, 1460)
# disable the feature
self.vapi.mss_clamp_enable_disable(self.pg1.sw_if_index,
ipv4_mss=0, ipv6_mss=0,
ipv4_direction=0, ipv6_direction=0)
# Send the packets again and ensure they are unchanged.
self.send_and_verify_ip4(self.pg1, self.pg0, 1460, 1460)
def test_tcp_mss_clamping_ip6_tx(self):
""" IP6 TCP MSS Clamping TX """
# enable the TCP MSS clamping feature to lower the MSS to 1424.
self.vapi.mss_clamp_enable_disable(self.pg1.sw_if_index,
ipv4_mss=0, ipv6_mss=1424,
ipv4_direction=0, ipv6_direction=3)
# Verify that the feature is enabled.
rv, reply = self.vapi.mss_clamp_get(sw_if_index=self.pg1.sw_if_index)
self.assertEqual(reply[0].ipv6_mss, 1424)
self.assertEqual(reply[0].ipv6_direction, 3)
# Send syn packets and verify that the MSS value is lowered.
self.send_and_verify_ip6(self.pg0, self.pg1, 1460, 1424)
# check the stats
stats = self.statistics.get_counter(
'/err/tcp-mss-clamping-ip6-out/clamped')
self.assertEqual(sum(stats), 65)
# Send syn packets with small enough MSS values and verify they are
# unchanged.
self.send_and_verify_ip6(self.pg0, self.pg1, 1400, 1400)
# enable the the feature only in TX direction
# and change the max MSS value
self.vapi.mss_clamp_enable_disable(self.pg1.sw_if_index,
ipv4_mss=0, ipv6_mss=1420,
ipv4_direction=0, ipv6_direction=2)
# Send syn packets and verify that the MSS value is lowered.
self.send_and_verify_ip6(self.pg0, self.pg1, 1460, 1420)
# enable the the feature only in RX direction
self.vapi.mss_clamp_enable_disable(self.pg1.sw_if_index,
ipv4_mss=0, ipv6_mss=1424,
ipv4_direction=0, ipv6_direction=1)
# Send the packets again and ensure they are unchanged.
self.send_and_verify_ip6(self.pg0, self.pg1, 1460, 1460)
# disable the feature
self.vapi.mss_clamp_enable_disable(self.pg1.sw_if_index,
ipv4_mss=0, ipv6_mss=0,
ipv4_direction=0, ipv6_direction=0)
# Send the packets again and ensure they are unchanged.
self.send_and_verify_ip6(self.pg0, self.pg1, 1460, 1460)
def test_tcp_mss_clamping_ip6_rx(self):
""" IP6 TCP MSS Clamping RX """
# enable the TCP MSS clamping feature to lower the MSS to 1424.
self.vapi.mss_clamp_enable_disable(self.pg1.sw_if_index,
ipv4_mss=0, ipv6_mss=1424,
ipv4_direction=0, ipv6_direction=3)
# Verify that the feature is enabled.
rv, reply = self.vapi.mss_clamp_get(sw_if_index=self.pg1.sw_if_index)
self.assertEqual(reply[0].ipv6_mss, 1424)
self.assertEqual(reply[0].ipv6_direction, 3)
# Send syn packets and verify that the MSS value is lowered.
self.send_and_verify_ip6(self.pg1, self.pg0, 1460, 1424)
# check the stats
stats = self.statistics.get_counter(
'/err/tcp-mss-clamping-ip6-in/clamped')
self.assertEqual(sum(stats), 65)
# Send syn packets with small enough MSS values and verify they are
# unchanged.
self.send_and_verify_ip6(self.pg1, self.pg0, 1400, 1400)
# enable the the feature only in RX direction
# and change the max MSS value
self.vapi.mss_clamp_enable_disable(self.pg1.sw_if_index,
ipv4_mss=0, ipv6_mss=1420,
ipv4_direction=0, ipv6_direction=1)
# Send syn packets and verify that the MSS value is lowered.
self.send_and_verify_ip6(self.pg1, self.pg0, 1460, 1420)
# enable the the feature only in TX direction
self.vapi.mss_clamp_enable_disable(self.pg1.sw_if_index,
ipv4_mss=0, ipv6_mss=1424,
ipv4_direction=0, ipv6_direction=2)
# Send the packets again and ensure they are unchanged.
self.send_and_verify_ip6(self.pg1, self.pg0, 1460, 1460)
# disable the feature
self.vapi.mss_clamp_enable_disable(self.pg1.sw_if_index,
ipv4_mss=0, ipv6_mss=0,
ipv4_direction=0, ipv6_direction=0)
# Send the packets again and ensure they are unchanged.
self.send_and_verify_ip6(self.pg1, self.pg0, 1460, 1460)
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)