Skip to content

Commit

Permalink
Install Iptables rules to set TCPMSS for 'lo' interface (#3452)
Browse files Browse the repository at this point in the history
* Install Iptables rules to set TCPMSS for lo interface
* Moved implementation to hostcfgd to maintain at one place
  • Loading branch information
prsunny authored Sep 18, 2019
1 parent 3c0b56a commit 8ca1eb2
Showing 1 changed file with 92 additions and 0 deletions.
92 changes: 92 additions & 0 deletions files/image_config/hostcfgd/hostcfgd
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import subprocess
import syslog
import copy
import jinja2
import ipaddr as ipaddress
from swsssdk import ConfigDBConnector

# FILE
Expand Down Expand Up @@ -49,6 +50,82 @@ def obfuscate(data):
else:
return data

class Iptables(object):
def __init__(self):
'''
Default MSS to 1460 - (MTU 1500 - 40 (TCP/IP Overhead))
For IPv6, it would be 1440 - (MTU 1500 - 60 octects)
'''
self.tcpmss = 1460
self.tcp6mss = 1440

def is_ip_prefix_in_key(self, key):
'''
Function to check if IP address is present in the key. If it
is present, then the key would be a tuple or else, it shall be
be string
'''
return (isinstance(key, tuple))

def load(self, lpbk_table):
for row in lpbk_table:
self.iptables_handler(row, lpbk_table[row])

def command(self, chain, ip, ver, op):
cmd = 'iptables' if ver == '4' else 'ip6tables'
cmd += ' -t mangle --{} {} -p tcp --tcp-flags SYN SYN'.format(op, chain)
cmd += ' -d' if chain == 'PREROUTING' else ' -s'
mss = self.tcpmss if ver == '4' else self.tcp6mss
cmd += ' {} -j TCPMSS --set-mss {}'.format(ip, mss)

return cmd

def iptables_handler(self, key, data, add=True):
if not self.is_ip_prefix_in_key(key):
return

iface, ip = key
ip_str = ip.split("/")[0]
ip_addr = ipaddress.IPAddress(ip_str)
if isinstance(ip_addr, ipaddress.IPv6Address):
ver = '6'
else:
ver = '4'

self.mangle_handler(ip_str, ver, add)

def mangle_handler(self, ip, ver, add):
if not add:
op = 'delete'
else:
op = 'check'

iptables_cmds = []
chains = ['PREROUTING', 'POSTROUTING']
for chain in chains:
cmd = self.command(chain, ip, ver, op)
if not add:
iptables_cmds.append(cmd)
else:
'''
For add case, first check if rule exists. Iptables just appends to the chain
as a new rule even if it is the same as an existing one. Check this and
do nothing if rule exists
'''
ret = subprocess.call(cmd, shell=True)
if ret == 0:
syslog.syslog(syslog.LOG_INFO, "{} rule exists in {}".format(ip, chain))
else:
# Modify command from Check to Append
iptables_cmds.append(cmd.replace("check", "append"))

for cmd in iptables_cmds:
syslog.syslog(syslog.LOG_INFO, "Running cmd - {}".format(cmd))
try:
subprocess.check_call(cmd, shell=True)
except subprocess.CalledProcessError as err:
syslog.syslog(syslog.LOG_ERR, "{} - failed: return code - {}, output:\n{}"
.format(err.cmd, err.returncode, err.output))

class AaaCfg(object):
def __init__(self):
Expand Down Expand Up @@ -159,6 +236,9 @@ class HostConfigDaemon:
self.aaacfg = AaaCfg()
self.aaacfg.load(aaa, tacacs_global, tacacs_server)
self.hostname_cache=""
lpbk_table = self.config_db.get_table('LOOPBACK_INTERFACE')
self.iptables = Iptables()
self.iptables.load(lpbk_table)

def aaa_handler(self, key, data):
self.aaacfg.aaa_update(key, data)
Expand Down Expand Up @@ -215,11 +295,23 @@ class HostConfigDaemon:

self.hostname_cache = hostname

def lpbk_handler(self, key, data):
key = ConfigDBConnector.deserialize_key(key)
#Check if delete operation by fetch existing keys
keys = self.config_db.get_keys('LOOPBACK_INTERFACE')
if key in keys:
add = True
else:
add = False

self.iptables.iptables_handler(key, data, add)

def start(self):
self.config_db.subscribe('AAA', lambda table, key, data: self.aaa_handler(key, data))
self.config_db.subscribe('TACPLUS_SERVER', lambda table, key, data: self.tacacs_server_handler(key, data))
self.config_db.subscribe('TACPLUS', lambda table, key, data: self.tacacs_global_handler(key, data))
self.config_db.subscribe('DEVICE_METADATA', lambda table, key, data: self.hostname_handler(key, data))
self.config_db.subscribe('LOOPBACK_INTERFACE', lambda table, key, data: self.lpbk_handler(key, data))
self.config_db.listen()


Expand Down

0 comments on commit 8ca1eb2

Please sign in to comment.