diff --git a/config/xp/ab b/config/xp/ab new file mode 100644 index 0000000..9780b4b --- /dev/null +++ b/config/xp/ab @@ -0,0 +1 @@ +xpType:ab diff --git a/core/experience.py b/core/experience.py index 80485ab..8b35b77 100644 --- a/core/experience.py +++ b/core/experience.py @@ -1,6 +1,155 @@ -from .parameter import ExperienceParameter +from .parameter import Parameter from topos.multi_interface import MultiInterfaceTopo +class ExperienceParameter(Parameter): + """ + Handler for experience parameters stored in configuration files + """ + RMEM = "rmem" + WMEM = "wmem" + SCHED = "sched" + CC = "congctrl" + AUTOCORK = "autocork" + EARLYRETRANS = "earlyRetrans" + KERNELPM = "kpm" + KERNELPMC = "kpmc" #kernel path manager client / server + KERNELPMS = "kpms" + USERPMC = "upmc" + USERPMS = "upms" #userspace path manager client / server + USERPMCARGS = "upmc_args" + USERPMSARGS = "upms_args" + CLIENTPCAP = "clientPcap" + SERVERPCAP = "serverPcap" + SNAPLENPCAP = "snaplenPcap" + XPTYPE = "xpType" + PINGCOUNT = "pingCount" + NETPERFTESTLEN = "netperfTestlen" + NETPERFTESTNAME = "netperfTestname" + NETPERFREQRESSIZE = "netperfReqresSize" + + SIRIRUNTIME = "siriRunTime" + SIRIQUERYSIZE = "siriQuerySize" + SIRIRESPONSESIZE = "siriResponseSize" + SIRIDELAYQUERYRESPONSE = "siriDelayQueryResponse" + SIRIMINPAYLOADSIZE = "siriMinPayloadSize" + SIRIMAXPAYLOADSIZE = "siriMaxPayloadSize" + SIRIINTERVALTIMEMS = "siriIntervalTimeMs" + SIRIBUFFERSIZE = "siriBufferSize" + SIRIBURSTSIZE = "siriBurstSize" + SIRIINTERVALBURSTTIMEMS = "siriIntervalBurstTimeMs" + VLCFILE = "vlcFile" + VLCTIME = "vlcTime" + DITGKBYTES = "ditgKBytes" + DITGCONSTANTPACKETSIZE = "ditgConstantPacketSize" + DITGMEANPOISSONPACKETSSEC = "ditgMeanPoissonPacketsSec" + DITGCONSTANTPACKETSSEC = "ditgConstantPacketsSec" + DITGBURSTSONPACKETSSEC = "ditgBurstsOnPacketsSec" + DITGBURSTSOFFPACKETSSEC = "ditgBurstsOffPacketsSec" + MSGCLIENTSLEEP = "msgClientSleep" + MSGSERVERSLEEP = "msgServerSleep" + MSGNBREQUESTS = "msgNbRequests" + MSGBYTES = "msgBytes" + QUICMULTIPATH = "quicMultipath" + QUICSIRIRUNTIME = "quicSiriRunTime" + PRIOPATH0 = "prioPath0" + PRIOPATH1 = "prioPath1" + BACKUPPATH0 = "backupPath0" + BACKUPPATH1 = "backupPath1" + EXPIRATION = "expiration" + BUFFERAUTOTUNING = "bufferAutotuning" + METRIC = "metric" + + + # Global sysctl keys + SYSCTL_KEY = { + RMEM: "net.ipv4.tcp_rmem", + WMEM: "net.ipv4.tcp_wmem", + KERNELPM: "net.mptcp.mptcp_path_manager", + SCHED: "net.mptcp.mptcp_scheduler", + CC: "net.ipv4.tcp_congestion_control", + AUTOCORK: "net.ipv4.tcp_autocorking", + EARLYRETRANS: "net.ipv4.tcp_early_retrans", + EXPIRATION: "net.mptcp.mptcp_sched_expiration", + BUFFERAUTOTUNING: "net.ipv4.tcp_moderate_rcvbuf", + } + + # sysctl keys specific to client and server, independently + SYSCTL_KEY_CLIENT = { + KERNELPMC: "net.mptcp.mptcp_path_manager", + } + SYSCTL_KEY_SERVER = { + KERNELPMS: "net.mptcp.mptcp_path_manager", + } + + # Default values for unspecified experience parameters + DEFAULT_PARAMETERS = { + RMEM: "10240 87380 16777216", + WMEM: "4096 16384 4194304", + KERNELPM: "fullmesh", + KERNELPMC: "fullmesh", + KERNELPMS: "fullmesh", + USERPMC: "fullmesh", + USERPMS: "fullmesh", + USERPMCARGS: "", + USERPMSARGS: "", + CC: "olia", + SCHED: "default", + AUTOCORK: "1", + EARLYRETRANS: "3", + EXPIRATION: "300", + BUFFERAUTOTUNING: "1", + METRIC: "-1", + CLIENTPCAP: "no", + SERVERPCAP: "no", + SNAPLENPCAP: "65535", # Default snapping value of tcpdump + XPTYPE: "none", + PINGCOUNT: "5", + NETPERFTESTLEN: "10", + NETPERFTESTNAME: "TCP_RR", + NETPERFREQRESSIZE: "2K,256", + SIRIQUERYSIZE: "2500", + SIRIRESPONSESIZE: "750", + SIRIDELAYQUERYRESPONSE: "0", + SIRIMINPAYLOADSIZE: "85", + SIRIMAXPAYLOADSIZE: "500", + SIRIINTERVALTIMEMS: "333", + SIRIBUFFERSIZE: "9", + SIRIBURSTSIZE: "0", + SIRIINTERVALBURSTTIMEMS: "0", + VLCFILE: "bunny_ibmff_360.mpd", + VLCTIME: "0", + DITGKBYTES: "10000", + DITGCONSTANTPACKETSIZE: "1428", + DITGMEANPOISSONPACKETSSEC: "0", + DITGCONSTANTPACKETSSEC: "0", + DITGBURSTSONPACKETSSEC: "0", + DITGBURSTSOFFPACKETSSEC: "0", + MSGCLIENTSLEEP: "5.0", + MSGSERVERSLEEP: "5.0", + MSGNBREQUESTS: "5", + MSGBYTES: "1200", + QUICMULTIPATH: "0", + PRIOPATH0: "0", + PRIOPATH1: "0", + BACKUPPATH0: "0", + BACKUPPATH1: "0", + } + + def __init__(self, parameter_filename): + super(ExperienceParameter, self).__init__(parameter_filename) + self.default_parameters = ExperienceParameter.DEFAULT_PARAMETERS + + def get(self, key): + val = super(ExperienceParameter, self).get(key) + if val is None: + if key in self.default_parameters: + return self.default_parameters[key] + else: + raise Exception("Parameter not found " + key) + else: + return val + + class Experience(object): """ Base class to instantiate an experience to perform. @@ -8,17 +157,34 @@ class Experience(object): This class is not instantiable as it. You must define a child class with the `NAME` attribute. + By default, an Experience relies on an instance of ExperienceParameter to + collect the parameters from the experience configuration file. However, an + experience may introduce specific parameters in the configuration file. In + such case, the inherinting class must override the `PARAMETER_CLASS` class + variable to point to another class inheriting from ExperienceParameter. + Attributes: experience_parameter Instance of ExperienceParameter topo Instance of Topo topo_config Instance of TopoConfig """ + PARAMETER_CLASS = ExperienceParameter - def __init__(self, experience_parameter, topo, topo_config): - self.experience_parameter = experience_parameter + def __init__(self, experience_parameter_filename, topo, topo_config): + """ + Instantiation of this base class only load the experience parameter + """ + self.experience_parameter = self.__class__.PARAMETER_CLASS(experience_parameter_filename) self.topo = topo self.topo_config = topo_config + def load_parameters(self): + """ + Load the parameter of interest from self.experience_parameter + """ + # Nothing to do in the base class + pass + def classic_run(self): """ Default function to perform the experiment. It consists into three phases: @@ -203,24 +369,24 @@ class Experience(object): def save_sysctl(self): self.sysctlBUP = {} - self._save_sysctl(ExperienceParameter.sysctlKey, self.sysctlBUP) + self._save_sysctl(ExperienceParameter.SYSCTL_KEY, self.sysctlBUP) self.sysctlBUPC = {} - self._save_sysctl(ExperienceParameter.sysctlKeyClient, self.sysctlBUPC, + self._save_sysctl(ExperienceParameter.SYSCTL_KEY_CLIENT, self.sysctlBUPC, ns = True, who = self.topo_config.client) self.sysctlBUPS = {} - self._save_sysctl(ExperienceParameter.sysctlKeyServer, self.sysctlBUPS, + self._save_sysctl(ExperienceParameter.SYSCTL_KEY_SERVER, self.sysctlBUPS, ns = True, who = self.topo_config.server) def _save_sysctl(self, sysctlDic, sysctlBUP, ns = False, who = None): for k in sysctlDic: - sysctlKey = sysctlDic[k] - cmd = self.cmdReadSysctl(sysctlKey) + SYSCTL_KEY = sysctlDic[k] + cmd = self.cmdReadSysctl(SYSCTL_KEY) if not ns: val = self.topo.command_global(cmd) else: val = self.topo.command_to(who, cmd) if val == "Error": - print("oooops can't get sysctl " + sysctlKey) + print("oooops can't get sysctl " + SYSCTL_KEY) else: # For Python3 compatibility if type(val) is bytes: @@ -238,45 +404,45 @@ class Experience(object): return s def write_sysctl(self): - self._write_sysctl(ExperienceParameter.sysctlKey, self.sysctlBUP) - self._write_sysctl(ExperienceParameter.sysctlKeyClient, self.sysctlBUPC, + self._write_sysctl(ExperienceParameter.SYSCTL_KEY, self.sysctlBUP) + self._write_sysctl(ExperienceParameter.SYSCTL_KEY_CLIENT, self.sysctlBUPC, ns = True, who = self.topo_config.client) - self._write_sysctl(ExperienceParameter.sysctlKeyServer, self.sysctlBUPS, + self._write_sysctl(ExperienceParameter.SYSCTL_KEY_SERVER, self.sysctlBUPS, ns = True, who = self.topo_config.server) def _write_sysctl(self, sysctlDic, sysctlBUP, ns = False, who = None): for k in sysctlBUP: - sysctlKey = sysctlDic[k] + SYSCTL_KEY = sysctlDic[k] sysctlValue = self.experience_parameter.get(k) - cmd = self.cmd_write_sysctl(sysctlKey,sysctlValue) + cmd = self.cmd_write_sysctl(SYSCTL_KEY,sysctlValue) if not ns: val = self.topo.command_global(cmd) else: val = self.topo.command_to(who, cmd) if val == "Error": - print("oooops can't set sysctl " + sysctlKey) + print("oooops can't set sysctl " + SYSCTL_KEY) def backUpSysctl(self): - self._backUpSysctl(ExperienceParameter.sysctlKey, self.sysctlBUP) - self._backUpSysctl(ExperienceParameter.sysctlKeyClient, self.sysctlBUPC, + self._backUpSysctl(ExperienceParameter.SYSCTL_KEY, self.sysctlBUP) + self._backUpSysctl(ExperienceParameter.SYSCTL_KEY_CLIENT, self.sysctlBUPC, ns = True, who = self.topo_config.client) - self._backUpSysctl(ExperienceParameter.sysctlKeyServer, self.sysctlBUPS, + self._backUpSysctl(ExperienceParameter.SYSCTL_KEY_SERVER, self.sysctlBUPS, ns = True, who = self.topo_config.server) def _backUpSysctl(self, sysctlDic, sysctlBUP, ns = False, who = None): for k in sysctlBUP: - sysctlKey = sysctlDic[k] + SYSCTL_KEY = sysctlDic[k] sysctlValue = sysctlBUP[k] - cmd = self.cmd_write_sysctl(sysctlKey,sysctlValue) + cmd = self.cmd_write_sysctl(SYSCTL_KEY,sysctlValue) if not ns: val = self.topo.command_global(cmd) else: val = self.topo.command_to(who, cmd) if val == "Error": - print("oooops can't set sysctl " + sysctlKey) + print("oooops can't set sysctl " + SYSCTL_KEY) def runTcpDump(self): @@ -292,3 +458,48 @@ class Experience(object): "tcpdump -i any -s " + snaplenpcap + " -w server.pcap &") if spcap == "yes" or cpcap == "yes": self.topo.command_to(self.topo_config.client,"sleep 5") + + +class RandomFileParameter(ExperienceParameter): + """ + Parameters for the RandomFileExperience + """ + FILE = "file" # file to fetch; if random, we create a file with random data called random. + RANDOM_SIZE = "file_size" # in KB + + def __init__(self, experience_parameter_filename): + super(RandomFileParameter, self).__init__(experience_parameter_filename) + self.default_parameters.update({ + RandomFileParameter.FILE: "random", + RandomFileParameter.RANDOM_SIZE: "1024", + }) + +class RandomFileExperience(Experience): + """ + Enable a experience to use random files + + This class is not directly instantiable + """ + PARAMETER_CLASS = RandomFileParameter + + def __init__(self, experience_parameter_filename, topo, topo_config): + super(RandomFileExperience, self).__init__(experience_parameter_filename, topo, topo_config) + self.load_parameters() + self.ping() + super(RandomFileExperience, self).classic_run() + + def load_parameters(self): + super(RandomFileExperience, self).load_parameters() + self.file = self.experience_parameter.get(RandomFileParameter.FILE) + self.random_size = self.experience_parameter.get(RandomFileParameter.RANDOM_SIZE) + + def prepare(self): + super(RandomFileExperience, self).prepare() + if self.file == "random": + self.topo.command_to(self.topo_config.client, + "dd if=/dev/urandom of=random bs=1K count={}".format(self.random_size)) + + def clean(self): + super(RandomFileExperience, self).clean() + if self.file == "random": + self.topo.command_to(self.topo_config.client, "rm random*") diff --git a/core/parameter.py b/core/parameter.py index feff15a..726972e 100644 --- a/core/parameter.py +++ b/core/parameter.py @@ -1,223 +1,45 @@ +import logging class Parameter(object): - def __init__(self, paramFile): - self.paramDic = {} - print("Create the param Object") - if paramFile is None: - print("default param...") + """ + Generic handler for parameters stored in configuration files + + Attributes: + parameters dictionary containing the value for configuration parameters + """ + def __init__(self, parameter_filename): + self.parameters = {} + if parameter_filename is None: + logging.warning("No parameter file provided; using default parameters") else: - self.loadParamFile(paramFile) + logging.info("Extract parameters from file {}".format(parameter_filename)) + self.load_parameter_file(parameter_filename) - def loadParamFile(self, paramFile): - f = open(paramFile) - i = 0 - for l in f: - i = i + 1 - if l.startswith("#"): - continue + def load_parameter_file(self, parameter_filename): + with open(parameter_filename) as f: + for line in f.readlines(): + # Ignore comments + if line.startswith("#"): + continue - tab = l.split(":") - if len(tab) == 2: - k = tab[0] - val = tab[1].rstrip() - if k in self.paramDic: - if not isinstance(self.paramDic[k], list): - self.paramDic[k] = [self.paramDic[k]] - self.paramDic[k].append(val) - else: - self.paramDic[k] = val - else: - print("Ignored Line " + str(i)) - print(l), - print("In file " + paramFile) - f.close() + try: + # Also get rid of trailing characters + key, value = line.strip().split(":") + if key in self.parameters: + if not isinstance(self.parameters[key], list): + self.parameters[key] = [self.parameters[key]] + self.parameters[key].append(value) + else: + self.parameters[key] = value + except ValueError as e: + logging.warning( + "Got error '{}' for line '{}'; ignore it".format(e, line)) def get(self, key): - if key in self.paramDic: - return self.paramDic[key] - return None + """ + Get the parameter with key `key`. If it does not exist, return None + """ + return self.parameters.get(key) def __str__(self): - s = self.paramDic.__str__() - return s - - -class ExperienceParameter(Parameter): - - RMEM = "rmem" - WMEM = "wmem" - SCHED = "sched" - CC = "congctrl" - AUTOCORK = "autocork" - EARLYRETRANS = "earlyRetrans" - KERNELPM = "kpm" - KERNELPMC = "kpmc" #kernel path manager client / server - KERNELPMS = "kpms" - USERPMC = "upmc" - USERPMS = "upms" #userspace path manager client / server - USERPMCARGS = "upmc_args" - USERPMSARGS = "upms_args" - CLIENTPCAP = "clientPcap" - SERVERPCAP = "serverPcap" - SNAPLENPCAP = "snaplenPcap" - XPTYPE = "xpType" - PINGCOUNT = "pingCount" - DDIBS = "ddIBS" - DDOBS = "ddIBS" - DDCOUNT = "ddCount" - PVRATELIMIT= "pvRateLimit" - PVG = "pvG" #patched version of pv - PVZ = "pvZ" - NCSERVERPORT = "ncServerPort" - NCCLIENTPORT = "ncClientPort" - CHANGEPV = "changePv" - CHANGEPVAT = "changePvAt" - HTTPSFILE = "file" # file to wget, if random : we create a file with random data called random. - HTTPSRANDOMSIZE = "file_size" # if file is set to random, define the size of the random file - EPLOADTESTDIR = "epload_test_dir" - HTTPFILE = "http_file" - HTTPRANDOMSIZE = "http_file_size" - NETPERFTESTLEN = "netperfTestlen" - NETPERFTESTNAME = "netperfTestname" - NETPERFREQRESSIZE = "netperfReqresSize" - ABCONCURRENTREQUESTS = "abConccurentRequests" - ABTIMELIMIT = "abTimelimit" - SIRIRUNTIME = "siriRunTime" - SIRIQUERYSIZE = "siriQuerySize" - SIRIRESPONSESIZE = "siriResponseSize" - SIRIDELAYQUERYRESPONSE = "siriDelayQueryResponse" - SIRIMINPAYLOADSIZE = "siriMinPayloadSize" - SIRIMAXPAYLOADSIZE = "siriMaxPayloadSize" - SIRIINTERVALTIMEMS = "siriIntervalTimeMs" - SIRIBUFFERSIZE = "siriBufferSize" - SIRIBURSTSIZE = "siriBurstSize" - SIRIINTERVALBURSTTIMEMS = "siriIntervalBurstTimeMs" - VLCFILE = "vlcFile" - VLCTIME = "vlcTime" - DITGKBYTES = "ditgKBytes" - DITGCONSTANTPACKETSIZE = "ditgConstantPacketSize" - DITGMEANPOISSONPACKETSSEC = "ditgMeanPoissonPacketsSec" - DITGCONSTANTPACKETSSEC = "ditgConstantPacketsSec" - DITGBURSTSONPACKETSSEC = "ditgBurstsOnPacketsSec" - DITGBURSTSOFFPACKETSSEC = "ditgBurstsOffPacketsSec" - IPERFTIME = "iperfTime" - IPERFPARALLEL = "iperfParallel" - MSGCLIENTSLEEP = "msgClientSleep" - MSGSERVERSLEEP = "msgServerSleep" - MSGNBREQUESTS = "msgNbRequests" - MSGBYTES = "msgBytes" - QUICMULTIPATH = "quicMultipath" - QUICSIRIRUNTIME = "quicSiriRunTime" - PRIOPATH0 = "prioPath0" - PRIOPATH1 = "prioPath1" - BACKUPPATH0 = "backupPath0" - BACKUPPATH1 = "backupPath1" - EXPIRATION = "expiration" - BUFFERAUTOTUNING = "bufferAutotuning" - METRIC = "metric" - - - # global sysctl - sysctlKey = {} - sysctlKey[RMEM] = "net.ipv4.tcp_rmem" - sysctlKey[WMEM] = "net.ipv4.tcp_wmem" - sysctlKey[KERNELPM] = "net.mptcp.mptcp_path_manager" - sysctlKey[SCHED] = "net.mptcp.mptcp_scheduler" - sysctlKey[CC] = "net.ipv4.tcp_congestion_control" - sysctlKey[AUTOCORK] = "net.ipv4.tcp_autocorking" - sysctlKey[EARLYRETRANS] = "net.ipv4.tcp_early_retrans" - sysctlKey[EXPIRATION] = "net.mptcp.mptcp_sched_expiration" - sysctlKey[BUFFERAUTOTUNING] = "net.ipv4.tcp_moderate_rcvbuf" - - - sysctlKeyClient = {} - sysctlKeyClient[KERNELPMC] = "net.mptcp.mptcp_path_manager" - sysctlKeyServer = {} - sysctlKeyServer[KERNELPMS] = "net.mptcp.mptcp_path_manager" - - defaultValue = {} - - defaultValue[RMEM] = "10240 87380 16777216" - defaultValue[WMEM] = "4096 16384 4194304" - defaultValue[KERNELPM] = "fullmesh" - defaultValue[KERNELPMC] = "fullmesh" - defaultValue[KERNELPMS] = "fullmesh" - defaultValue[USERPMC] = "fullmesh" - defaultValue[USERPMS] = "fullmesh" - defaultValue[USERPMCARGS] = "" - defaultValue[USERPMSARGS] = "" - defaultValue[CC] = "olia" - defaultValue[SCHED] = "default" - defaultValue[AUTOCORK] = "1" - defaultValue[EARLYRETRANS] = "3" - defaultValue[EXPIRATION] = "300" - defaultValue[BUFFERAUTOTUNING] = "1" - defaultValue[METRIC] = "-1" - - defaultValue[CLIENTPCAP] = "no" - defaultValue[SERVERPCAP] = "no" - defaultValue[SNAPLENPCAP] = "65535" # Default snapping value of tcpdump - defaultValue[XPTYPE] = "none" - defaultValue[PINGCOUNT] = "5" - defaultValue[DDIBS] = "1k" - defaultValue[DDOBS] = "1k" - defaultValue[DDCOUNT] = "5000" #5k * 1k = 5m - defaultValue[PVRATELIMIT] = "400k" - defaultValue[PVZ] = "10000" - defaultValue[PVG] = "10000" - defaultValue[NCSERVERPORT] = "33666" - defaultValue[NCCLIENTPORT] = "33555" - defaultValue[CHANGEPV] = "no" - defaultValue[HTTPSFILE] = "random" - defaultValue[HTTPSRANDOMSIZE] = "1024" - defaultValue[EPLOADTESTDIR] = "/bla/bla/bla" - defaultValue[HTTPFILE] = "random" - defaultValue[HTTPRANDOMSIZE] = "1024" - defaultValue[NETPERFTESTLEN] = "10" - defaultValue[NETPERFTESTNAME] = "TCP_RR" - defaultValue[NETPERFREQRESSIZE] = "2K,256" - defaultValue[ABCONCURRENTREQUESTS] = "50" - defaultValue[ABTIMELIMIT] = "20" - defaultValue[SIRIQUERYSIZE] = "2500" - defaultValue[SIRIRESPONSESIZE] = "750" - defaultValue[SIRIDELAYQUERYRESPONSE] = "0" - defaultValue[SIRIMINPAYLOADSIZE] = "85" - defaultValue[SIRIMAXPAYLOADSIZE] = "500" - defaultValue[SIRIINTERVALTIMEMS] = "333" - defaultValue[SIRIBUFFERSIZE] = "9" - defaultValue[SIRIBURSTSIZE] = "0" - defaultValue[SIRIINTERVALBURSTTIMEMS] = "0" - defaultValue[VLCFILE] = "bunny_ibmff_360.mpd" - defaultValue[VLCTIME] = "0" - defaultValue[DITGKBYTES] = "10000" - defaultValue[DITGCONSTANTPACKETSIZE] = "1428" - defaultValue[DITGMEANPOISSONPACKETSSEC] = "0" - defaultValue[DITGCONSTANTPACKETSSEC] = "0" - defaultValue[DITGBURSTSONPACKETSSEC] = "0" - defaultValue[DITGBURSTSOFFPACKETSSEC] = "0" - defaultValue[IPERFTIME] = "10" - defaultValue[IPERFPARALLEL] = "1" - defaultValue[MSGCLIENTSLEEP] = "5.0" - defaultValue[MSGSERVERSLEEP] = "5.0" - defaultValue[MSGNBREQUESTS] = "5" - defaultValue[MSGBYTES] = "1200" - defaultValue[QUICMULTIPATH] = "0" - defaultValue[PRIOPATH0] = "0" - defaultValue[PRIOPATH1] = "0" - defaultValue[BACKUPPATH0] = "0" - defaultValue[BACKUPPATH1] = "0" - - def __init__(self, paramFile): - super(ExperienceParameter, self).__init__(paramFile) - - def get(self, key): - val = super(ExperienceParameter, self).get(key) - if val is None: - if key in ExperienceParameter.defaultValue: - return ExperienceParameter.defaultValue[key] - else: - raise Exception("Parameter not found " + key) - else: - return val - - + return self.parameters.__str__() diff --git a/core/topo.py b/core/topo.py index b0ebcf3..f0cf21b 100644 --- a/core/topo.py +++ b/core/topo.py @@ -119,13 +119,13 @@ class TopoParameter(Parameter): RSUBNET = "rightSubnet" netemAt = "netemAt_" changeNetem = "changeNetem" - defaultValue = {} - defaultValue[LSUBNET] = "10.1." - defaultValue[RSUBNET] = "10.2." - defaultValue[changeNetem] = "false" + DEFAULT_PARAMETERS = {} + DEFAULT_PARAMETERS[LSUBNET] = "10.1." + DEFAULT_PARAMETERS[RSUBNET] = "10.2." + DEFAULT_PARAMETERS[changeNetem] = "false" - def __init__(self, paramFile): - Parameter.__init__(self, paramFile) + def __init__(self, parameter_filename): + Parameter.__init__(self, parameter_filename) self.linkCharacteristics = [] self.loadLinkCharacteristics() self.loadNetemAt() @@ -134,10 +134,10 @@ class TopoParameter(Parameter): def loadNetemAt(self): if not self.get(TopoParameter.changeNetem) == "yes": return - for k in sorted(self.paramDic): + for k in sorted(self.parameters): if k.startswith(TopoParameter.netemAt): i = int(k[len(TopoParameter.netemAt):]) - val = self.paramDic[k] + val = self.parameters[k] if not isinstance(val, list): tmp = val val = [] @@ -159,9 +159,9 @@ class TopoParameter(Parameter): def loadLinkCharacteristics(self): i = 0 - for k in sorted(self.paramDic): + for k in sorted(self.parameters): if k.startswith("path"): - tab = self.paramDic[k].split(",") + tab = self.parameters[k].split(",") bup = False loss = "0.0" if len(tab) == 5: @@ -180,13 +180,13 @@ class TopoParameter(Parameter): i = i + 1 else: print("Ignored path :") - print(self.paramDic[k]) + print(self.parameters[k]) def get(self, key): val = Parameter.get(self, key) if val is None: - if key in TopoParameter.defaultValue: - return TopoParameter.defaultValue[key] + if key in TopoParameter.DEFAULT_PARAMETERS: + return TopoParameter.DEFAULT_PARAMETERS[key] else: raise Exception("Param not found " + key) else: diff --git a/experiences/__init__.py b/experiences/__init__.py index 607b7a8..4d3317d 100644 --- a/experiences/__init__.py +++ b/experiences/__init__.py @@ -8,4 +8,14 @@ pkg_dir = os.path.dirname(__file__) for (module_loader, name, ispkg) in pkgutil.iter_modules([pkg_dir]): importlib.import_module('.' + name, __package__) -EXPERIENCES = {cls.NAME: cls for cls in Experience.__subclasses__()} \ No newline at end of file +# Track direct inheritance +EXPERIENCES = {} + +def _get_all_subclasses(BaseClass): + for cls in BaseClass.__subclasses__(): + if hasattr(cls, "NAME"): + EXPERIENCES[cls.NAME] = cls + + _get_all_subclasses(cls) + +_get_all_subclasses(Experience) \ No newline at end of file diff --git a/experiences/ab.py b/experiences/ab.py index bb83c64..69b8e71 100644 --- a/experiences/ab.py +++ b/experiences/ab.py @@ -1,19 +1,30 @@ -from core.experience import Experience, ExperienceParameter +from core.experience import RandomFileExperience, RandomFileParameter, ExperienceParameter import os -class AB(Experience): + +class ABParameter(RandomFileParameter): + CONCURRENT_REQUESTS = "abConccurentRequests" + TIME_LIMIT = "abTimelimit" + + def __init__(self, experience_parameter_filename): + super(ABParameter, self).__init__(experience_parameter_filename) + self.default_parameters.update({ + ABParameter.CONCURRENT_REQUESTS: "50", + ABParameter.TIME_LIMIT: "20", + }) + + +class AB(RandomFileExperience): NAME = "ab" + PARAMETER_CLASS = ABParameter SERVER_LOG = "ab_server.log" CLIENT_LOG = "ab_client.log" AB_BIN = "ab" PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(AB, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() - self.ping() - super(AB, self).classic_run() + def __init__(self, experience_parameter_filename, topo, topo_config): + super(AB, self).__init__(experience_parameter_filename, topo, topo_config) def ping(self): self.topo.command_to(self.topo_config.client, @@ -30,49 +41,39 @@ class AB(Experience): print(s) return s - def loadParam(self): - self.file = self.experience_parameter.get(ExperienceParameter.HTTPFILE) - self.random_size = self.experience_parameter.get(ExperienceParameter.HTTPRANDOMSIZE) - self.concurrent_requests = self.experience_parameter.get(ExperienceParameter.ABCONCURRENTREQUESTS) - self.timelimit = self.experience_parameter.get(ExperienceParameter.ABTIMELIMIT) + def load_parameters(self): + super(AB, self).load_parameters() + self.concurrent_requests = self.experience_parameter.get(ABParameter.CONCURRENT_REQUESTS) + self.time_limit = self.experience_parameter.get(ABParameter.TIME_LIMIT) def prepare(self): - Experience.prepare(self) + super(AB, self).prepare() self.topo.command_to(self.topo_config.client, "rm " + \ AB.CLIENT_LOG ) self.topo.command_to(self.topo_config.server, "rm " + \ AB.SERVER_LOG ) - if self.file == "random": - self.topo.command_to(self.topo_config.client, - "dd if=/dev/urandom of=random bs=1K count=" + \ - self.random_size) - def getAbServerCmd(self): - s = "python " + os.path.dirname(os.path.abspath(__file__)) + \ - "/utils/http_server.py &>" + AB.SERVER_LOG + "&" + def get_ab_server_cmd(self): + s = "python {}/../utils/http_server.py &> {} 2>&1 &".format( + os.path.dirname(os.path.abspath(__file__)), AB.SERVER_LOG) print(s) return s - def getAbClientCmd(self): - s = AB.AB_BIN + " -c " + self.concurrent_requests + " -t " + \ - self.timelimit + " http://" + self.topo_config.getServerIP() + "/" + self.file + \ - " &>" + AB.CLIENT_LOG + def get_ab_client_cmd(self): + s = "{} -c {} -t {} http://{}/{} &> {}".format(AB.AB_BIN, self.concurrent_requests, + self.time_limit, self.topo_config.getServerIP(), self.file, AB.CLIENT_LOG) print(s) return s def clean(self): - Experience.clean(self) - if self.file == "random": - self.topo.command_to(self.topo_config.client, "rm random*") - #todo use cst - #self.topo.command_to(self.topo_config.server, "killall netcat") - + super(AB, self).clean() def run(self): - cmd = self.getAbServerCmd() + cmd = self.get_ab_server_cmd() self.topo.command_to(self.topo_config.server, cmd) - - self.topo.command_to(self.topo_config.client, "sleep 2") - cmd = self.getAbClientCmd() + print("Wait for the HTTP server to be up, this can take quite a while...") + self.topo.command_to(self.topo_config.client, "sleep 15") + cmd = self.get_ab_client_cmd() self.topo.command_to(self.topo_config.client, cmd) self.topo.command_to(self.topo_config.client, "sleep 2") + self.topo.get_cli() diff --git a/experiences/ditg.py b/experiences/ditg.py index 03fa96e..499a1fd 100644 --- a/experiences/ditg.py +++ b/experiences/ditg.py @@ -14,9 +14,9 @@ class DITG(Experience): PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(DITG, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() + def __init__(self, experience_parameter_filename, topo, topo_config): + super(DITG, self).__init__(experience_parameter_filename, topo, topo_config) + self.load_parameters() self.ping() super(DITG, self).classic_run() @@ -35,7 +35,7 @@ class DITG(Experience): print(s) return s - def loadParam(self): + def load_parameters(self): self.kbytes = self.experience_parameter.get(ExperienceParameter.DITGKBYTES) self.constant_packet_size = self.experience_parameter.get(ExperienceParameter.DITGCONSTANTPACKETSIZE) self.mean_poisson_packets_sec = self.experience_parameter.get(ExperienceParameter.DITGMEANPOISSONPACKETSSEC) diff --git a/experiences/epload.py b/experiences/epload.py index b727dbd..c10fc74 100644 --- a/experiences/epload.py +++ b/experiences/epload.py @@ -1,8 +1,19 @@ from core.experience import Experience, ExperienceParameter import os +class EploadParameter(ExperienceParameter): + TEST_DIR = "test_dir" + + def __init__(self, experience_parameter_filename): + super(EploadParameter, self).__init__(experience_parameter_filename) + self.default_parameters.update({ + TEST_DIR: "/bla/bla/bla", + }) + + class Epload(Experience): NAME = "epload" + PARAMETER_CLASS = EploadParameter SERVER_LOG = "http_server.log" EPLOAD_LOG = "epload.log" @@ -10,9 +21,9 @@ class Epload(Experience): EPLOAD_EMULATOR="/home/mininet/epload/epload/emulator/run.js" PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(Epload, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() + def __init__(self, experience_parameter_filename, topo, topo_config): + super(Epload, self).__init__(experience_parameter_filename, topo, topo_config) + self.load_parameters() self.ping() super(Epload, self).classic_run() @@ -31,8 +42,8 @@ class Epload(Experience): print(s) return s - def loadParam(self): - self.epload_test_dir = self.experience_parameter.get(ExperienceParameter.EPLOADTESTDIR) + def load_parameters(self): + self.test_dir = self.experience_parameter.get(EploadParameter.TEST_DIR) def prepare(self): super(Epload, self).prepare() @@ -54,19 +65,19 @@ class Epload(Experience): def getEploadClientCmd(self): s = Epload.NODE_BIN + " " + Epload.EPLOAD_EMULATOR + \ " http " + \ - self.epload_test_dir + " &>" + Epload.EPLOAD_LOG + self.test_dir + " &>" + Epload.EPLOAD_LOG print(s) return s def getSubHostCmd(self): - s = "for f in `ls " + self.epload_test_dir + "/*`; do " + \ + s = "for f in `ls " + self.test_dir + "/*`; do " + \ " sed -i 's/@host@/" + self.topo_config.getServerIP() + "/' " + \ "$f; done" print(s) return s def getSubBackHostCmd(self): - s = "for f in `ls " + self.epload_test_dir + "/*`; do " + \ + s = "for f in `ls " + self.test_dir + "/*`; do " + \ " sed -i 's/" + self.topo_config.getServerIP() + "/@host@/' " + \ "$f; done" print(s) diff --git a/experiences/http.py b/experiences/http.py index 6c616ca..5230bc4 100644 --- a/experiences/http.py +++ b/experiences/http.py @@ -1,7 +1,7 @@ -from core.experience import Experience, ExperienceParameter +from core.experience import ExperienceParameter, RandomFileExperience, RandomFileParameter import os -class HTTP(Experience): +class HTTP(RandomFileExperience): NAME = "http" SERVER_LOG = "http_server.log" @@ -9,11 +9,9 @@ class HTTP(Experience): WGET_BIN = "wget" PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(HTTP, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() - self.ping() - super(HTTP, self).classic_run() + def __init__(self, experience_parameter_filename, topo, topo_config): + # Just rely on RandomFileExperiment + super(HTTP, self).__init__(experience_parameter_filename, topo, topo_config) def ping(self): self.topo.command_to(self.topo_config.client, "rm " + \ @@ -30,9 +28,9 @@ class HTTP(Experience): print(s) return s - def loadParam(self): - self.file = self.experience_parameter.get(ExperienceParameter.HTTPFILE) - self.random_size = self.experience_parameter.get(ExperienceParameter.HTTPRANDOMSIZE) + def load_parameters(self): + # Just rely on RandomFileExperiment + super(HTTP, self).load_parameters() def prepare(self): super(HTTP, self).prepare() @@ -40,26 +38,20 @@ class HTTP(Experience): HTTP.CLIENT_LOG ) self.topo.command_to(self.topo_config.server, "rm " + \ HTTP.SERVER_LOG ) - if self.file == "random": - self.topo.command_to(self.topo_config.client, - "dd if=/dev/urandom of=random bs=1K count=" + \ - self.random_size) def getHTTPServerCmd(self): - s = "/etc/init.d/apache2 restart &>" + HTTP.SERVER_LOG + "&" + s = "/etc/init.d/apache2 restart &> {}&".format(HTTP.SERVER_LOG) print(s) return s def getHTTPClientCmd(self): - s = "(time " + HTTP.WGET_BIN + " http://" + self.topo_config.getServerIP() + \ - "/" + self.file + " --no-check-certificate) &>" + HTTP.CLIENT_LOG + s = "(time {} http://{}/{} --no-check-certificate) &> {}".format(HTTP.WGET_BIN, + self.topo_config.getServerIP(), self.file, HTTP.CLIENT_LOG) print(s) return s def clean(self): super(HTTP, self).clean() - if self.file == "random": - self.topo.command_to(self.topo_config.client, "rm random*") def run(self): cmd = self.getHTTPServerCmd() diff --git a/experiences/https.py b/experiences/https.py index 6b78994..d307684 100644 --- a/experiences/https.py +++ b/experiences/https.py @@ -1,7 +1,7 @@ -from core.experience import Experience, ExperienceParameter +from core.experience import ExperienceParameter, RandomFileExperience, RandomFileParameter import os -class HTTPS(Experience): +class HTTPS(RandomFileExperience): NAME = "https" SERVER_LOG = "https_server.log" @@ -9,11 +9,9 @@ class HTTPS(Experience): WGET_BIN = "wget" PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(HTTPS, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() - self.ping() - super(HTTPS, self).classic_run() + def __init__(self, experience_parameter_filename, topo, topo_config): + # Just rely on RandomFileExperiment + super(HTTPS, self).__init__(experience_parameter_filename, topo, topo_config) def ping(self): self.topo.command_to(self.topo_config.client, "rm " + \ @@ -30,9 +28,9 @@ class HTTPS(Experience): print(s) return s - def loadParam(self): - self.file = self.experience_parameter.get(ExperienceParameter.HTTPSFILE) - self.random_size = self.experience_parameter.get(ExperienceParameter.HTTPSRANDOMSIZE) + def load_parameters(self): + # Just rely on RandomFileExperiment + super(HTTPS, self).load_parameters() def prepare(self): super(HTTPS, self).prepare() @@ -40,10 +38,6 @@ class HTTPS(Experience): HTTPS.CLIENT_LOG ) self.topo.command_to(self.topo_config.server, "rm " + \ HTTPS.SERVER_LOG ) - if self.file == "random": - self.topo.command_to(self.topo_config.client, - "dd if=/dev/urandom of=random bs=1K count=" + \ - self.random_size) def getHTTPSServerCmd(self): s = "python {}/../utils/https_server.py {}/../utils/server.pem &> {}&".format(os.path.dirname(os.path.abspath(__file__)), @@ -59,8 +53,6 @@ class HTTPS(Experience): def clean(self): super(HTTPS, self).clean() - if self.file == "random": - self.topo.command_to(self.topo_config.client, "rm random*") def run(self): cmd = self.getHTTPSServerCmd() @@ -68,7 +60,7 @@ class HTTPS(Experience): self.topo.command_to(self.topo_config.server, cmd) print("Waiting for the server to run") - self.topo.command_to(self.topo_config.client, "sleep 15") + self.topo.command_to(self.topo_config.client, "sleep 2") cmd = self.getHTTPSClientCmd() self.topo.command_to(self.topo_config.client, "netstat -sn > netstat_client_before") self.topo.command_to(self.topo_config.client, cmd) diff --git a/experiences/iperf.py b/experiences/iperf.py index 6246ec6..d06609c 100644 --- a/experiences/iperf.py +++ b/experiences/iperf.py @@ -1,17 +1,29 @@ from core.experience import Experience, ExperienceParameter import os +class IPerfParameter(ExperienceParameter): + TIME = "iperfTime" + PARALLEL = "iperfParallel" + + def __init__(self, experience_parameter_filename): + super(IPerfParameter, self).__init__(experience_parameter_filename) + self.default_parameters.update({ + IPerfParameter.TIME: "10", + IPerfParameter.PARALLEL: "1", + }) + class IPerf(Experience): NAME = "iperf" + PARAMETER_CLASS = IPerfParameter IPERF_LOG = "iperf.log" SERVER_LOG = "server.log" IPERF_BIN = "iperf3" PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(IPerf, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() + def __init__(self, experience_parameter_filename, topo, topo_config): + super(IPerf, self).__init__(experience_parameter_filename, topo, topo_config) + self.load_parameters() self.ping() super(IPerf, self).classic_run() @@ -30,9 +42,9 @@ class IPerf(Experience): print(s) return s - def loadParam(self): - self.time = self.experience_parameter.get(ExperienceParameter.IPERFTIME) - self.parallel = self.experience_parameter.get(ExperienceParameter.IPERFPARALLEL) + def load_parameters(self): + self.time = self.experience_parameter.get(IPerfParameter.TIME) + self.parallel = self.experience_parameter.get(IPerfParameter.PARALLEL) def prepare(self): super(IPerf, self).prepare() diff --git a/experiences/msg.py b/experiences/msg.py index 6244274..09620ec 100644 --- a/experiences/msg.py +++ b/experiences/msg.py @@ -9,9 +9,9 @@ class Msg(Experience): CLIENT_ERR = "msg_client.err" PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(Msg, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() + def __init__(self, experience_parameter_filename, topo, topo_config): + super(Msg, self).__init__(experience_parameter_filename, topo, topo_config) + self.load_parameters() self.ping() super(Msg, self).classic_run() @@ -30,7 +30,7 @@ class Msg(Experience): print(s) return s - def loadParam(self): + def load_parameters(self): self.client_sleep = self.experience_parameter.get(ExperienceParameter.MSGCLIENTSLEEP) self.server_sleep = self.experience_parameter.get(ExperienceParameter.MSGSERVERSLEEP) self.nb_requests = self.experience_parameter.get(ExperienceParameter.MSGNBREQUESTS) diff --git a/experiences/nc.py b/experiences/nc.py index 3631cb0..cd755e8 100644 --- a/experiences/nc.py +++ b/experiences/nc.py @@ -5,30 +5,49 @@ Should be the mother of ExperienceNCPV, shame on me, should rewrite ExperienceNCPV as daughter class of this one. """ +class NCParameter(ExperienceParameter): + DD_IBS = "ddIBS" + DD_OBS = "ddIBS" + DD_COUNT = "ddCount" + SERVER_PORT = "ncServerPort" + CLIENT_PORT = "ncClientPort" + + def __init__(self, experience_parameter_filename): + super(NCParameter, self).__init__(experience_parameter_filename) + self.default_parameters.update({ + NCParameter.DD_IBS: "1k", + NCParameter.DD_OBS: "1k", + NCParameter.DD_COUNT: "5000", #5k * 1k = 5m + NCParameter.SERVER_PORT: "33666", + NCParameter.CLIENT_PORT: "33555", + }) + + class NC(Experience): NAME = "nc" + PARAMETER_CLASS = NCParameter SERVER_NC_LOG = "netcat_server" CLIENT_NC_LOG = "netcat_client" NC_BIN = "netcat" - def __init__(self, experience_parameter, topo, topo_config): - super(NC, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() + def __init__(self, experience_parameter_filename, topo, topo_config): + super(NC, self).__init__(experience_parameter_filename, topo, topo_config) + self.load_parameters() super(NC, self).classic_run() - def loadParam(self): - self.ddibs = self.experience_parameter.get(ExperienceParameter.DDIBS) - self.ddobs = self.experience_parameter.get(ExperienceParameter.DDOBS) - self.ddcount = self.experience_parameter.get(ExperienceParameter.DDCOUNT) - self.ncServerPort = self.experience_parameter.get(ExperienceParameter.NCSERVERPORT) + def load_parameters(self): + self.ddibs = self.experience_parameter.get(NCParameter.DD_IBS) + self.ddobs = self.experience_parameter.get(NCParameter.DD_OBS) + self.ddcount = self.experience_parameter.get(NCParameter.DD_COUNT) + self.ncServerPort = self.experience_parameter.get(NCParameter.SERVER_PORT) self.ncClientPort = [] for k in sorted(self.experience_parameter.paramDic): - if k.startswith(ExperienceParameter.NCCLIENTPORT): + if k.startswith(NCParameter.CLIENT_PORT): port = self.experience_parameter.paramDic[k] self.ncClientPort.append(port) if len(self.ncClientPort) == 0: - d = self.experience_parameter.get(ExperienceParameter.NCCLIENTPORT) + d = self.experience_parameter.get(NCParameter.CLIENT_PORT) self.ncClientPort.append(d) def prepare(self): diff --git a/experiences/ncpv.py b/experiences/ncpv.py index 837bf45..8debfc2 100644 --- a/experiences/ncpv.py +++ b/experiences/ncpv.py @@ -1,4 +1,21 @@ -from core.experience import Experience, ExperienceParameter +from .nc import NC, NCParameter, ExperienceParameter + + +class NCPVParameter(NCParameter): + RATE_LIMIT= "pvRateLimit" + G = "pvG" #patched version of pv + Z = "pvZ" + CHANGE_PV = "changePv" + CHANGE_PV_AT = "changePvAt" + + def __init__(self, experience_parameter_filename): + super(NCPVParameter, self).__init__(experience_parameter_filename) + self.default_parameters.update({ + NCPVParameter.RATE_LIMIT: "400k", + NCPVParameter.G: "10000", + NCPVParameter.Z: "10000", + NCPVParameter.CHANGE_PV: "no", + }) class MpPvAt(object): @@ -12,11 +29,12 @@ class MpPvAt(object): ") will be " + self.cmd -class NCPV(Experience): +class NCPV(NC): """ NC PV : NetCat and Pipe Viewer """ NAME = "ncpv" + PARAMETER_CLASS = NCPVParameter SERVER_NC_LOG = "netcat_server" CLIENT_NC_LOG = "netcat_client" @@ -24,9 +42,9 @@ class NCPV(Experience): PV_BIN = "/usr/local/bin/pv" PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(NCPV, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() + def __init__(self, experience_parameter_filename, topo, topo_config): + super(NCPV, self).__init__(experience_parameter_filename, topo, topo_config) + self.load_parameters() self.ping() super(NCPV, self).classic_run() @@ -45,23 +63,11 @@ class NCPV(Experience): print(s) return s - def loadParam(self): + def load_parameters(self): + super(NCPV, self).load_parameters() self.pvg = self.experience_parameter.get(ExperienceParameter.PVG) self.pvz = self.experience_parameter.get(ExperienceParameter.PVZ) self.pvRateLimit = self.experience_parameter.get(ExperienceParameter.PVRATELIMIT) - self.ddibs = self.experience_parameter.get(ExperienceParameter.DDIBS) - self.ddobs = self.experience_parameter.get(ExperienceParameter.DDOBS) - self.ddcount = self.experience_parameter.get(ExperienceParameter.DDCOUNT) - self.ncServerPort = self.experience_parameter.get(ExperienceParameter.NCSERVERPORT) - self.pvRateLimit = self.experience_parameter.get(ExperienceParameter.PVRATELIMIT) - self.ncClientPort = [] - for k in sorted(self.experience_parameter.paramDic): - if k.startswith(ExperienceParameter.NCCLIENTPORT): - port = self.experience_parameter.paramDic[k] - self.ncClientPort.append(port) - if len(self.ncClientPort) == 0: - d = self.experience_parameter.get(ExperienceParameter.NCCLIENTPORT) - self.ncClientPort.append(d) self.loadPvAt() def loadPvAt(self): @@ -106,15 +112,11 @@ class NCPV(Experience): def prepare(self): super(NCPV, self).prepare() - self.topo.command_to(self.topo_config.client, "rm " + \ - NCPV.CLIENT_NC_LOG ) - self.topo.command_to(self.topo_config.server, "rm " + \ - NCPV.SERVER_NC_LOG ) def getNCServerCmd(self, id): - s = NCPV.NC_BIN + " -d " + \ + s = NC.NC_BIN + " -d " + \ " -l " + self.ncServerPort + \ - " 1>/dev/null 2>" + NCPV.SERVER_NC_LOG + \ + " 1>/dev/null 2>" + NC.SERVER_NC_LOG + \ "_" + str(id) + ".log &" print(s) return s @@ -123,10 +125,10 @@ class NCPV(Experience): s = "dd if=/dev/urandom ibs=" + self.ddibs + \ " obs=" + self.ddobs + \ " count=" + self.ddcount + \ - " | " + NCPV.PV_BIN + \ + " | " + NC.PV_BIN + \ " -g " + self.pvg + " -z " + self.pvz + \ " -q --rate-limit " + self.pvRateLimit + \ - " | " + NCPV.NC_BIN + " " + \ + " | " + NC.NC_BIN + " " + \ " -p " + self.ncClientPort[id] + " " + \ self.topo_config.getServerIP() + " " + \ self.ncServerPort + " " + \ @@ -134,13 +136,13 @@ class NCPV(Experience): "_" + str(id) + ".log" print(s) return s + def getPvPidCmd(self): s = "pgrep -n pv" return s def clean(self): super(NCPV, self).clean() - self.topo.command_to(self.topo_config.server, "killall netcat") def run(self): for i in range(0, len(self.ncClientPort)): diff --git a/experiences/netperf.py b/experiences/netperf.py index d596da0..68db96e 100644 --- a/experiences/netperf.py +++ b/experiences/netperf.py @@ -10,9 +10,9 @@ class Netperf(Experience): NETSERVER_BIN = "netserver" PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(Netperf, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() + def __init__(self, experience_parameter_filename, topo, topo_config): + super(Netperf, self).__init__(experience_parameter_filename, topo, topo_config) + self.load_parameters() self.ping() super(Netperf, self).classic_run() @@ -31,7 +31,7 @@ class Netperf(Experience): print(s) return s - def loadParam(self): + def load_parameters(self): self.testlen = self.experience_parameter.get(ExperienceParameter.NETPERFTESTLEN) self.testname = self.experience_parameter.get(ExperienceParameter.NETPERFTESTNAME) self.reqres_size = self.experience_parameter.get(ExperienceParameter.NETPERFREQRESSIZE) diff --git a/experiences/none.py b/experiences/none.py index eb661e0..5084548 100644 --- a/experiences/none.py +++ b/experiences/none.py @@ -3,8 +3,8 @@ from core.experience import Experience, ExperienceParameter class NoneExperience(Experience): NAME = "none" - def __init__(self, experience_parameter, topo, topo_config): - super(NoneExperience, self).__init__(experience_parameter, topo, topo_config) + def __init__(self, experience_parameter_filename, topo, topo_config): + super(NoneExperience, self).__init__(experience_parameter_filename, topo, topo_config) super(NoneExperience, self).classic_run() def prepare(self): diff --git a/experiences/ping.py b/experiences/ping.py index b22b41a..be2503d 100644 --- a/experiences/ping.py +++ b/experiences/ping.py @@ -5,8 +5,8 @@ class Ping(Experience): PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(Ping, self).__init__(experience_parameter, topo, topo_config) + def __init__(self, experience_parameter_filename, topo, topo_config): + super(Ping, self).__init__(experience_parameter_filename, topo, topo_config) super(Ping, self).classic_run() def prepare(self): diff --git a/experiences/quic.py b/experiences/quic.py index 7426ca9..2a2f438 100644 --- a/experiences/quic.py +++ b/experiences/quic.py @@ -1,9 +1,9 @@ -from core.experience import Experience, ExperienceParameter +from core.experience import RandomFileExperience, RandomFileParameter, ExperienceParameter from topos.multi_interface_cong import MultiInterfaceCongConfig import os -class QUIC(Experience): +class QUIC(RandomFileExperience): NAME = "quic" GO_BIN = "/usr/local/go/bin/go" @@ -15,11 +15,9 @@ class QUIC(Experience): CERTPATH = "~/go/src/github.com/lucas-clemente/quic-go/example/" PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(QUIC, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() - self.ping() - super(QUIC, self).classic_run() + def __init__(self, experience_parameter_filename, topo, topo_config): + # Just rely on RandomFileExperience + super(QUIC, self).__init__(experience_parameter_filename, topo, topo_config) def ping(self): self.topo.command_to(self.topo_config.client, "rm " + \ @@ -36,9 +34,8 @@ class QUIC(Experience): print(s) return s - def loadParam(self): - self.file = self.experience_parameter.get(ExperienceParameter.HTTPSFILE) - self.random_size = self.experience_parameter.get(ExperienceParameter.HTTPSRANDOMSIZE) + def load_parameters(self): + super(QUIC, self).load_parameters() self.multipath = self.experience_parameter.get(ExperienceParameter.QUICMULTIPATH) def prepare(self): @@ -47,10 +44,6 @@ class QUIC(Experience): QUIC.CLIENT_LOG ) self.topo.command_to(self.topo_config.server, "rm " + \ QUIC.SERVER_LOG ) - if self.file == "random": - self.topo.command_to(self.topo_config.client, - "dd if=/dev/urandom of=random bs=1K count=" + \ - self.random_size) def getQUICServerCmd(self): s = QUIC.GO_BIN + " run " + QUIC.SERVER_GO_FILE @@ -69,7 +62,7 @@ class QUIC(Experience): def getCongServerCmd(self, congID): s = "python " + os.path.dirname(os.path.abspath(__file__)) + \ - "/utils/https_server.py &> https_server" + str(congID) + ".log &" + "/../utils/https_server.py &> https_server" + str(congID) + ".log &" print(s) return s @@ -81,8 +74,6 @@ class QUIC(Experience): def clean(self): super(QUIC, self).clean() - if self.file == "random": - self.topo.command_to(self.topo_config.client, "rm random*") def run(self): cmd = self.getQUICServerCmd() diff --git a/experiences/quic_siri.py b/experiences/quic_siri.py index 1f7ecff..9d7160b 100644 --- a/experiences/quic_siri.py +++ b/experiences/quic_siri.py @@ -12,9 +12,9 @@ class QUICSiri(Experience): SERVER_GO_FILE = "~/go/src/github.com/lucas-clemente/quic-go/example/siri/siri.go" PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(QUICSiri, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() + def __init__(self, experience_parameter_filename, topo, topo_config): + super(QUICSiri, self).__init__(experience_parameter_filename, topo, topo_config) + self.load_parameters() self.ping() super(QUICSiri, self).classic_run() @@ -33,7 +33,7 @@ class QUICSiri(Experience): print(s) return s - def loadParam(self): + def load_parameters(self): self.run_time = self.experience_parameter.get(ExperienceParameter.QUICSIRIRUNTIME) self.multipath = self.experience_parameter.get(ExperienceParameter.QUICMULTIPATH) diff --git a/experiences/send_file.py b/experiences/send_file.py index aa381cb..d1e6298 100644 --- a/experiences/send_file.py +++ b/experiences/send_file.py @@ -1,7 +1,7 @@ -from core.experience import Experience, ExperienceParameter +from core.experience import RandomFileExperience, RandomFileParameter, ExperienceParameter import os -class SendFile(Experience): +class SendFile(RandomFileExperience): NAME = "sendfile" SERVER_LOG = "sendfile_server.log" @@ -9,11 +9,9 @@ class SendFile(Experience): WGET_BIN = "./client" PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(SendFile, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() - self.ping() - super(SendFile, self).classic_run() + def __init__(self, experience_parameter_filename, topo, topo_config): + # Just rely on RandomFileExperience + super(SendFile, self).__init__(experience_parameter_filename, topo, topo_config) def ping(self): self.topo.command_to(self.topo_config.client, "rm " + \ @@ -30,9 +28,8 @@ class SendFile(Experience): print(s) return s - def loadParam(self): - self.file = self.experience_parameter.get(ExperienceParameter.HTTPSFILE) - self.random_size = self.experience_parameter.get(ExperienceParameter.HTTPSRANDOMSIZE) + def load_parameters(self): + super(SendFile, self).load_parameters() def prepare(self): super(SendFile, self).prepare() @@ -40,10 +37,6 @@ class SendFile(Experience): SendFile.CLIENT_LOG ) self.topo.command_to(self.topo_config.server, "rm " + \ SendFile.SERVER_LOG ) - if self.file == "random": - self.topo.command_to(self.topo_config.client, - "dd if=/dev/urandom of=random bs=1K count=" + \ - self.random_size) def getSendFileServerCmd(self): s = "./server &>" + SendFile.SERVER_LOG + "&" @@ -57,8 +50,6 @@ class SendFile(Experience): def clean(self): super(SendFile, self).clean() - if self.file == "random": - self.topo.command_to(self.topo_config.client, "rm random*") def run(self): cmd = self.getSendFileServerCmd() diff --git a/experiences/siri.py b/experiences/siri.py index e9000e8..10b587a 100644 --- a/experiences/siri.py +++ b/experiences/siri.py @@ -10,9 +10,9 @@ class Siri(Experience): JAVA_BIN = "java" PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(Siri, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() + def __init__(self, experience_parameter_filename, topo, topo_config): + super(Siri, self).__init__(experience_parameter_filename, topo, topo_config) + self.load_parameters() self.ping() super(Siri, self).classic_run() @@ -31,7 +31,7 @@ class Siri(Experience): print(s) return s - def loadParam(self): + def load_parameters(self): self.run_time = self.experience_parameter.get(ExperienceParameter.SIRIRUNTIME) self.query_size = self.experience_parameter.get(ExperienceParameter.SIRIQUERYSIZE) self.response_size = self.experience_parameter.get(ExperienceParameter.SIRIRESPONSESIZE) diff --git a/experiences/siri_http.py b/experiences/siri_http.py index 8b637dd..40c4845 100644 --- a/experiences/siri_http.py +++ b/experiences/siri_http.py @@ -1,7 +1,7 @@ -from core.experience import Experience, ExperienceParameter +from core.experience import ExperienceParameter, RandomFileExperience, RandomFileParameter import os -class SiriHTTP(Experience): +class SiriHTTP(RandomFileExperience): NAME = "sirihttp" HTTP_SERVER_LOG = "http_server.log" @@ -13,11 +13,9 @@ class SiriHTTP(Experience): JAVA_BIN = "java" PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(SiriHTTP, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() - self.ping() - super(SiriHTTP, self).classic_run() + def __init__(self, experience_parameter_filename, topo, topo_config): + # Just rely on RandomFileExperiment + super(SiriHTTP, self).__init__(experience_parameter_filename, topo, topo_config) def ping(self): self.topo.command_to(self.topo_config.client, "rm " + \ @@ -34,7 +32,9 @@ class SiriHTTP(Experience): print(s) return s - def loadParam(self): + def load_parameters(self): + # Start collecting parameters of RandomFileExperiment + super(SiriHTTP, self).load_parameters() self.run_time = self.experience_parameter.get(ExperienceParameter.SIRIRUNTIME) self.query_size = self.experience_parameter.get(ExperienceParameter.SIRIQUERYSIZE) self.response_size = self.experience_parameter.get(ExperienceParameter.SIRIRESPONSESIZE) @@ -45,8 +45,6 @@ class SiriHTTP(Experience): self.buffer_size = self.experience_parameter.get(ExperienceParameter.SIRIBUFFERSIZE) self.burst_size = self.experience_parameter.get(ExperienceParameter.SIRIBURSTSIZE) self.interval_burst_time_ms = self.experience_parameter.get(ExperienceParameter.SIRIINTERVALBURSTTIMEMS) - self.file = self.experience_parameter.get(ExperienceParameter.HTTPFILE) - self.random_size = self.experience_parameter.get(ExperienceParameter.HTTPRANDOMSIZE) def prepare(self): super(SiriHTTP, self).prepare() diff --git a/experiences/siri_msg.py b/experiences/siri_msg.py index 9ba126c..b3682de 100644 --- a/experiences/siri_msg.py +++ b/experiences/siri_msg.py @@ -13,9 +13,9 @@ class SiriMsg(Experience): JAVA_BIN = "java" PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(SiriMsg, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() + def __init__(self, experience_parameter_filename, topo, topo_config): + super(SiriMsg, self).__init__(experience_parameter_filename, topo, topo_config) + self.load_parameters() self.ping() super(SiriMsg, self).classic_run() @@ -34,7 +34,7 @@ class SiriMsg(Experience): print(s) return s - def loadParam(self): + def load_parameters(self): self.run_time = self.experience_parameter.get(ExperienceParameter.SIRIRUNTIME) self.query_size = self.experience_parameter.get(ExperienceParameter.SIRIQUERYSIZE) self.response_size = self.experience_parameter.get(ExperienceParameter.SIRIRESPONSESIZE) diff --git a/experiences/vlc.py b/experiences/vlc.py index de3a552..396dd3a 100644 --- a/experiences/vlc.py +++ b/experiences/vlc.py @@ -9,9 +9,9 @@ class VLC(Experience): VLC_BIN = "/home/mininet/vlc/vlc" PING_OUTPUT = "ping.log" - def __init__(self, experience_parameter, topo, topo_config): - super(VLC, self).__init__(experience_parameter, topo, topo_config) - self.loadParam() + def __init__(self, experience_parameter_filename, topo, topo_config): + super(VLC, self).__init__(experience_parameter_filename, topo, topo_config) + self.load_parameters() self.ping() super(VLC, self).classic_run() @@ -30,7 +30,7 @@ class VLC(Experience): print(s) return s - def loadParam(self): + def load_parameters(self): self.file = self.experience_parameter.get(ExperienceParameter.VLCFILE) self.time = self.experience_parameter.get(ExperienceParameter.VLCTIME) diff --git a/runner.py b/runner.py index cc97a5e..4ea3f01 100644 --- a/runner.py +++ b/runner.py @@ -20,13 +20,12 @@ class Runner(object): All the operations are done when calling the constructor. """ def __init__(self, builder_type, topo_parameter_file, experience_parameter_file): - self.experience_parameter = ExperienceParameter(experience_parameter_file) self.topo_parameter = TopoParameter(topo_parameter_file) self.set_builder(builder_type) self.set_topo() self.set_topo_config() self.start_topo() - self.run_experience() + self.run_experience(experience_parameter_file) self.stop_topo() def set_builder(self, builder_type): @@ -69,13 +68,15 @@ class Runner(object): self.topo.start_network() self.topo_config.configure_network() - def run_experience(self): + def run_experience(self, experience_parameter_file): """ Match the name of the experiement and launch it """ - xp = self.experience_parameter.get(ExperienceParameter.XPTYPE) + # Well, we need to load twice the experience parameters, is it really annoying? + xp = ExperienceParameter(experience_parameter_file).get(ExperienceParameter.XPTYPE) + print(EXPERIENCES) if xp in EXPERIENCES: - EXPERIENCES[xp](self.experience_parameter, self.topo, self.topo_config) + EXPERIENCES[xp](experience_parameter_file, self.topo, self.topo_config) else: raise Exception("Unknown experience {}".format(xp)) @@ -94,7 +95,7 @@ if __name__ == '__main__': parser.add_argument("--topo_param_file", "-t", required=True, help="path to the topo parameter file") - parser.add_argument("--experience_param_file", "-x", required=True, + parser.add_argument("--experience_param_file", "-x", help="path to the experience parameter file") args = parser.parse_args() diff --git a/utils/http_server.py b/utils/http_server.py index aae6a44..e37855e 100644 --- a/utils/http_server.py +++ b/utils/http_server.py @@ -9,27 +9,19 @@ SimpleHTTPServer.py - simple HTTP server supporting SSL. usage: python SimpleHTTPServer.py ''' -import socket, os -try: - # Python 2 - from SocketServer import BaseServer - from BaseHTTPServer import HTTPServer - from SimpleHTTPServer import SimpleHTTPRequestHandler -except ImportError: +import sys +if sys.version_info[0] == 3: # Python 3 - from socketserver import BaseServer - from http.server import HTTPServer, SimpleHTTPRequestHandler - -from OpenSSL import SSL - -def test(HandlerClass=SimpleHTTPRequestHandler, - ServerClass=HTTPServer): - server_address = ('', 80) # (address, port) - httpd = ServerClass(server_address, HandlerClass) - sa = httpd.socket.getsockname() - print("Serving HTTP on", sa[0], "port", sa[1], "...") + import http.server + server_address = ('', 80) + httpd = http.server.HTTPServer(server_address, http.server.SimpleHTTPRequestHandler) + print("Serving HTTP on 0.0.0.0 port 80...") httpd.serve_forever() +else: + # Python2 + import BaseHTTPServer, SimpleHTTPServer + import os - -if __name__ == '__main__': - test() + httpd = BaseHTTPServer.HTTPServer(('', 443), SimpleHTTPServer.SimpleHTTPRequestHandler) + print("Serving HTTP on 0.0.0.0 port 80...") + httpd.serve_forever() \ No newline at end of file