diff --git a/src/conf/topo/3_ecmp_2 b/src/conf/topo/3_ecmp_2 index 7d73017..ca2b504 100644 --- a/src/conf/topo/3_ecmp_2 +++ b/src/conf/topo/3_ecmp_2 @@ -7,3 +7,9 @@ error path_0:10,10,5 path_1:100,20,5 topoType:ECMPLike +# change tc during an experiment +changeNetem:yes +#netem_{path_id}:at,cmd +netemAt_0:2,delay 100ms +netemAt_0:5,delay 2ms + diff --git a/src/mpConfig.py b/src/mpConfig.py index 05002f3..17d1642 100644 --- a/src/mpConfig.py +++ b/src/mpConfig.py @@ -6,6 +6,32 @@ class MpConfig: self.topo = topo self.param = param + def configureNetwork(self): + print("Configure interfaces....Generic call ?") + self.configureInterfaces() + self.configureRoute() + + def getMidL2RInterface(self, id): + "get Middle link, left to right interface" + pass + + def getMidR2LInterface(self, id): + pass + + def getMidLeftName(self, i): + "get Middle link, left box name" + pass + + def getMidRightName(self, i): + pass + + def configureInterfaces(self): + pass + + def configureNetwork(self): + pass + + def getClientInterfaceCount(self): raise Exception("To be implemented") diff --git a/src/mpECMPSingleInterfaceConfig.py b/src/mpECMPSingleInterfaceConfig.py index c211152..aa77c64 100644 --- a/src/mpECMPSingleInterfaceConfig.py +++ b/src/mpECMPSingleInterfaceConfig.py @@ -8,10 +8,6 @@ class MpECMPSingleInterfaceConfig(MpConfig): def __init__(self, topo, param): MpConfig.__init__(self, topo, param) - def configureNetwork(self): - self.configureInterfaces() - self.configureRoute() - def configureRoute(self): i = 0 mask = len(self.topo.routers) - 1 diff --git a/src/mpExperience.py b/src/mpExperience.py index 7cafaac..1306508 100644 --- a/src/mpExperience.py +++ b/src/mpExperience.py @@ -19,6 +19,15 @@ class MpExperience: self.runTcpDump() pass + def runNetemAt(self): + if not self.mpTopo.changeNetem == "yes": + return + print("Will change netem config on the fly") + links = self.mpTopo.getLinkCharacteristics() + for l in links: + cmd = l.buildNetemCmd() + print(cmd) + def run(self): pass diff --git a/src/mpLinkCharacteristics.py b/src/mpLinkCharacteristics.py index b57b1ac..d50e0c4 100644 --- a/src/mpLinkCharacteristics.py +++ b/src/mpLinkCharacteristics.py @@ -7,7 +7,29 @@ class MpLinkCharacteristics: self.delay = delay self.queueSize = queueSize self.bandwidth = bandwidth + self.netemAt = [] + + def addNetemAt(self, n): + if len(self.netemAt) == 0: + n.delay = n.at + self.netemAt.append(n) + else: + if n.at > self.netemAt[-1].at: + n.delta = n.at - self.netemAt[-1].at + self.netemAt.append(n) + else: + print("Do not take into account " + n.__str__() + \ + "because ooo !") + pass + def buildNetemCmd(self): + cmd = "" + for n in self.netemAt: + cmd = cmd + "sleep " + str(n.delta) + cmd = cmd + " && " + cmd = cmd + " echo " + n.cmd + " && " + cmd = cmd + " true &" + def asDict(self): d = {} d['bw'] = int(self.bandwidth) @@ -19,6 +41,8 @@ class MpLinkCharacteristics: s = "Link id : " + str(self.id) + "\n" s = s + "\tDelay : " + str(self.delay) + "\n" s = s + "\tQueue Size : " + str(self.queueSize) + "\n" - s = s + "\tBandwidth : " + str(self.bandwidth) + s = s + "\tBandwidth : " + str(self.bandwidth) + "\n" + for l in self.netemAt: + s = s + "\t" + l.__str__() + "\n" return s diff --git a/src/mpMultiInterfaceConfig.py b/src/mpMultiInterfaceConfig.py index 4cb89e8..8305cff 100644 --- a/src/mpMultiInterfaceConfig.py +++ b/src/mpMultiInterfaceConfig.py @@ -7,10 +7,6 @@ class MpMultiInterfaceConfig(MpConfig): def __init__(self, topo, param): MpConfig.__init__(self, topo, param) - def configureNetwork(self): - self.configureInterfaces() - self.configureRoute() - def configureRoute(self): i = 0 for l in self.topo.switch: @@ -36,6 +32,7 @@ class MpMultiInterfaceConfig(MpConfig): def configureInterfaces(self): + print("Configure interfaces for multi inf") self.client = self.topo.getHost(MpTopo.clientName) self.server = self.topo.getHost(MpTopo.serverName) self.router = self.topo.getHost(MpTopo.routerName) @@ -101,3 +98,14 @@ class MpMultiInterfaceConfig(MpConfig): def getServerInterface(self): return MpTopo.serverName + "-eth0" + def getMidLeftName(self, id): + return MpTopo.switchNamePrefix + str(id) + + def getMidRightName(self, id): + return MpTopo.routerName + + def getMidL2RInterface(self, id): + return self.getMidLeftName(id) + "-eth1" + + def getMidR2LInterface(self, id): + return self.getMidRightName(id) + "-eth" + str(id) diff --git a/src/mpNetemAt.py b/src/mpNetemAt.py new file mode 100644 index 0000000..bbbdeaa --- /dev/null +++ b/src/mpNetemAt.py @@ -0,0 +1,9 @@ +class MpNetemAt: + def __init__(self, at, cmd): + self.at = at + self.cmd = cmd + self.delta = 0 + + def __str__(self): + return "Netem... at " + str(self.at) + "(" + str(self.delta) + \ + ") will be " + self.cmd diff --git a/src/mpParam.py b/src/mpParam.py index 6b5dcdd..e761c01 100644 --- a/src/mpParam.py +++ b/src/mpParam.py @@ -18,7 +18,15 @@ class MpParam: tab = l.split(":") if len(tab) == 2: - self.paramDic[tab[0]] = tab[1][:-1] + k = tab[0] + val = tab[1][:-1] + if k in self.paramDic: + tmp = self.paramDic[k] + self.paramDic[k] = [] + self.paramDic[k].append(tmp) + self.paramDic[k].append(val) + else: + self.paramDic[k] = val else: print("Ignored Line " + str(i)) print(l), diff --git a/src/mpParamTopo.py b/src/mpParamTopo.py index b8e533e..6b07860 100644 --- a/src/mpParamTopo.py +++ b/src/mpParamTopo.py @@ -1,17 +1,47 @@ from mpLinkCharacteristics import MpLinkCharacteristics from mpParam import MpParam +from mpNetemAt import MpNetemAt class MpParamTopo(MpParam): LSUBNET = "leftSubnet" RSUBNET = "rightSubnet" + netemAt = "netemAt_" + changeNetem = "changeNetem" defaultValue = {} defaultValue[LSUBNET] = "10.1." defaultValue[RSUBNET] = "10.2." + defaultValue[changeNetem] = "false" def __init__(self, paramFile): MpParam.__init__(self, paramFile) self.linkCharacteristics = [] self.loadLinkCharacteristics() + self.loadNetemAt() + print(self.__str__()) + + def loadNetemAt(self): + if not self.getParam(MpParamTopo.changeNetem) == "yes": + return + for k in sorted(self.paramDic): + if k.startswith(MpParamTopo.netemAt): + i = int(k[len(MpParamTopo.netemAt):]) + val = self.paramDic[k] + if not isinstance(val, list): + val = list(val) + self.loadNetemAtList(i, val) + + def loadNetemAtList(self, id, nlist): + for n in nlist: + tab = n.split(",") + if len(tab)==2: + o = MpNetemAt(float(tab[0]), tab[1]) + if id < len(self.linkCharacteristics): + self.linkCharacteristics[id].addNetemAt(o) + else: + print("Error can't set netem for link " + str(id)) + else: + print("Netem wrong line : " + n) + print(self.linkCharacteristics[id].netemAt) def loadLinkCharacteristics(self): i = 0 @@ -31,7 +61,7 @@ class MpParamTopo(MpParam): val = MpParam.getParam(self, key) if val is None: if key in MpParamTopo.defaultValue: - return MpParamTopo[key] + return MpParamTopo.defaultValue[key] else: raise Exception("Param not found " + key) else: diff --git a/src/mpTopo.py b/src/mpTopo.py index a6d4e4a..318ed76 100644 --- a/src/mpTopo.py +++ b/src/mpTopo.py @@ -1,3 +1,5 @@ +from mpParamTopo import MpParamTopo + class MpTopo: mininetBuilder = "mininet" multiIfTopo = "MultiIf" @@ -14,8 +16,12 @@ class MpTopo: def __init__(self, topoBuilder, topoParam): self.topoBuilder = topoBuilder self.topoParam = topoParam + self.changeNetem = topoParam.getParam(MpParamTopo.changeNetem) self.logFile = open(MpTopo.cmdLog, 'w') - + + def getLinkCharacteristics(self): + return topoParam.linkCharacteristics() + def commandTo(self, who, cmd): self.logFile.write(who.__str__() + " : " + cmd + "\n") self.topoBuilder.commandTo(who, cmd)