From e9ac22fb8c398a2d5899c815c7ccec919ae6c725 Mon Sep 17 00:00:00 2001 From: Craig Pratt Date: Wed, 16 Feb 2022 10:54:39 -0800 Subject: [PATCH] Added MTU support to micronets/devices and a NetReach agent config variable (#80) In order to support tunneling inter-AP traffic over vxlans on a network with 1500-byte MTUs the MTU that NetReach devices connect with needs to be reduced so the addition of the vxlan headers doesn't exceed the 1500-byte limit. The DHCP "Interface MTU Option" is supposed to accomplish this proactively - and avoid having to resort to Path MTU Discovery - which can cause some latency during connection establishment. This change adds support for an (optional) "mtu" field to both micronet and device definitions. And the dnsmasq adapter will now pick this up and set the DHCP "Interface MTU Option" (option 26) accordingly at the subnet level (for micronets) and/or the device level. Tested this with NetReach inter-AP tunnels. The latency that was occurring to perform inter-AP MTU path discovery is gone and iperf3 tests show no loss of frames. --- micronets-gw-service/app/dnsmasq_adapter.py | 4 ++++ micronets-gw-service/app/gateway_service_api.py | 7 +++++-- micronets-gw-service/app/netreach_adapter.py | 4 ++++ micronets-gw-service/config.py | 1 + 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/micronets-gw-service/app/dnsmasq_adapter.py b/micronets-gw-service/app/dnsmasq_adapter.py index 6c81e88..e2f75ab 100644 --- a/micronets-gw-service/app/dnsmasq_adapter.py +++ b/micronets-gw-service/app/dnsmasq_adapter.py @@ -64,6 +64,8 @@ def write_micronets (self, outfile, micronets): dns_server += "," + server outfile.write ("dhcp-option=tag:{}, option:dns-server{}\n" .format (micronet_id, dns_server)) + if 'mtu' in micronet: + outfile.write (f"dhcp-option=tag:{micronet_id}, option:mtu,{micronet['mtu']}\n") outfile.write ("\n") def write_devices (self, outfile, devices): @@ -85,4 +87,6 @@ def write_devices (self, outfile, devices): outfile.write (f"\n# Device: {device_id}/(\"{device_name}\")\n") outfile.write ("dhcp-host={},{},set:{},{},{}\n" .format (mac_addr, short_device_id, device_id, ip_addr, lease_period)) + if 'mtu' in device: + outfile.write (f"dhcp-option=tag:{device_id}, option:mtu,{device['mtu']}\n") outfile.write ("\n") diff --git a/micronets-gw-service/app/gateway_service_api.py b/micronets-gw-service/app/gateway_service_api.py index 638a689..63111c5 100644 --- a/micronets-gw-service/app/gateway_service_api.py +++ b/micronets-gw-service/app/gateway_service_api.py @@ -131,7 +131,8 @@ async def get_interfaces (): return await get_conf_model().get_interfaces(medium=medium_param) def check_micronet (micronet, micronet_id=None, required=True): - check_for_unrecognized_entries (micronet, ['micronetId','ipv4Network','nameservers','interface','vlan','name']) + check_for_unrecognized_entries (micronet, ['micronetId', 'ipv4Network', 'nameservers', 'interface', 'vlan', + 'name', 'mtu']) body_micronet_id = check_field (micronet, 'micronetId', str, required) if micronet_id and body_micronet_id: if micronet_id != body_micronet_id: @@ -146,6 +147,7 @@ def check_micronet (micronet, micronet_id=None, required=True): check_field (micronet, 'interface', str, required) check_vlan (micronet, 'vlan', False) # Optional check_field (micronet, 'name', str, False) + check_field (micronet, 'mtu', int, False) def check_micronets (micronets, required): for micronet in micronets: @@ -318,7 +320,7 @@ def check_portspec (container, field_name, required): async def check_device (device, required): check_for_unrecognized_entries (device, ['deviceId', 'macAddress', 'networkAddress', 'psk', 'outRules', 'inRules', - 'allowHosts','denyHosts','name']) + 'allowHosts','denyHosts','name','mtu']) device_id = check_field (device, 'deviceId', str, required) if device_id: device_id = device_id.lower () @@ -347,6 +349,7 @@ async def check_device (device, required): await check_hostspecs (device, 'allowHosts', False) await check_hostspecs (device, 'denyHosts', False) check_field (device, 'name', str, False) + check_field (device, 'mtu', int, False) async def check_devices (devices, required): for device in devices: diff --git a/micronets-gw-service/app/netreach_adapter.py b/micronets-gw-service/app/netreach_adapter.py index 333a513..29e055c 100644 --- a/micronets-gw-service/app/netreach_adapter.py +++ b/micronets-gw-service/app/netreach_adapter.py @@ -54,6 +54,7 @@ def __init__ (self, config): self.use_device_pass = bool(config.get('NETREACH_ADAPTER_USE_DEVICE_PASS', "False")) self.psk_cache_enabled = bool(config.get('NETREACH_ADAPTER_PSK_CACHE_ENABLED', "True")) self.psk_cache_expire_s = config.get('NETREACH_ADAPTER_PSK_CACHE_EXPIRE_S', 120) + self.device_mtu = config.get('NETREACH_ADAPTER_DEVICE_MTU', 0) self.tunnel_man = NetreachApNetworkManager(config, self) self.api_token = None self.api_token_refresh = None @@ -445,6 +446,9 @@ async def _setup_micronets_for_ap(self, service_list, service_device_list): "nameservers": [micronet_gateway] } } + + if self.device_mtu: + micronet_to_add['micronet']['mtu'] = self.device_mtu logger.info(f"NetreachAdapter:_setup_micronets_for_ap: micronet: {json.dumps(micronet_to_add, indent=4)}") result = await micronets_api.post(f"{self.micronets_api_prefix}/micronets", json=micronet_to_add) diff --git a/micronets-gw-service/config.py b/micronets-gw-service/config.py index 02a7903..51a8f32 100644 --- a/micronets-gw-service/config.py +++ b/micronets-gw-service/config.py @@ -80,6 +80,7 @@ class NetreachDefaultSettings(): "options:remote_ip={remote_vxlan_host} " \ "options:key={vxlan_conn_key}" NETREACH_ADAPTER_VXLAN_DISCONNECT_CMD = "/usr/bin/ovs-vsctl del-port {vxlan_port_name}" + NETREACH_ADAPTER_DEVICE_MTU = 1430 # # Configure settings for local/development testing