2020-06-24 08:36:26 +00:00
|
|
|
from .parameter import ExperienceParameter
|
2020-06-24 10:28:44 +00:00
|
|
|
from topos.multi_interface import MultiInterfaceTopo
|
2015-01-08 18:52:45 +00:00
|
|
|
|
2020-06-24 08:54:44 +00:00
|
|
|
class Experience(object):
|
2020-06-24 14:11:54 +00:00
|
|
|
"""
|
|
|
|
Base class to instantiate an experience to perform.
|
|
|
|
|
|
|
|
This class is not instantiable as it. You must define a child class with the
|
|
|
|
`NAME` attribute.
|
|
|
|
"""
|
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def __init__(self, xpParam, mpTopo, mpConfig):
|
|
|
|
self.xpParam = xpParam
|
|
|
|
self.mpTopo = mpTopo
|
|
|
|
self.mpConfig = mpConfig
|
|
|
|
print(self.xpParam)
|
2015-02-26 16:43:45 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def classicRun(self):
|
|
|
|
self.prepare()
|
|
|
|
self.run()
|
|
|
|
self.clean()
|
2015-02-26 16:43:45 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def prepare(self):
|
|
|
|
self.setupSysctl()
|
|
|
|
self.runUserspacePM()
|
|
|
|
self.mpConfig.configureNetwork()
|
|
|
|
self.changeMetric()
|
|
|
|
self.putPriorityOnPaths()
|
|
|
|
self.disableTSO()
|
|
|
|
self.runTcpDump()
|
|
|
|
self.runNetemAt()
|
|
|
|
pass
|
2015-01-08 18:52:45 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def changeMetric(self):
|
2020-06-24 08:36:26 +00:00
|
|
|
metric = self.xpParam.getParam(ExperienceParameter.METRIC)
|
2020-06-23 11:20:07 +00:00
|
|
|
if int(metric) >= 0:
|
|
|
|
self.mpTopo.notNSCommand("echo " + metric + " > /sys/module/mptcp_sched_metric/parameters/metric")
|
2016-06-21 15:31:17 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def putPriorityOnPaths(self):
|
2020-06-24 10:28:44 +00:00
|
|
|
# Only meaningful if mpTopo is instance of MultiInterfaceTopo
|
|
|
|
if isinstance(self.mpTopo, MultiInterfaceTopo):
|
2020-06-24 08:36:26 +00:00
|
|
|
prioPath0 = self.xpParam.getParam(ExperienceParameter.PRIOPATH0)
|
|
|
|
prioPath1 = self.xpParam.getParam(ExperienceParameter.PRIOPATH1)
|
2020-06-23 11:20:07 +00:00
|
|
|
if not prioPath0 == prioPath1:
|
|
|
|
self.mpTopo.commandTo(self.mpConfig.client, "/home/mininet/iproute/ip/ip link set dev " +
|
|
|
|
self.mpConfig.getClientInterface(0) + " priority " + str(prioPath0))
|
|
|
|
self.mpTopo.commandTo(self.mpConfig.router, "/home/mininet/iproute/ip/ip link set dev " +
|
|
|
|
self.mpConfig.getRouterInterfaceSwitch(0) + " priority " +
|
|
|
|
str(prioPath0))
|
|
|
|
self.mpTopo.commandTo(self.mpConfig.client, "/home/mininet/iproute/ip/ip link set dev " +
|
|
|
|
self.mpConfig.getClientInterface(1) + " priority " + str(prioPath1))
|
|
|
|
self.mpTopo.commandTo(self.mpConfig.router, "/home/mininet/iproute/ip/ip link set dev " +
|
|
|
|
self.mpConfig.getRouterInterfaceSwitch(1) + " priority " +
|
|
|
|
str(prioPath1))
|
2016-05-13 08:00:29 +00:00
|
|
|
|
2020-06-24 08:36:26 +00:00
|
|
|
backupPath0 = self.xpParam.getParam(ExperienceParameter.BACKUPPATH0)
|
2020-06-23 11:20:07 +00:00
|
|
|
if int(backupPath0) > 0:
|
|
|
|
self.mpTopo.commandTo(self.mpConfig.client, self.mpConfig.interfaceBUPCommand(self.mpConfig.getClientInterface(0)))
|
|
|
|
self.mpTopo.commandTo(self.mpConfig.router, self.mpConfig.interfaceBUPCommand(self.mpConfig.getRouterInterfaceSwitch(0)))
|
2020-06-24 08:36:26 +00:00
|
|
|
backupPath1 = self.xpParam.getParam(ExperienceParameter.BACKUPPATH1)
|
2020-06-23 11:20:07 +00:00
|
|
|
if int(backupPath1) > 0:
|
|
|
|
self.mpTopo.commandTo(self.mpConfig.client, self.mpConfig.interfaceBUPCommand(self.mpConfig.getClientInterface(1)))
|
|
|
|
self.mpTopo.commandTo(self.mpConfig.router, self.mpConfig.interfaceBUPCommand(self.mpConfig.getRouterInterfaceSwitch(1)))
|
2016-06-21 15:32:19 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def disableTSO(self):
|
|
|
|
links = self.mpTopo.getLinkCharacteristics()
|
|
|
|
i = 0
|
|
|
|
for l in links:
|
|
|
|
lname = self.mpConfig.getMidLeftName(i)
|
|
|
|
rname = self.mpConfig.getMidRightName(i)
|
|
|
|
lbox = self.mpTopo.getHost(lname)
|
|
|
|
lif = self.mpConfig.getMidL2RInterface(i)
|
|
|
|
rif = self.mpConfig.getMidR2LInterface(i)
|
|
|
|
rbox = self.mpTopo.getHost(rname)
|
|
|
|
print(str(lname) + " " + str(lif))
|
|
|
|
print(str(rname) + " " + str(rif))
|
|
|
|
print("boxes " + str(lbox) + " " + str(rbox))
|
|
|
|
cmd = "ethtool -K " + lif + " tso off"
|
|
|
|
print(cmd)
|
|
|
|
self.mpTopo.commandTo(lbox, cmd)
|
|
|
|
cmd = "ethtool -K " + rif + " tso off"
|
|
|
|
print(cmd)
|
|
|
|
self.mpTopo.commandTo(rbox, cmd)
|
|
|
|
i = i + 1
|
2017-05-09 08:36:01 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
# And for the server
|
|
|
|
cmd = "ethtool -K " + self.mpConfig.getServerInterface() + " tso off"
|
|
|
|
print(cmd)
|
|
|
|
self.mpTopo.commandTo(self.mpConfig.server, cmd)
|
2017-05-09 08:36:01 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
cmd = "ethtool -K " + self.mpConfig.getRouterInterfaceSwitch(self.mpConfig.getClientInterfaceCount()) + " tso off"
|
|
|
|
print(cmd)
|
|
|
|
self.mpTopo.commandTo(self.mpConfig.router, cmd)
|
2017-05-09 08:36:01 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def runUserspacePM(self):
|
2020-06-24 08:36:26 +00:00
|
|
|
if self.xpParam.getParam(ExperienceParameter.KERNELPMC) != "netlink":
|
2020-06-23 11:20:07 +00:00
|
|
|
print("Client : Error, I can't change the userspace pm if the kernel pm is not netlink !")
|
|
|
|
else:
|
2020-06-24 08:36:26 +00:00
|
|
|
upmc = self.xpParam.getParam(ExperienceParameter.USERPMC)
|
|
|
|
upmca = self.xpParam.getParam(ExperienceParameter.USERPMCARGS)
|
2020-06-23 11:20:07 +00:00
|
|
|
self.mpTopo.commandTo(self.mpConfig.client, upmc + \
|
|
|
|
" " + upmca + " &>upmc.log &")
|
2020-06-24 08:36:26 +00:00
|
|
|
if self.xpParam.getParam(ExperienceParameter.KERNELPMS) != "netlink":
|
2020-06-23 11:20:07 +00:00
|
|
|
print("Server : Error, I can't change the userspace pm if the kernel pm is not netlink !")
|
|
|
|
else:
|
2020-06-24 08:36:26 +00:00
|
|
|
upms = self.xpParam.getParam(ExperienceParameter.USERPMS)
|
|
|
|
upmsa = self.xpParam.getParam(ExperienceParameter.USERPMSARGS)
|
2020-06-23 11:20:07 +00:00
|
|
|
self.mpTopo.commandTo(self.mpConfig.server, upms + \
|
|
|
|
" " + upmsa + " &>upms.log &")
|
2015-02-23 11:26:32 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def cleanUserspacePM(self):
|
2020-06-24 08:36:26 +00:00
|
|
|
if self.xpParam.getParam(ExperienceParameter.KERNELPMC) != "netlink":
|
2020-06-23 11:20:07 +00:00
|
|
|
print("Client : Error, I can't change the userspace pm if the kernel pm is not netlink !")
|
|
|
|
else:
|
2020-06-24 08:36:26 +00:00
|
|
|
upmc = self.xpParam.getParam(ExperienceParameter.USERPMC)
|
2020-06-23 11:20:07 +00:00
|
|
|
self.mpTopo.commandTo(self.mpConfig.client, "killall " + upmc)
|
2020-06-24 08:36:26 +00:00
|
|
|
if self.xpParam.getParam(ExperienceParameter.KERNELPMS) != "netlink":
|
2020-06-23 11:20:07 +00:00
|
|
|
print("Server : Error, I can't change the userspace pm if the kernel pm is not netlink !")
|
|
|
|
else:
|
2020-06-24 08:36:26 +00:00
|
|
|
upms = self.xpParam.getParam(ExperienceParameter.USERPMS)
|
2020-06-23 11:20:07 +00:00
|
|
|
self.mpTopo.commandTo(self.mpConfig.server, "killall " + upms)
|
2015-02-23 11:26:32 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def runNetemAt(self):
|
|
|
|
if not self.mpTopo.changeNetem == "yes":
|
|
|
|
print("I don't need to change netem")
|
|
|
|
return
|
|
|
|
print("Will change netem config on the fly")
|
|
|
|
links = self.mpTopo.getLinkCharacteristics()
|
|
|
|
i = 0
|
|
|
|
for l in links:
|
|
|
|
lname = self.mpConfig.getMidLeftName(i)
|
|
|
|
rname = self.mpConfig.getMidRightName(i)
|
|
|
|
lbox = self.mpTopo.getHost(lname)
|
|
|
|
lif = self.mpConfig.getMidL2RInterface(i)
|
|
|
|
rif = self.mpConfig.getMidR2LInterface(i)
|
|
|
|
rbox = self.mpTopo.getHost(rname)
|
|
|
|
print(str(lname) + " " + str(lif))
|
|
|
|
print(str(rname) + " " + str(rif))
|
|
|
|
print("boxes " + str(lbox) + " " + str(rbox))
|
|
|
|
cmd = l.buildBwCmd(lif)
|
|
|
|
print(cmd)
|
|
|
|
self.mpTopo.commandTo(lbox, cmd)
|
|
|
|
cmd = l.buildBwCmd(rif)
|
|
|
|
print(cmd)
|
|
|
|
self.mpTopo.commandTo(rbox, cmd)
|
|
|
|
ilif = self.mpConfig.getMidL2RIncomingInterface(i)
|
|
|
|
irif = self.mpConfig.getMidR2LIncomingInterface(i)
|
|
|
|
cmd = l.buildPolicingCmd(ilif)
|
|
|
|
print(cmd)
|
|
|
|
self.mpTopo.commandTo(lbox, cmd)
|
|
|
|
cmd = l.buildPolicingCmd(irif)
|
|
|
|
print(cmd)
|
|
|
|
self.mpTopo.commandTo(rbox, cmd)
|
|
|
|
cmd = l.buildNetemCmd(irif)
|
|
|
|
print(cmd)
|
|
|
|
self.mpTopo.commandTo(rbox, cmd)
|
|
|
|
cmd = l.buildNetemCmd(ilif)
|
|
|
|
print(cmd)
|
|
|
|
self.mpTopo.commandTo(lbox, cmd)
|
2019-11-28 08:32:49 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
i = i + 1
|
2015-01-20 10:04:36 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def run(self):
|
|
|
|
pass
|
2015-01-08 18:52:45 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def clean(self):
|
|
|
|
self.mpTopo.commandTo(self.mpConfig.client,
|
|
|
|
"killall tcpdump")
|
|
|
|
self.mpTopo.commandTo(self.mpConfig.server,
|
|
|
|
"killall tcpdump")
|
|
|
|
self.backUpSysctl()
|
|
|
|
self.cleanUserspacePM()
|
|
|
|
pass
|
2015-01-08 18:52:45 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def setupSysctl(self):
|
|
|
|
self.saveSysctl()
|
|
|
|
self.writeSysctl()
|
2015-01-14 14:19:39 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def saveSysctl(self):
|
|
|
|
self.sysctlBUP = {}
|
2020-06-24 08:36:26 +00:00
|
|
|
self._saveSysctl(ExperienceParameter.sysctlKey, self.sysctlBUP)
|
2020-06-23 11:20:07 +00:00
|
|
|
self.sysctlBUPC = {}
|
2020-06-24 08:36:26 +00:00
|
|
|
self._saveSysctl(ExperienceParameter.sysctlKeyClient, self.sysctlBUPC,
|
2020-06-23 11:20:07 +00:00
|
|
|
ns = True, who = self.mpConfig.client)
|
|
|
|
self.sysctlBUPS = {}
|
2020-06-24 08:36:26 +00:00
|
|
|
self._saveSysctl(ExperienceParameter.sysctlKeyServer, self.sysctlBUPS,
|
2020-06-23 11:20:07 +00:00
|
|
|
ns = True, who = self.mpConfig.server)
|
2015-02-23 10:32:22 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def _saveSysctl(self, sysctlDic, sysctlBUP, ns = False, who = None):
|
|
|
|
for k in sysctlDic:
|
|
|
|
sysctlKey = sysctlDic[k]
|
|
|
|
cmd = self.cmdReadSysctl(sysctlKey)
|
|
|
|
if not ns:
|
|
|
|
val = self.mpTopo.notNSCommand(cmd)
|
|
|
|
else:
|
|
|
|
val = self.mpTopo.commandTo(who, cmd)
|
|
|
|
if val == "Error":
|
|
|
|
print("oooops can't get sysctl " + sysctlKey)
|
|
|
|
else:
|
2020-06-23 11:23:27 +00:00
|
|
|
# For Python3 compatibility
|
|
|
|
if type(val) is bytes:
|
|
|
|
val = val.decode()
|
2020-06-23 11:20:07 +00:00
|
|
|
sysctlBUP[k] = val.split(" ",2)[2][:-1]
|
2015-02-23 10:32:22 +00:00
|
|
|
|
2015-01-14 14:19:39 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def cmdReadSysctl(self, key):
|
|
|
|
s = "sysctl " + key
|
|
|
|
return s
|
2015-01-14 14:19:39 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def cmdWriteSysctl(self, key, value):
|
|
|
|
s = self.cmdReadSysctl(key)
|
|
|
|
s = s + "=\"" + str(value) + "\""
|
|
|
|
return s
|
2015-01-14 14:19:39 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def writeSysctl(self):
|
2020-06-24 08:36:26 +00:00
|
|
|
self._writeSysctl(ExperienceParameter.sysctlKey, self.sysctlBUP)
|
|
|
|
self._writeSysctl(ExperienceParameter.sysctlKeyClient, self.sysctlBUPC,
|
2020-06-23 11:20:07 +00:00
|
|
|
ns = True, who = self.mpConfig.client)
|
2020-06-24 08:36:26 +00:00
|
|
|
self._writeSysctl(ExperienceParameter.sysctlKeyServer, self.sysctlBUPS,
|
2020-06-23 11:20:07 +00:00
|
|
|
ns = True, who = self.mpConfig.server)
|
2015-02-23 10:32:22 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def _writeSysctl(self, sysctlDic, sysctlBUP, ns = False, who = None):
|
|
|
|
for k in sysctlBUP:
|
|
|
|
sysctlKey = sysctlDic[k]
|
|
|
|
sysctlValue = self.xpParam.getParam(k)
|
|
|
|
cmd = self.cmdWriteSysctl(sysctlKey,sysctlValue)
|
|
|
|
if not ns:
|
|
|
|
val = self.mpTopo.notNSCommand(cmd)
|
|
|
|
else:
|
|
|
|
val = self.mpTopo.commandTo(who, cmd)
|
|
|
|
if val == "Error":
|
|
|
|
print("oooops can't set sysctl " + sysctlKey)
|
2015-01-14 14:19:39 +00:00
|
|
|
|
2015-02-23 10:32:22 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def backUpSysctl(self):
|
2020-06-24 08:36:26 +00:00
|
|
|
self._backUpSysctl(ExperienceParameter.sysctlKey, self.sysctlBUP)
|
|
|
|
self._backUpSysctl(ExperienceParameter.sysctlKeyClient, self.sysctlBUPC,
|
2020-06-23 11:20:07 +00:00
|
|
|
ns = True, who = self.mpConfig.client)
|
2020-06-24 08:36:26 +00:00
|
|
|
self._backUpSysctl(ExperienceParameter.sysctlKeyServer, self.sysctlBUPS,
|
2020-06-23 11:20:07 +00:00
|
|
|
ns = True, who = self.mpConfig.server)
|
2015-02-23 10:32:22 +00:00
|
|
|
|
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def _backUpSysctl(self, sysctlDic, sysctlBUP, ns = False, who = None):
|
|
|
|
for k in sysctlBUP:
|
|
|
|
sysctlKey = sysctlDic[k]
|
|
|
|
sysctlValue = sysctlBUP[k]
|
|
|
|
cmd = self.cmdWriteSysctl(sysctlKey,sysctlValue)
|
|
|
|
if not ns:
|
|
|
|
val = self.mpTopo.notNSCommand(cmd)
|
|
|
|
else:
|
|
|
|
val = self.mpTopo.commandTo(who, cmd)
|
2015-02-23 10:32:22 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
if val == "Error":
|
|
|
|
print("oooops can't set sysctl " + sysctlKey)
|
2015-01-14 14:19:39 +00:00
|
|
|
|
2015-02-23 10:32:22 +00:00
|
|
|
|
2020-06-23 11:20:07 +00:00
|
|
|
def runTcpDump(self):
|
|
|
|
#todo : replace filename by cst
|
2020-06-24 08:36:26 +00:00
|
|
|
cpcap = self.xpParam.getParam(ExperienceParameter.CLIENTPCAP)
|
|
|
|
spcap = self.xpParam.getParam(ExperienceParameter.SERVERPCAP)
|
|
|
|
snaplenpcap = self.xpParam.getParam(ExperienceParameter.SNAPLENPCAP)
|
2020-06-23 11:20:07 +00:00
|
|
|
if cpcap == "yes" :
|
|
|
|
self.mpTopo.commandTo(self.mpConfig.client,
|
|
|
|
"tcpdump -i any -s " + snaplenpcap + " -w client.pcap &")
|
|
|
|
if spcap == "yes" :
|
|
|
|
self.mpTopo.commandTo(self.mpConfig.server,
|
|
|
|
"tcpdump -i any -s " + snaplenpcap + " -w server.pcap &")
|
|
|
|
if spcap == "yes" or cpcap == "yes":
|
|
|
|
self.mpTopo.commandTo(self.mpConfig.client,"sleep 5")
|