commit 2022-02-16]13:26:08
This commit is contained in:
parent
fac7b51d4c
commit
951cbd51e8
@ -2,4 +2,6 @@ leftSubnet:10.0.
|
|||||||
rightSubnet:10.1.
|
rightSubnet:10.1.
|
||||||
path_c2r_0:10,10,4
|
path_c2r_0:10,10,4
|
||||||
path_c2r_1:40,30,4
|
path_c2r_1:40,30,4
|
||||||
|
path_c2r_3:10,10,4
|
||||||
|
path_c2r_4:10,10,4
|
||||||
topoType:MultiIf
|
topoType:MultiIf
|
||||||
|
5
config/topo/topo_1_1
Normal file
5
config/topo/topo_1_1
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
clients:5
|
||||||
|
leftSubnet:10.0.
|
||||||
|
rightSubnet:10.1.
|
||||||
|
path_c2r_0:10,10,4,10
|
||||||
|
topoType:IoTMultiClient
|
@ -2,4 +2,7 @@ leftSubnet:10.0.
|
|||||||
rightSubnet:10.1.
|
rightSubnet:10.1.
|
||||||
path_c2r_0:10,10,4
|
path_c2r_0:10,10,4
|
||||||
path_c2r_1:40,30,4
|
path_c2r_1:40,30,4
|
||||||
|
path_c2r_3:40,30,4
|
||||||
|
path_c2r_4:40,30,4
|
||||||
topoType:MultiIfMultiClient
|
topoType:MultiIfMultiClient
|
||||||
|
|
||||||
|
5
config/xp/basicquic
Normal file
5
config/xp/basicquic
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
xpType:basicquic
|
||||||
|
serverPcap:yes
|
||||||
|
kpms:fullmesh
|
||||||
|
kpmc:fullmesh
|
||||||
|
rmem:300000 300000 300000
|
@ -1,4 +1,4 @@
|
|||||||
xpType:https
|
xpType:pquic
|
||||||
clientPcap:yes
|
clientPcap:yes
|
||||||
kpms:fullmesh
|
kpms:fullmesh
|
||||||
kpmc:fullmesh
|
kpmc:fullmesh
|
||||||
|
@ -2,6 +2,7 @@ from .parameter import Parameter
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
class ExperimentParameter(Parameter):
|
class ExperimentParameter(Parameter):
|
||||||
"""
|
"""
|
||||||
Handler for experiment parameters stored in configuration files.
|
Handler for experiment parameters stored in configuration files.
|
||||||
@ -12,25 +13,25 @@ class ExperimentParameter(Parameter):
|
|||||||
Attribute:
|
Attribute:
|
||||||
default_parameters Default values for the parameters
|
default_parameters Default values for the parameters
|
||||||
"""
|
"""
|
||||||
RMEM = "rmem"
|
RMEM = "rmem"
|
||||||
WMEM = "wmem"
|
WMEM = "wmem"
|
||||||
MPTCP_ENABLED = "mptcpEnabled"
|
MPTCP_ENABLED = "mptcpEnabled"
|
||||||
SCHED = "sched"
|
SCHED = "sched"
|
||||||
CC = "congctrl"
|
CC = "congctrl"
|
||||||
AUTOCORK = "autocork"
|
AUTOCORK = "autocork"
|
||||||
EARLY_RETRANS = "earlyRetrans"
|
EARLY_RETRANS = "earlyRetrans"
|
||||||
KERNELPM = "kpm"
|
KERNELPM = "kpm"
|
||||||
KERNELPMC = "kpmc" #kernel path manager client / server
|
KERNELPMC = "kpmc" # kernel path manager client / server
|
||||||
KERNELPMS = "kpms"
|
KERNELPMS = "kpms"
|
||||||
USERPMC = "upmc"
|
USERPMC = "upmc"
|
||||||
USERPMS = "upms" #userspace path manager client / server
|
USERPMS = "upms" # userspace path manager client / server
|
||||||
USERPMC_ARGS = "upmc_args"
|
USERPMC_ARGS = "upmc_args"
|
||||||
USERPMS_ARGS = "upms_args"
|
USERPMS_ARGS = "upms_args"
|
||||||
CLIENT_PCAP = "clientPcap"
|
CLIENT_PCAP = "clientPcap"
|
||||||
SERVER_PCAP = "serverPcap"
|
SERVER_PCAP = "serverPcap"
|
||||||
SNAPLEN_PCAP = "snaplen_pcap"
|
SNAPLEN_PCAP = "snaplen_pcap"
|
||||||
XP_TYPE = "xpType"
|
XP_TYPE = "xpType"
|
||||||
PING_COUNT = "pingCount"
|
PING_COUNT = "pingCount"
|
||||||
PRIO_PATH_0 = "priority_path_0"
|
PRIO_PATH_0 = "priority_path_0"
|
||||||
PRIO_PATH_1 = "priority_path_1"
|
PRIO_PATH_1 = "priority_path_1"
|
||||||
BACKUP_PATH_0 = "backup_path_0"
|
BACKUP_PATH_0 = "backup_path_0"
|
||||||
@ -41,13 +42,13 @@ class ExperimentParameter(Parameter):
|
|||||||
SYSCTL_KEY = {
|
SYSCTL_KEY = {
|
||||||
RMEM: "net.ipv4.tcp_rmem",
|
RMEM: "net.ipv4.tcp_rmem",
|
||||||
WMEM: "net.ipv4.tcp_wmem",
|
WMEM: "net.ipv4.tcp_wmem",
|
||||||
MPTCP_ENABLED: "net.mptcp.mptcp_enabled",
|
# MPTCP_ENABLED: "net.mptcp.mptcp_enabled",
|
||||||
KERNELPM: "net.mptcp.mptcp_path_manager",
|
# KERNELPM: "net.mptcp.mptcp_path_manager",
|
||||||
SCHED: "net.mptcp.mptcp_scheduler",
|
# SCHED: "net.mptcp.mptcp_scheduler",
|
||||||
CC: "net.ipv4.tcp_congestion_control",
|
# CC: "net.ipv4.tcp_congestion_control",
|
||||||
AUTOCORK: "net.ipv4.tcp_autocorking",
|
# AUTOCORK: "net.ipv4.tcp_autocorking",
|
||||||
EARLY_RETRANS: "net.ipv4.tcp_early_retrans",
|
# EARLY_RETRANS: "net.ipv4.tcp_early_retrans",
|
||||||
BUFFER_AUTOTUNING: "net.ipv4.tcp_moderate_rcvbuf",
|
# BUFFER_AUTOTUNING: "net.ipv4.tcp_moderate_rcvbuf",
|
||||||
}
|
}
|
||||||
|
|
||||||
# sysctl keys specific to client and server, independently
|
# sysctl keys specific to client and server, independently
|
||||||
@ -93,10 +94,10 @@ class ExperimentParameter(Parameter):
|
|||||||
|
|
||||||
class Experiment(object):
|
class Experiment(object):
|
||||||
"""
|
"""
|
||||||
Base class to instantiate an experiment to perform.
|
Base class to instantiate an experiment to perform.
|
||||||
|
|
||||||
This class is not instantiable as it. You must define a child class with the
|
This class is not instantiable as it. You must define a child class with the
|
||||||
`NAME` attribute.
|
`NAME` attribute.
|
||||||
|
|
||||||
By default, an Experiment relies on an instance of ExperimentParameter to
|
By default, an Experiment relies on an instance of ExperimentParameter to
|
||||||
collect the parameters from the experiment configuration file. However, an
|
collect the parameters from the experiment configuration file. However, an
|
||||||
@ -108,7 +109,7 @@ class Experiment(object):
|
|||||||
experiment_parameter Instance of ExperimentParameter
|
experiment_parameter Instance of ExperimentParameter
|
||||||
topo Instance of Topo
|
topo Instance of Topo
|
||||||
topo_config Instance of TopoConfig
|
topo_config Instance of TopoConfig
|
||||||
"""
|
"""
|
||||||
PARAMETER_CLASS = ExperimentParameter
|
PARAMETER_CLASS = ExperimentParameter
|
||||||
|
|
||||||
IP_BIN = "ip"
|
IP_BIN = "ip"
|
||||||
@ -118,7 +119,8 @@ class Experiment(object):
|
|||||||
"""
|
"""
|
||||||
Instantiation of this base class only load the experiment parameter
|
Instantiation of this base class only load the experiment parameter
|
||||||
"""
|
"""
|
||||||
self.experiment_parameter = self.__class__.PARAMETER_CLASS(experiment_parameter_filename)
|
self.experiment_parameter = self.__class__.PARAMETER_CLASS(
|
||||||
|
experiment_parameter_filename)
|
||||||
self.topo = topo
|
self.topo = topo
|
||||||
self.topo_config = topo_config
|
self.topo_config = topo_config
|
||||||
|
|
||||||
@ -158,8 +160,10 @@ class Experiment(object):
|
|||||||
"""
|
"""
|
||||||
Function only meaningful for MPTCP
|
Function only meaningful for MPTCP
|
||||||
"""
|
"""
|
||||||
priority_path_0 = self.experiment_parameter.get(ExperimentParameter.PRIO_PATH_0)
|
priority_path_0 = self.experiment_parameter.get(
|
||||||
priority_path_1 = self.experiment_parameter.get(ExperimentParameter.PRIO_PATH_1)
|
ExperimentParameter.PRIO_PATH_0)
|
||||||
|
priority_path_1 = self.experiment_parameter.get(
|
||||||
|
ExperimentParameter.PRIO_PATH_1)
|
||||||
if not priority_path_0 == priority_path_1:
|
if not priority_path_0 == priority_path_1:
|
||||||
self.topo.command_to(self.topo_config.client, "{} link set dev {} priority {}".format(
|
self.topo.command_to(self.topo_config.client, "{} link set dev {} priority {}".format(
|
||||||
Experiment.IP_BIN, self.topo_config.get_client_interface(0), priority_path_0))
|
Experiment.IP_BIN, self.topo_config.get_client_interface(0), priority_path_0))
|
||||||
@ -170,18 +174,20 @@ class Experiment(object):
|
|||||||
self.topo.command_to(self.topo_config.router, "{} link set dev {} priority {}".format(
|
self.topo.command_to(self.topo_config.router, "{} link set dev {} priority {}".format(
|
||||||
Experiment.IP_BIN, self.topo_config.get_router_interface_to_client_switch(1), priority_path_1))
|
Experiment.IP_BIN, self.topo_config.get_router_interface_to_client_switch(1), priority_path_1))
|
||||||
|
|
||||||
backup_path_0 = self.experiment_parameter.get(ExperimentParameter.BACKUP_PATH_0)
|
backup_path_0 = self.experiment_parameter.get(
|
||||||
|
ExperimentParameter.BACKUP_PATH_0)
|
||||||
if int(backup_path_0) > 0:
|
if int(backup_path_0) > 0:
|
||||||
self.topo.command_to(self.topo_config.client,
|
self.topo.command_to(self.topo_config.client,
|
||||||
self.topo_config.interface_backup_command(self.topo_config.get_client_interface(0)))
|
self.topo_config.interface_backup_command(self.topo_config.get_client_interface(0)))
|
||||||
self.topo.command_to(self.topo_config.router,
|
self.topo.command_to(self.topo_config.router,
|
||||||
self.topo_config.interface_backup_command(self.topo_config.get_router_interface_to_client_switch(0)))
|
self.topo_config.interface_backup_command(self.topo_config.get_router_interface_to_client_switch(0)))
|
||||||
backup_path_1 = self.experiment_parameter.get(ExperimentParameter.BACKUP_PATH_1)
|
backup_path_1 = self.experiment_parameter.get(
|
||||||
|
ExperimentParameter.BACKUP_PATH_1)
|
||||||
if int(backup_path_1) > 0:
|
if int(backup_path_1) > 0:
|
||||||
self.topo.command_to(self.topo_config.client,
|
self.topo.command_to(self.topo_config.client,
|
||||||
self.topo_config.interface_backup_command(self.topo_config.get_client_interface(1)))
|
self.topo_config.interface_backup_command(self.topo_config.get_client_interface(1)))
|
||||||
self.topo.command_to(self.topo_config.router,
|
self.topo.command_to(self.topo_config.router,
|
||||||
self.topo_config.interface_backup_command(self.topo_config.get_router_interface_to_client_switch(1)))
|
self.topo_config.interface_backup_command(self.topo_config.get_router_interface_to_client_switch(1)))
|
||||||
|
|
||||||
def run_userspace_path_manager(self):
|
def run_userspace_path_manager(self):
|
||||||
"""
|
"""
|
||||||
@ -190,13 +196,15 @@ class Experiment(object):
|
|||||||
if self.experiment_parameter.get(ExperimentParameter.KERNELPMC) == "netlink":
|
if self.experiment_parameter.get(ExperimentParameter.KERNELPMC) == "netlink":
|
||||||
logging.info("Running user-space path manager on client")
|
logging.info("Running user-space path manager on client")
|
||||||
upmc = self.experiment_parameter.get(ExperimentParameter.USERPMC)
|
upmc = self.experiment_parameter.get(ExperimentParameter.USERPMC)
|
||||||
upmca = self.experiment_parameter.get(ExperimentParameter.USERPMC_ARGS)
|
upmca = self.experiment_parameter.get(
|
||||||
|
ExperimentParameter.USERPMC_ARGS)
|
||||||
self.topo.command_to(self.topo_config.client, "{} {} &>{} &".format(
|
self.topo.command_to(self.topo_config.client, "{} {} &>{} &".format(
|
||||||
upmc, upmca, "upmc.log"))
|
upmc, upmca, "upmc.log"))
|
||||||
if self.experiment_parameter.get(ExperimentParameter.KERNELPMS) == "netlink":
|
if self.experiment_parameter.get(ExperimentParameter.KERNELPMS) == "netlink":
|
||||||
logging.info("Running user-space path manager on server")
|
logging.info("Running user-space path manager on server")
|
||||||
upms = self.experiment_parameter.get(ExperimentParameter.USERPMS)
|
upms = self.experiment_parameter.get(ExperimentParameter.USERPMS)
|
||||||
upmsa = self.experiment_parameter.get(ExperimentParameter.USERPMS_ARGS)
|
upmsa = self.experiment_parameter.get(
|
||||||
|
ExperimentParameter.USERPMS_ARGS)
|
||||||
self.topo.command_to(self.topo_config.server, "{} {} &>{} &".format(
|
self.topo.command_to(self.topo_config.server, "{} {} &>{} &".format(
|
||||||
upms, upmsa, "upms.log"))
|
upms, upmsa, "upms.log"))
|
||||||
|
|
||||||
@ -204,11 +212,13 @@ class Experiment(object):
|
|||||||
if self.experiment_parameter.get(ExperimentParameter.KERNELPMC) == "netlink":
|
if self.experiment_parameter.get(ExperimentParameter.KERNELPMC) == "netlink":
|
||||||
logging.info("Cleaning user-space path manager on client")
|
logging.info("Cleaning user-space path manager on client")
|
||||||
upmc = self.experiment_parameter.get(ExperimentParameter.USERPMC)
|
upmc = self.experiment_parameter.get(ExperimentParameter.USERPMC)
|
||||||
self.topo.command_to(self.topo_config.client, "killall {}".format(upmc))
|
self.topo.command_to(self.topo_config.client,
|
||||||
|
"killall {}".format(upmc))
|
||||||
if self.experiment_parameter.get(ExperimentParameter.KERNELPMS) == "netlink":
|
if self.experiment_parameter.get(ExperimentParameter.KERNELPMS) == "netlink":
|
||||||
logging.info("Cleaning user-space path manager on server")
|
logging.info("Cleaning user-space path manager on server")
|
||||||
upms = self.experiment_parameter.get(ExperimentParameter.USERPMS)
|
upms = self.experiment_parameter.get(ExperimentParameter.USERPMS)
|
||||||
self.topo.command_to(self.topo_config.client, "killall {}".format(upms))
|
self.topo.command_to(self.topo_config.client,
|
||||||
|
"killall {}".format(upms))
|
||||||
|
|
||||||
def run_netem_at(self):
|
def run_netem_at(self):
|
||||||
self.topo_config.run_netem_at()
|
self.topo_config.run_netem_at()
|
||||||
@ -244,13 +254,14 @@ class Experiment(object):
|
|||||||
Record the current sysctls
|
Record the current sysctls
|
||||||
"""
|
"""
|
||||||
self.sysctl_to_restore = {}
|
self.sysctl_to_restore = {}
|
||||||
self._save_sysctl(ExperimentParameter.SYSCTL_KEY, self.sysctl_to_restore)
|
self._save_sysctl(ExperimentParameter.SYSCTL_KEY,
|
||||||
|
self.sysctl_to_restore)
|
||||||
self.client_sysctl_to_restore = {}
|
self.client_sysctl_to_restore = {}
|
||||||
self._save_sysctl(ExperimentParameter.SYSCTL_KEY_CLIENT, self.client_sysctl_to_restore,
|
self._save_sysctl(ExperimentParameter.SYSCTL_KEY_CLIENT, self.client_sysctl_to_restore,
|
||||||
ns=True, who=self.topo_config.client)
|
ns=True, who=self.topo_config.client)
|
||||||
self.server_sysctl_to_restore = {}
|
self.server_sysctl_to_restore = {}
|
||||||
self._save_sysctl(ExperimentParameter.SYSCTL_KEY_SERVER, self.server_sysctl_to_restore,
|
self._save_sysctl(ExperimentParameter.SYSCTL_KEY_SERVER, self.server_sysctl_to_restore,
|
||||||
ns=True, who=self.topo_config.server)
|
ns=True, who=self.topo_config.server)
|
||||||
|
|
||||||
def _save_sysctl(self, sysctl_dict, sysctl_to_restore, ns=False, who=None):
|
def _save_sysctl(self, sysctl_dict, sysctl_to_restore, ns=False, who=None):
|
||||||
for k in sysctl_dict:
|
for k in sysctl_dict:
|
||||||
@ -284,13 +295,14 @@ class Experiment(object):
|
|||||||
"""
|
"""
|
||||||
Write the experiment sysctls
|
Write the experiment sysctls
|
||||||
"""
|
"""
|
||||||
self._write_sysctl(ExperimentParameter.SYSCTL_KEY, self.sysctl_to_restore)
|
self._write_sysctl(ExperimentParameter.SYSCTL_KEY,
|
||||||
|
self.sysctl_to_restore)
|
||||||
self._write_sysctl(ExperimentParameter.SYSCTL_KEY_CLIENT, self.client_sysctl_to_restore,
|
self._write_sysctl(ExperimentParameter.SYSCTL_KEY_CLIENT, self.client_sysctl_to_restore,
|
||||||
ns=True, who=self.topo_config.client)
|
ns=True, who=self.topo_config.client)
|
||||||
self._write_sysctl(ExperimentParameter.SYSCTL_KEY_SERVER, self.server_sysctl_to_restore,
|
self._write_sysctl(ExperimentParameter.SYSCTL_KEY_SERVER, self.server_sysctl_to_restore,
|
||||||
ns=True, who=self.topo_config.server)
|
ns=True, who=self.topo_config.server)
|
||||||
|
|
||||||
def _write_sysctl(self, sysctl_dict, sysctl_to_restore, ns = False, who = None):
|
def _write_sysctl(self, sysctl_dict, sysctl_to_restore, ns=False, who=None):
|
||||||
for k in sysctl_to_restore:
|
for k in sysctl_to_restore:
|
||||||
sysctl_key = sysctl_dict[k]
|
sysctl_key = sysctl_dict[k]
|
||||||
sysctl_value = self.experiment_parameter.get(k)
|
sysctl_value = self.experiment_parameter.get(k)
|
||||||
@ -306,13 +318,14 @@ class Experiment(object):
|
|||||||
"""
|
"""
|
||||||
Restore back the sysctls that were present before running the experiment
|
Restore back the sysctls that were present before running the experiment
|
||||||
"""
|
"""
|
||||||
self._restore_sysctl(ExperimentParameter.SYSCTL_KEY, self.sysctl_to_restore)
|
self._restore_sysctl(ExperimentParameter.SYSCTL_KEY,
|
||||||
|
self.sysctl_to_restore)
|
||||||
self._restore_sysctl(ExperimentParameter.SYSCTL_KEY_CLIENT, self.client_sysctl_to_restore,
|
self._restore_sysctl(ExperimentParameter.SYSCTL_KEY_CLIENT, self.client_sysctl_to_restore,
|
||||||
ns=True, who=self.topo_config.client)
|
ns=True, who=self.topo_config.client)
|
||||||
self._restore_sysctl(ExperimentParameter.SYSCTL_KEY_SERVER, self.server_sysctl_to_restore,
|
self._restore_sysctl(ExperimentParameter.SYSCTL_KEY_SERVER, self.server_sysctl_to_restore,
|
||||||
ns=True, who=self.topo_config.server)
|
ns=True, who=self.topo_config.server)
|
||||||
|
|
||||||
def _restore_sysctl(self, sysctl_dict, sysctl_to_restore, ns = False, who = None):
|
def _restore_sysctl(self, sysctl_dict, sysctl_to_restore, ns=False, who=None):
|
||||||
for k in sysctl_to_restore:
|
for k in sysctl_to_restore:
|
||||||
sysctl_key = sysctl_dict[k]
|
sysctl_key = sysctl_dict[k]
|
||||||
sysctl_value = sysctl_to_restore[k]
|
sysctl_value = sysctl_to_restore[k]
|
||||||
@ -326,27 +339,32 @@ class Experiment(object):
|
|||||||
logging.error("unable to set sysctl {}".format(sysctl_key))
|
logging.error("unable to set sysctl {}".format(sysctl_key))
|
||||||
|
|
||||||
def run_tcpdump(self):
|
def run_tcpdump(self):
|
||||||
client_pcap = self.experiment_parameter.get(ExperimentParameter.CLIENT_PCAP)
|
client_pcap = self.experiment_parameter.get(
|
||||||
server_pcap = self.experiment_parameter.get(ExperimentParameter.SERVER_PCAP)
|
ExperimentParameter.CLIENT_PCAP)
|
||||||
snaplen_pcap = self.experiment_parameter.get(ExperimentParameter.SNAPLEN_PCAP)
|
server_pcap = self.experiment_parameter.get(
|
||||||
|
ExperimentParameter.SERVER_PCAP)
|
||||||
|
snaplen_pcap = self.experiment_parameter.get(
|
||||||
|
ExperimentParameter.SNAPLEN_PCAP)
|
||||||
|
self.topo.command_to(self.topo_config.router,
|
||||||
|
"tcpdump -i any -s {} -w router.pcap &".format(snaplen_pcap))
|
||||||
if client_pcap == "yes":
|
if client_pcap == "yes":
|
||||||
self.topo.command_to(self.topo_config.client,
|
self.topo.command_to(self.topo_config.client,
|
||||||
"tcpdump -i any -s {} -w client.pcap &".format(snaplen_pcap))
|
"tcpdump -i any -s {} -w client.pcap &".format(snaplen_pcap))
|
||||||
if server_pcap == "yes":
|
if server_pcap == "yes":
|
||||||
self.topo.command_to(self.topo_config.server,
|
self.topo.command_to(self.topo_config.server,
|
||||||
"tcpdump -i any -s {} -w server.pcap &".format(snaplen_pcap))
|
"tcpdump -i any -s {} -w server.pcap &".format(snaplen_pcap))
|
||||||
if server_pcap == "yes" or client_pcap == "yes":
|
if server_pcap == "yes" or client_pcap == "yes":
|
||||||
logging.info("Activating tcpdump, waiting for it to run")
|
logging.info("Activating tcpdump, waiting for it to run")
|
||||||
self.topo.command_to(self.topo_config.client,"sleep 5")
|
self.topo.command_to(self.topo_config.client, "sleep 5")
|
||||||
|
|
||||||
def ping(self):
|
def ping(self):
|
||||||
self.topo.command_to(self.topo_config.client,
|
self.topo.command_to(self.topo_config.client,
|
||||||
"rm {}".format(Experiment.PING_OUTPUT))
|
"rm {}".format(Experiment.PING_OUTPUT))
|
||||||
count = self.experiment_parameter.get(ExperimentParameter.PING_COUNT)
|
count = self.experiment_parameter.get(ExperimentParameter.PING_COUNT)
|
||||||
for j in range(0, self.topo_config.server_interface_count()):
|
for j in range(0, self.topo_config.server_interface_count()):
|
||||||
for i in range(0, self.topo_config.client_interface_count()):
|
for i in range(0, self.topo_config.client_interface_count()):
|
||||||
cmd = self.ping_command(self.topo_config.get_client_ip(i),
|
cmd = self.ping_command(self.topo_config.get_client_ip(i),
|
||||||
self.topo_config.get_server_ip(interface_index=j), n=count)
|
self.topo_config.get_server_ip(interface_index=j), n=count)
|
||||||
logging.info(cmd)
|
logging.info(cmd)
|
||||||
self.topo.command_to(self.topo_config.client, cmd)
|
self.topo.command_to(self.topo_config.client, cmd)
|
||||||
|
|
||||||
@ -362,7 +380,8 @@ class RandomFileParameter(ExperimentParameter):
|
|||||||
RANDOM_SIZE = "file_size" # in KB
|
RANDOM_SIZE = "file_size" # in KB
|
||||||
|
|
||||||
def __init__(self, experiment_parameter_filename):
|
def __init__(self, experiment_parameter_filename):
|
||||||
super(RandomFileParameter, self).__init__(experiment_parameter_filename)
|
super(RandomFileParameter, self).__init__(
|
||||||
|
experiment_parameter_filename)
|
||||||
self.default_parameters.update({
|
self.default_parameters.update({
|
||||||
RandomFileParameter.FILE: "random",
|
RandomFileParameter.FILE: "random",
|
||||||
RandomFileParameter.RANDOM_SIZE: "1024",
|
RandomFileParameter.RANDOM_SIZE: "1024",
|
||||||
@ -378,22 +397,24 @@ class RandomFileExperiment(Experiment):
|
|||||||
PARAMETER_CLASS = RandomFileParameter
|
PARAMETER_CLASS = RandomFileParameter
|
||||||
|
|
||||||
def __init__(self, experiment_parameter_filename, topo, topo_config):
|
def __init__(self, experiment_parameter_filename, topo, topo_config):
|
||||||
super(RandomFileExperiment, self).__init__(experiment_parameter_filename, topo, topo_config)
|
super(RandomFileExperiment, self).__init__(
|
||||||
|
experiment_parameter_filename, topo, topo_config)
|
||||||
self.load_parameters()
|
self.load_parameters()
|
||||||
self.ping()
|
self.ping()
|
||||||
|
|
||||||
def load_parameters(self):
|
def load_parameters(self):
|
||||||
super(RandomFileExperiment, self).load_parameters()
|
super(RandomFileExperiment, self).load_parameters()
|
||||||
self.file = self.experiment_parameter.get(RandomFileParameter.FILE)
|
self.file = self.experiment_parameter.get(RandomFileParameter.FILE)
|
||||||
self.random_size = self.experiment_parameter.get(RandomFileParameter.RANDOM_SIZE)
|
self.random_size = self.experiment_parameter.get(
|
||||||
|
RandomFileParameter.RANDOM_SIZE)
|
||||||
|
|
||||||
def prepare(self):
|
def prepare(self):
|
||||||
super(RandomFileExperiment, self).prepare()
|
super(RandomFileExperiment, self).prepare()
|
||||||
if self.file == "random":
|
if self.file == "random":
|
||||||
self.topo.command_to(self.topo_config.client,
|
self.topo.command_to(self.topo_config.client,
|
||||||
"dd if=/dev/urandom of=random bs=1K count={}".format(self.random_size))
|
"dd if=/dev/urandom of=random bs=1K count={}".format(self.random_size))
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
super(RandomFileExperiment, self).clean()
|
super(RandomFileExperiment, self).clean()
|
||||||
if self.file == "random":
|
if self.file == "random":
|
||||||
self.topo.command_to(self.topo_config.client, "rm random*")
|
self.topo.command_to(self.topo_config.client, "rm random*")
|
||||||
|
86
core/topo.py
86
core/topo.py
@ -8,6 +8,7 @@ class NetemAt(object):
|
|||||||
"""
|
"""
|
||||||
Class representing a netem command to be run after some time
|
Class representing a netem command to be run after some time
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, at, cmd):
|
def __init__(self, at, cmd):
|
||||||
self.at = at
|
self.at = at
|
||||||
self.cmd = cmd
|
self.cmd = cmd
|
||||||
@ -41,6 +42,7 @@ class LinkCharacteristics(object):
|
|||||||
netem_at list of NetemAt instances applicable to the link
|
netem_at list of NetemAt instances applicable to the link
|
||||||
backup integer indicating if this link is a backup one or not (useful for MPTCP)
|
backup integer indicating if this link is a backup one or not (useful for MPTCP)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, id, link_type, delay, queue_size, bandwidth, loss, backup=0):
|
def __init__(self, id, link_type, delay, queue_size, bandwidth, loss, backup=0):
|
||||||
self.id = id
|
self.id = id
|
||||||
self.link_type = link_type
|
self.link_type = link_type
|
||||||
@ -48,7 +50,8 @@ class LinkCharacteristics(object):
|
|||||||
self.queue_size = queue_size
|
self.queue_size = queue_size
|
||||||
self.bandwidth = bandwidth
|
self.bandwidth = bandwidth
|
||||||
self.loss = loss
|
self.loss = loss
|
||||||
self.queuing_delay = str(self.extract_queuing_delay(queue_size, bandwidth, delay))
|
self.queuing_delay = str(
|
||||||
|
self.extract_queuing_delay(queue_size, bandwidth, delay))
|
||||||
self.netem_at = []
|
self.netem_at = []
|
||||||
self.backup = backup
|
self.backup = backup
|
||||||
|
|
||||||
@ -63,11 +66,11 @@ class LinkCharacteristics(object):
|
|||||||
Return the buffer size in bytes
|
Return the buffer size in bytes
|
||||||
"""
|
"""
|
||||||
return (1500.0 * self.bandwidth_delay_product_divided_by_mtu()) + \
|
return (1500.0 * self.bandwidth_delay_product_divided_by_mtu()) + \
|
||||||
(float(self.bandwidth) * 1000.0 * float(self.queuing_delay) / 8)
|
(float(self.bandwidth) * 1000.0 * float(self.queuing_delay) / 8)
|
||||||
|
|
||||||
def extract_queuing_delay(self, queue_size, bandwidth, delay, mtu=1500):
|
def extract_queuing_delay(self, queue_size, bandwidth, delay, mtu=1500):
|
||||||
queuing_delay = (int(queue_size) * int(mtu) * 8.0 * 1000.0) / \
|
queuing_delay = (int(queue_size) * int(mtu) * 8.0 * 1000.0) / \
|
||||||
(float(bandwidth) * 1024 * 1024)
|
(float(bandwidth) * 1024 * 1024)
|
||||||
return max(int(queuing_delay), 1)
|
return max(int(queuing_delay), 1)
|
||||||
|
|
||||||
def add_netem_at(self, n):
|
def add_netem_at(self, n):
|
||||||
@ -79,7 +82,8 @@ class LinkCharacteristics(object):
|
|||||||
n.delta = n.at - self.netem_at[-1].at
|
n.delta = n.at - self.netem_at[-1].at
|
||||||
self.netem_at.append(n)
|
self.netem_at.append(n)
|
||||||
else:
|
else:
|
||||||
logging.error("{}: not taken into account because not specified in order in the topo param file".format(n))
|
logging.error(
|
||||||
|
"{}: not taken into account because not specified in order in the topo param file".format(n))
|
||||||
|
|
||||||
def build_delete_tc_cmd(self, ifname):
|
def build_delete_tc_cmd(self, ifname):
|
||||||
return "tc qdisc del dev {} root; tc qdisc del dev {} ingress ".format(ifname, ifname)
|
return "tc qdisc del dev {} root; tc qdisc del dev {} ingress ".format(ifname, ifname)
|
||||||
@ -137,11 +141,13 @@ class TopoParameter(Parameter):
|
|||||||
RIGHT_SUBNET = "rightSubnet"
|
RIGHT_SUBNET = "rightSubnet"
|
||||||
NETEM_AT = "netemAt_"
|
NETEM_AT = "netemAt_"
|
||||||
CHANGE_NETEM = "changeNetem"
|
CHANGE_NETEM = "changeNetem"
|
||||||
|
CLIENTS = "clients"
|
||||||
|
|
||||||
DEFAULT_PARAMETERS = {
|
DEFAULT_PARAMETERS = {
|
||||||
LEFT_SUBNET: "10.1.",
|
LEFT_SUBNET: "10.1.",
|
||||||
RIGHT_SUBNET: "10.2.",
|
RIGHT_SUBNET: "10.2.",
|
||||||
CHANGE_NETEM: "false",
|
CHANGE_NETEM: "false",
|
||||||
|
CLIENTS: "1",
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, parameter_filename):
|
def __init__(self, parameter_filename):
|
||||||
@ -150,6 +156,7 @@ class TopoParameter(Parameter):
|
|||||||
self.link_characteristics = []
|
self.link_characteristics = []
|
||||||
self.load_link_characteristics()
|
self.load_link_characteristics()
|
||||||
self.load_netem_at()
|
self.load_netem_at()
|
||||||
|
self.load_clients()
|
||||||
logging.info(self)
|
logging.info(self)
|
||||||
|
|
||||||
def parse_netem_at(self, key):
|
def parse_netem_at(self, key):
|
||||||
@ -161,13 +168,23 @@ class TopoParameter(Parameter):
|
|||||||
_, link_type, link_id = key.split("_")
|
_, link_type, link_id = key.split("_")
|
||||||
return link_type, int(link_id)
|
return link_type, int(link_id)
|
||||||
|
|
||||||
|
def load_clients(self):
|
||||||
|
for k in sorted(self.parameters):
|
||||||
|
if k == 'clients':
|
||||||
|
self._clients = int(self.parameters[k])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def clients(self):
|
||||||
|
return self._clients
|
||||||
|
|
||||||
def load_netem_at(self):
|
def load_netem_at(self):
|
||||||
if not self.get(TopoParameter.CHANGE_NETEM) == "yes":
|
if not self.get(TopoParameter.CHANGE_NETEM) == "yes":
|
||||||
return
|
return
|
||||||
for k in sorted(self.parameters):
|
for k in sorted(self.parameters):
|
||||||
if k.startswith(TopoParameter.NETEM_AT):
|
if k.startswith(TopoParameter.NETEM_AT):
|
||||||
link_type, link_id = self.parse_netem_at(k)
|
link_type, link_id = self.parse_netem_at(k)
|
||||||
self.load_netem_at_value(link_type, link_id, self.parameters[k])
|
self.load_netem_at_value(
|
||||||
|
link_type, link_id, self.parameters[k])
|
||||||
|
|
||||||
def find_link_characteristic(self, link_type, link_id):
|
def find_link_characteristic(self, link_type, link_id):
|
||||||
for l in self.link_characteristics:
|
for l in self.link_characteristics:
|
||||||
@ -184,7 +201,8 @@ class TopoParameter(Parameter):
|
|||||||
l.add_netem_at(na)
|
l.add_netem_at(na)
|
||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logging.error("Unable to set netem for link {} with command {}: {}".format(link_id, n, e))
|
logging.error(
|
||||||
|
"Unable to set netem for link {} with command {}: {}".format(link_id, n, e))
|
||||||
|
|
||||||
logging.info(self.link_characteristics[link_id].netem_at)
|
logging.info(self.link_characteristics[link_id].netem_at)
|
||||||
|
|
||||||
@ -243,7 +261,7 @@ class TopoParameter(Parameter):
|
|||||||
logging.error("Ignored path {}: {}".format(k, e))
|
logging.error("Ignored path {}: {}".format(k, e))
|
||||||
else:
|
else:
|
||||||
path = LinkCharacteristics(link_id, link_type, delay, queue_size,
|
path = LinkCharacteristics(link_id, link_type, delay, queue_size,
|
||||||
bw, loss_perc, backup=is_backup)
|
bw, loss_perc, backup=is_backup)
|
||||||
self.link_characteristics.append(path)
|
self.link_characteristics.append(path)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@ -281,8 +299,8 @@ class BottleneckLink(object):
|
|||||||
topo_builder.add_link(self.bs2, self.bs3)
|
topo_builder.add_link(self.bs2, self.bs3)
|
||||||
|
|
||||||
def get_bs_name(self, index):
|
def get_bs_name(self, index):
|
||||||
return "{}_{}_{}_{}".format(BottleneckLink.BOTTLENECK_SWITCH_NAME_PREFIX,
|
return "{}_{}_{}_{}".format(BottleneckLink.BOTTLENECK_SWITCH_NAME_PREFIX,
|
||||||
self.link_characteristics.link_type, self.link_characteristics.id, index)
|
self.link_characteristics.link_type, self.link_characteristics.id, index)
|
||||||
|
|
||||||
def reinit_variables(self):
|
def reinit_variables(self):
|
||||||
# Required to retrieve actual nodes
|
# Required to retrieve actual nodes
|
||||||
@ -297,30 +315,34 @@ class BottleneckLink(object):
|
|||||||
|
|
||||||
# Cleanup tc commands
|
# Cleanup tc commands
|
||||||
for bs1_ifname in bs1_interface_names:
|
for bs1_ifname in bs1_interface_names:
|
||||||
clean_cmd = self.link_characteristics.build_delete_tc_cmd(bs1_ifname)
|
clean_cmd = self.link_characteristics.build_delete_tc_cmd(
|
||||||
|
bs1_ifname)
|
||||||
logging.info(clean_cmd)
|
logging.info(clean_cmd)
|
||||||
self.topo.command_to(self.bs1, clean_cmd)
|
self.topo.command_to(self.bs1, clean_cmd)
|
||||||
|
|
||||||
for bs2_ifname in bs2_interface_names:
|
for bs2_ifname in bs2_interface_names:
|
||||||
clean_cmd = self.link_characteristics.build_delete_tc_cmd(bs2_ifname)
|
clean_cmd = self.link_characteristics.build_delete_tc_cmd(
|
||||||
|
bs2_ifname)
|
||||||
logging.info(clean_cmd)
|
logging.info(clean_cmd)
|
||||||
self.topo.command_to(self.bs2, clean_cmd)
|
self.topo.command_to(self.bs2, clean_cmd)
|
||||||
|
|
||||||
# Flow bs0 -> bs3
|
# Flow bs0 -> bs3
|
||||||
netem_cmd = self.link_characteristics.build_netem_cmd(bs1_interface_names[-1],
|
netem_cmd = self.link_characteristics.build_netem_cmd(bs1_interface_names[-1],
|
||||||
"loss {}".format(self.link_characteristics.loss) if float(self.link_characteristics.loss) > 0 else "")
|
"loss {}".format(self.link_characteristics.loss) if float(self.link_characteristics.loss) > 0 else "")
|
||||||
logging.info(netem_cmd)
|
logging.info(netem_cmd)
|
||||||
self.topo.command_to(self.bs1, netem_cmd)
|
self.topo.command_to(self.bs1, netem_cmd)
|
||||||
shaping_cmd = self.link_characteristics.build_bandwidth_cmd(bs2_interface_names[-1])
|
shaping_cmd = self.link_characteristics.build_bandwidth_cmd(
|
||||||
|
bs2_interface_names[-1])
|
||||||
logging.info(shaping_cmd)
|
logging.info(shaping_cmd)
|
||||||
self.topo.command_to(self.bs2, shaping_cmd)
|
self.topo.command_to(self.bs2, shaping_cmd)
|
||||||
|
|
||||||
# Flow bs3 -> bs0
|
# Flow bs3 -> bs0
|
||||||
netem_cmd = self.link_characteristics.build_netem_cmd(bs2_interface_names[0],
|
netem_cmd = self.link_characteristics.build_netem_cmd(bs2_interface_names[0],
|
||||||
"loss {}".format(self.link_characteristics.loss) if float(self.link_characteristics.loss) > 0 else "")
|
"loss {}".format(self.link_characteristics.loss) if float(self.link_characteristics.loss) > 0 else "")
|
||||||
logging.info(netem_cmd)
|
logging.info(netem_cmd)
|
||||||
self.topo.command_to(self.bs2, netem_cmd)
|
self.topo.command_to(self.bs2, netem_cmd)
|
||||||
shaping_cmd = self.link_characteristics.build_bandwidth_cmd(bs1_interface_names[0])
|
shaping_cmd = self.link_characteristics.build_bandwidth_cmd(
|
||||||
|
bs1_interface_names[0])
|
||||||
logging.info(shaping_cmd)
|
logging.info(shaping_cmd)
|
||||||
self.topo.command_to(self.bs1, shaping_cmd)
|
self.topo.command_to(self.bs1, shaping_cmd)
|
||||||
|
|
||||||
@ -328,18 +350,22 @@ class BottleneckLink(object):
|
|||||||
bs1_interface_names = self.topo.get_interface_names(self.bs1)
|
bs1_interface_names = self.topo.get_interface_names(self.bs1)
|
||||||
bs2_interface_names = self.topo.get_interface_names(self.bs2)
|
bs2_interface_names = self.topo.get_interface_names(self.bs2)
|
||||||
# Flow bs0 -> bs3
|
# Flow bs0 -> bs3
|
||||||
shaping_cmd = self.link_characteristics.build_changing_bandwidth_cmd(bs1_interface_names[-1])
|
shaping_cmd = self.link_characteristics.build_changing_bandwidth_cmd(
|
||||||
|
bs1_interface_names[-1])
|
||||||
logging.info(shaping_cmd)
|
logging.info(shaping_cmd)
|
||||||
self.topo.command_to(self.bs1, shaping_cmd)
|
self.topo.command_to(self.bs1, shaping_cmd)
|
||||||
netem_cmd = self.link_characteristics.build_changing_netem_cmd(bs2_interface_names[-1])
|
netem_cmd = self.link_characteristics.build_changing_netem_cmd(
|
||||||
|
bs2_interface_names[-1])
|
||||||
logging.info(netem_cmd)
|
logging.info(netem_cmd)
|
||||||
self.topo.command_to(self.bs2, netem_cmd)
|
self.topo.command_to(self.bs2, netem_cmd)
|
||||||
|
|
||||||
# Flow bs3 -> bs0
|
# Flow bs3 -> bs0
|
||||||
shaping_cmd = self.link_characteristics.build_changing_bandwidth_cmd(bs2_interface_names[0])
|
shaping_cmd = self.link_characteristics.build_changing_bandwidth_cmd(
|
||||||
|
bs2_interface_names[0])
|
||||||
logging.info(shaping_cmd)
|
logging.info(shaping_cmd)
|
||||||
self.topo.command_to(self.bs2, shaping_cmd)
|
self.topo.command_to(self.bs2, shaping_cmd)
|
||||||
netem_cmd = self.link_characteristics.build_changing_netem_cmd(bs1_interface_names[0])
|
netem_cmd = self.link_characteristics.build_changing_netem_cmd(
|
||||||
|
bs1_interface_names[0])
|
||||||
logging.info(netem_cmd)
|
logging.info(netem_cmd)
|
||||||
self.topo.command_to(self.bs1, netem_cmd)
|
self.topo.command_to(self.bs1, netem_cmd)
|
||||||
|
|
||||||
@ -380,7 +406,8 @@ class Topo(object):
|
|||||||
def __init__(self, topo_builder, topo_parameter):
|
def __init__(self, topo_builder, topo_parameter):
|
||||||
self.topo_builder = topo_builder
|
self.topo_builder = topo_builder
|
||||||
self.topo_parameter = topo_parameter
|
self.topo_parameter = topo_parameter
|
||||||
self.change_netem = topo_parameter.get(TopoParameter.CHANGE_NETEM).lower() == "yes"
|
self.change_netem = topo_parameter.get(
|
||||||
|
TopoParameter.CHANGE_NETEM).lower() == "yes"
|
||||||
self.log_file = open(Topo.CMD_LOG_FILENAME, 'w')
|
self.log_file = open(Topo.CMD_LOG_FILENAME, 'w')
|
||||||
self.clients = []
|
self.clients = []
|
||||||
self.routers = []
|
self.routers = []
|
||||||
@ -467,7 +494,8 @@ class Topo(object):
|
|||||||
otherwise just connect it to from_a and to_b and returns the bottleneck_link
|
otherwise just connect it to from_a and to_b and returns the bottleneck_link
|
||||||
"""
|
"""
|
||||||
if bottleneck_link is None:
|
if bottleneck_link is None:
|
||||||
bottleneck_link = BottleneckLink(self.topo_builder, self, link_characteristics)
|
bottleneck_link = BottleneckLink(
|
||||||
|
self.topo_builder, self, link_characteristics)
|
||||||
self.bottleneck_links.append(bottleneck_link)
|
self.bottleneck_links.append(bottleneck_link)
|
||||||
|
|
||||||
self.topo_builder.add_link(from_a, bottleneck_link.get_left())
|
self.topo_builder.add_link(from_a, bottleneck_link.get_left())
|
||||||
@ -476,9 +504,12 @@ class Topo(object):
|
|||||||
|
|
||||||
def reinit_variables(self):
|
def reinit_variables(self):
|
||||||
# Because we create nodes before starting mininet
|
# Because we create nodes before starting mininet
|
||||||
self.clients = [self.get_host(self.get_client_name(i)) for i in range(len(self.clients))]
|
self.clients = [self.get_host(self.get_client_name(i))
|
||||||
self.routers = [self.get_host(self.get_router_name(i)) for i in range(len(self.routers))]
|
for i in range(len(self.clients))]
|
||||||
self.servers = [self.get_host(self.get_server_name(i)) for i in range(len(self.servers))]
|
self.routers = [self.get_host(self.get_router_name(i))
|
||||||
|
for i in range(len(self.routers))]
|
||||||
|
self.servers = [self.get_host(self.get_server_name(i))
|
||||||
|
for i in range(len(self.servers))]
|
||||||
for b in self.bottleneck_links:
|
for b in self.bottleneck_links:
|
||||||
b.reinit_variables()
|
b.reinit_variables()
|
||||||
|
|
||||||
@ -502,6 +533,7 @@ class TopoConfig(object):
|
|||||||
This class is not instantiable as it. You must define a child class with the
|
This class is not instantiable as it. You must define a child class with the
|
||||||
`NAME` attribute.
|
`NAME` attribute.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, topo, param):
|
def __init__(self, topo, param):
|
||||||
self.topo = topo
|
self.topo = topo
|
||||||
self.param = param
|
self.param = param
|
||||||
@ -520,8 +552,10 @@ class TopoConfig(object):
|
|||||||
logging.info("Disable TSO, GSO and GRO on all interfaces of all nodes")
|
logging.info("Disable TSO, GSO and GRO on all interfaces of all nodes")
|
||||||
for node in [self.topo.get_host(n) for n in self.topo.topo_builder.net]:
|
for node in [self.topo.get_host(n) for n in self.topo.topo_builder.net]:
|
||||||
for intf in self.topo.get_interface_names(node):
|
for intf in self.topo.get_interface_names(node):
|
||||||
logging.debug("Disable TSO, GSO and GRO on interface {}".format(intf))
|
logging.debug(
|
||||||
cmd = "ethtool -K {} tso off; ethtool -K {} gso off; ethtool -K {} gro off".format(intf, intf, intf)
|
"Disable TSO, GSO and GRO on interface {}".format(intf))
|
||||||
|
cmd = "ethtool -K {} tso off; ethtool -K {} gso off; ethtool -K {} gro off".format(
|
||||||
|
intf, intf, intf)
|
||||||
logging.debug(cmd)
|
logging.debug(cmd)
|
||||||
self.topo.command_to(node, cmd)
|
self.topo.command_to(node, cmd)
|
||||||
|
|
||||||
|
88
experiments/basicquic.py
Normal file
88
experiments/basicquic.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
from core.experiment import ExperimentParameter, RandomFileExperiment, RandomFileParameter
|
||||||
|
import os
|
||||||
|
import threading
|
||||||
|
|
||||||
|
|
||||||
|
class BASICQUIC(RandomFileExperiment):
|
||||||
|
NAME = "basicquic"
|
||||||
|
SERVER_LOG = "echo-quic_server.log"
|
||||||
|
CLIENT_LOG = "echo-quic_client.log"
|
||||||
|
WGET_BIN = "wget"
|
||||||
|
PING_OUTPUT = "ping.log"
|
||||||
|
|
||||||
|
def __init__(self, experiment_parameter_filename, topo, topo_config):
|
||||||
|
# Just rely on RandomFileExperiment
|
||||||
|
super(BASICQUIC, self).__init__(
|
||||||
|
experiment_parameter_filename, topo, topo_config)
|
||||||
|
|
||||||
|
def load_parameters(self):
|
||||||
|
# Just rely on RandomFileExperiment
|
||||||
|
super(BASICQUIC, self).load_parameters()
|
||||||
|
|
||||||
|
def prepare(self):
|
||||||
|
super(BASICQUIC, self).prepare()
|
||||||
|
self.topo.command_to(self.topo_config.client, "rm " +
|
||||||
|
BASICQUIC.CLIENT_LOG)
|
||||||
|
self.topo.command_to(self.topo_config.server, "rm " +
|
||||||
|
BASICQUIC.SERVER_LOG)
|
||||||
|
|
||||||
|
def getHTTPSServerCmd(self):
|
||||||
|
# s = "{}/../utils/server".format(
|
||||||
|
# os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
s = "/home/mininet/pugit/sample/minitopo/utils/server & > {}".format(
|
||||||
|
BASICQUIC.SERVER_LOG)
|
||||||
|
|
||||||
|
print(s)
|
||||||
|
return s
|
||||||
|
|
||||||
|
def getHTTPSClientCmd(self):
|
||||||
|
# s = "ping -c 3 -I {} {} > ping-result".format(
|
||||||
|
# "10.0.0.", self.topo_config.get_client_ip(1))
|
||||||
|
|
||||||
|
# s = "{}/../utils/echo-client {} > {}".format(os.path.dirname(os.path.abspath(__file__)),
|
||||||
|
# self.topo.get_server_ip(
|
||||||
|
# 0),
|
||||||
|
# os.path.dirname(os.path.abspath(__file__)), BASICQUIC.CLIENT_LOG)
|
||||||
|
|
||||||
|
s = "/home/mininet/pugit/sample/minitopo/utils/echo-client {} & > {}".format(
|
||||||
|
self.topo_config.get_server_ip(0),
|
||||||
|
BASICQUIC.CLIENT_LOG,
|
||||||
|
)
|
||||||
|
|
||||||
|
print(s)
|
||||||
|
return s
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
super(BASICQUIC, self).clean()
|
||||||
|
|
||||||
|
def startServer(self):
|
||||||
|
self.topo.command_to(self.topo_config.server, cmd)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
cmd = self.getHTTPSServerCmd()
|
||||||
|
self.topo.command_to(self.topo_config.server,
|
||||||
|
"netstat -sn > netstat_server_before")
|
||||||
|
self.topo.command_to(self.topo_config.router,
|
||||||
|
"netstat -sn > netstat_router_before")
|
||||||
|
|
||||||
|
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 2")
|
||||||
|
# for i in range(1, self.topo.client_count()):
|
||||||
|
# self.topo.command_to(self.topo_config.clients[i], "sleep 2")
|
||||||
|
|
||||||
|
cmd = self.getHTTPSClientCmd()
|
||||||
|
# for c in self.topo_config.clients:
|
||||||
|
# self.topo.command_to(c, cmd)
|
||||||
|
for i in range(1, self.topo.client_count()):
|
||||||
|
self.topo.command_to(self.topo_config.clients[i], cmd)
|
||||||
|
# self.topo_config.configure_client(i)
|
||||||
|
|
||||||
|
self.topo.command_to(self.topo_config.server,
|
||||||
|
"netstat -sn > netstat_server_after")
|
||||||
|
self.topo.command_to(self.topo_config.router,
|
||||||
|
"netstat -sn > netstat_router_after")
|
||||||
|
self.topo.command_to(self.topo_config.server,
|
||||||
|
"pkill -f server")
|
||||||
|
self.topo.command_to(self.topo_config.client, "sleep 2")
|
@ -8,7 +8,8 @@ class IPerfScenarioParameter(ExperimentParameter):
|
|||||||
FM_SUBFLOWS = "iperfScenarioFMSublows"
|
FM_SUBFLOWS = "iperfScenarioFMSublows"
|
||||||
|
|
||||||
def __init__(self, experiment_parameter_filename):
|
def __init__(self, experiment_parameter_filename):
|
||||||
super(IPerfScenarioParameter, self).__init__(experiment_parameter_filename)
|
super(IPerfScenarioParameter, self).__init__(
|
||||||
|
experiment_parameter_filename)
|
||||||
self.default_parameters.update({
|
self.default_parameters.update({
|
||||||
IPerfScenarioParameter.FM_SUBFLOWS: "1",
|
IPerfScenarioParameter.FM_SUBFLOWS: "1",
|
||||||
})
|
})
|
||||||
@ -24,29 +25,37 @@ class IPerfScenario(Experiment):
|
|||||||
PING_OUTPUT = "ping.log"
|
PING_OUTPUT = "ping.log"
|
||||||
|
|
||||||
def __init__(self, experiment_parameter_filename, topo, topo_config):
|
def __init__(self, experiment_parameter_filename, topo, topo_config):
|
||||||
super(IPerfScenario, self).__init__(experiment_parameter_filename, topo, topo_config)
|
super(IPerfScenario, self).__init__(
|
||||||
|
experiment_parameter_filename, topo, topo_config)
|
||||||
|
|
||||||
self.load_parameters()
|
self.load_parameters()
|
||||||
self.ping()
|
self.ping()
|
||||||
|
|
||||||
def load_parameters(self):
|
def load_parameters(self):
|
||||||
super(IPerfScenario, self).load_parameters()
|
super(IPerfScenario, self).load_parameters()
|
||||||
self.fm_subflows = self.experiment_parameter.get(IPerfScenarioParameter.FM_SUBFLOWS)
|
self.fm_subflows = self.experiment_parameter.get(
|
||||||
|
IPerfScenarioParameter.FM_SUBFLOWS)
|
||||||
|
|
||||||
def prepare(self):
|
def prepare(self):
|
||||||
super(IPerfScenario, self).prepare()
|
super(IPerfScenario, self).prepare()
|
||||||
self.topo.command_to(self.topo_config.client, "rm {}".format(IPerfScenario.IPERF_LOG))
|
self.topo.command_to(self.topo_config.client,
|
||||||
self.topo.command_to(self.topo_config.server, "rm {}".format(IPerfScenario.SERVER_LOG))
|
"rm {}".format(IPerfScenario.IPERF_LOG))
|
||||||
|
self.topo.command_to(self.topo_config.server,
|
||||||
|
"rm {}".format(IPerfScenario.SERVER_LOG))
|
||||||
|
|
||||||
if not isinstance(self.topo, MultiInterfaceMultiClientTopo):
|
if not isinstance(self.topo, MultiInterfaceMultiClientTopo):
|
||||||
raise Exception("IPerfScenario only runs with MultiInterfaceMultiClientTopo")
|
raise Exception(
|
||||||
|
"IPerfScenario only runs with MultiInterfaceMultiClientTopo")
|
||||||
|
|
||||||
def get_client_iperf_cmd(self, server_ip, time, client_id):
|
def get_client_iperf_cmd(self, server_ip, time, client_id):
|
||||||
s = "{} -c {} -t {} -P 1 -i 5 &>{}{}".format(IPerfScenario.IPERF_BIN, server_ip, time, IPerfScenario.IPERF_LOG, client_id)
|
s = "{} -c {} -t {} -P 1 -i 5 &>{}{}".format(
|
||||||
|
IPerfScenario.IPERF_BIN, server_ip, time, IPerfScenario.IPERF_LOG, client_id)
|
||||||
logging.info(s)
|
logging.info(s)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def get_server_cmd(self, server_id=0):
|
def get_server_cmd(self, server_id=0):
|
||||||
s = "{} -s &> {}{} &".format(IPerfScenario.IPERF_BIN, IPerfScenario.SERVER_LOG, server_id)
|
s = "{} -s &> {}{} &".format(IPerfScenario.IPERF_BIN,
|
||||||
|
IPerfScenario.SERVER_LOG, server_id)
|
||||||
logging.info(s)
|
logging.info(s)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
@ -54,32 +63,39 @@ class IPerfScenario(Experiment):
|
|||||||
super(IPerfScenario, self).clean()
|
super(IPerfScenario, self).clean()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
print('IPerfScenario!!!!!!')
|
||||||
self.topo.command_to(self.topo_config.router, "tcpdump -i any -w router.pcap &")
|
self.topo.command_to(self.topo_config.router,
|
||||||
|
"tcpdump -i any -w router.pcap &")
|
||||||
# First run servers
|
# First run servers
|
||||||
for l, s in enumerate(self.topo_config.servers):
|
for l, s in enumerate(self.topo_config.servers):
|
||||||
self.topo.command_to(s, self.get_server_cmd(server_id=l))
|
self.topo.command_to(s, self.get_server_cmd(server_id=l))
|
||||||
|
|
||||||
# And set nb of subflows for fullmesh
|
# And set nb of subflows for fullmesh
|
||||||
self.topo.command_to(self.topo_config.client, "echo {} > /sys/module/mptcp_fullmesh/parameters/num_subflows".format(self.fm_subflows))
|
self.topo.command_to(
|
||||||
|
self.topo_config.client, "echo {} > /sys/module/mptcp_fullmesh/parameters/num_subflows".format(self.fm_subflows))
|
||||||
|
|
||||||
self.topo.command_to(self.topo_config.client, "sleep 2")
|
self.topo.command_to(self.topo_config.client, "sleep 2")
|
||||||
|
|
||||||
# We run as follow.
|
# We run as follow.
|
||||||
logging.info("This experiment last about 1 minute. Please wait...")
|
logging.info("This experiment last about 1 minute. Please wait...")
|
||||||
cmd = "sleep 10 && {} &".format(self.get_client_iperf_cmd(self.topo_config.get_server_ip(interface_index=1), 20, 1))
|
cmd = "sleep 10 && {} &".format(self.get_client_iperf_cmd(
|
||||||
|
self.topo_config.get_server_ip(interface_index=1), 20, 1))
|
||||||
self.topo.command_to(self.topo_config.clients[1], cmd)
|
self.topo.command_to(self.topo_config.clients[1], cmd)
|
||||||
cmd = "sleep 20 && {} &".format(self.get_client_iperf_cmd(self.topo_config.get_server_ip(interface_index=2), 20, 2))
|
cmd = "sleep 20 && {} &".format(self.get_client_iperf_cmd(
|
||||||
|
self.topo_config.get_server_ip(interface_index=2), 20, 2))
|
||||||
self.topo.command_to(self.topo_config.clients[2], cmd)
|
self.topo.command_to(self.topo_config.clients[2], cmd)
|
||||||
cmd = "{} &".format(self.get_client_iperf_cmd(self.topo_config.get_server_ip(), 50, 0))
|
cmd = "{} &".format(self.get_client_iperf_cmd(
|
||||||
|
self.topo_config.get_server_ip(), 50, 0))
|
||||||
self.topo.command_to(self.topo_config.client, cmd)
|
self.topo.command_to(self.topo_config.client, cmd)
|
||||||
|
|
||||||
self.topo.command_to(self.topo_config.client, "sleep 2")
|
self.topo.command_to(self.topo_config.client, "sleep 2")
|
||||||
|
|
||||||
# This is hacky
|
# This is hacky
|
||||||
self.topo.command_global("sysctl -w net.mptcp.mptcp_enabled=0")
|
self.topo.command_global("sysctl -w net.mptcp.mptcp_enabled=0")
|
||||||
self.topo.command_global("sysctl -w net.ipv4.tcp_congestion_control=reno")
|
self.topo.command_global(
|
||||||
|
"sysctl -w net.ipv4.tcp_congestion_control=reno")
|
||||||
|
|
||||||
self.topo.command_to(self.topo_config.client, "sleep 50")
|
self.topo.command_to(self.topo_config.client, "sleep 50")
|
||||||
|
|
||||||
self.topo.command_to(self.topo_config.client, "echo 1 > /sys/module/mptcp_fullmesh/parameters/num_subflows")
|
self.topo.command_to(
|
||||||
|
self.topo_config.client, "echo 1 > /sys/module/mptcp_fullmesh/parameters/num_subflows")
|
||||||
|
BIN
mptcp_debs/linux-headers-4.1.39+_4.1.39+-81_amd64.deb
Normal file
BIN
mptcp_debs/linux-headers-4.1.39+_4.1.39+-81_amd64.deb
Normal file
Binary file not shown.
BIN
mptcp_debs/linux-image-4.1.39+-dbg_4.1.39+-81_amd64.deb
Normal file
BIN
mptcp_debs/linux-image-4.1.39+-dbg_4.1.39+-81_amd64.deb
Normal file
Binary file not shown.
BIN
mptcp_debs/linux-image-4.1.39+_4.1.39+-81_amd64.deb
Normal file
BIN
mptcp_debs/linux-image-4.1.39+_4.1.39+-81_amd64.deb
Normal file
Binary file not shown.
BIN
mptcp_debs/linux-libc-dev_4.1.39+-81_amd64.deb
Normal file
BIN
mptcp_debs/linux-libc-dev_4.1.39+-81_amd64.deb
Normal file
Binary file not shown.
30
runner.py
30
runner.py
@ -14,15 +14,18 @@ import os
|
|||||||
import subprocess
|
import subprocess
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
def get_git_revision_short_hash():
|
def get_git_revision_short_hash():
|
||||||
# Because we might run Minitopo from elsewhere.
|
# Because we might run Minitopo from elsewhere.
|
||||||
curr_dir = os.getcwd()
|
curr_dir = os.getcwd()
|
||||||
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
os.chdir(ROOT_DIR)
|
os.chdir(ROOT_DIR)
|
||||||
ret = subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']).decode("unicode_escape").strip()
|
ret = subprocess.check_output(
|
||||||
|
['git', 'rev-parse', '--short', 'HEAD']).decode("unicode_escape").strip()
|
||||||
os.chdir(curr_dir)
|
os.chdir(curr_dir)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class Runner(object):
|
class Runner(object):
|
||||||
"""
|
"""
|
||||||
Run an experiment described by `experiment_parameter_file` in the topology
|
Run an experiment described by `experiment_parameter_file` in the topology
|
||||||
@ -31,8 +34,10 @@ class Runner(object):
|
|||||||
|
|
||||||
All the operations are done when calling the constructor.
|
All the operations are done when calling the constructor.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, builder_type, topo_parameter_file, experiment_parameter_file):
|
def __init__(self, builder_type, topo_parameter_file, experiment_parameter_file):
|
||||||
logging.info("Minitopo version {}".format(get_git_revision_short_hash()))
|
logging.info("Minitopo version {}".format(
|
||||||
|
get_git_revision_short_hash()))
|
||||||
self.topo_parameter = TopoParameter(topo_parameter_file)
|
self.topo_parameter = TopoParameter(topo_parameter_file)
|
||||||
self.set_builder(builder_type)
|
self.set_builder(builder_type)
|
||||||
self.apply_topo()
|
self.apply_topo()
|
||||||
@ -48,7 +53,8 @@ class Runner(object):
|
|||||||
if builder_type == Topo.MININET_BUILDER:
|
if builder_type == Topo.MININET_BUILDER:
|
||||||
self.topo_builder = MininetBuilder()
|
self.topo_builder = MininetBuilder()
|
||||||
else:
|
else:
|
||||||
raise Exception("I can not find the builder {}".format(builder_type))
|
raise Exception(
|
||||||
|
"I can not find the builder {}".format(builder_type))
|
||||||
|
|
||||||
def apply_topo(self):
|
def apply_topo(self):
|
||||||
"""
|
"""
|
||||||
@ -86,9 +92,11 @@ class Runner(object):
|
|||||||
Match the name of the experiement and launch it
|
Match the name of the experiement and launch it
|
||||||
"""
|
"""
|
||||||
# Well, we need to load twice the experiment parameters, is it really annoying?
|
# Well, we need to load twice the experiment parameters, is it really annoying?
|
||||||
xp = ExperimentParameter(experiment_parameter_file).get(ExperimentParameter.XP_TYPE)
|
xp = ExperimentParameter(experiment_parameter_file).get(
|
||||||
|
ExperimentParameter.XP_TYPE)
|
||||||
if xp in EXPERIMENTS:
|
if xp in EXPERIMENTS:
|
||||||
exp = EXPERIMENTS[xp](experiment_parameter_file, self.topo, self.topo_config)
|
exp = EXPERIMENTS[xp](experiment_parameter_file,
|
||||||
|
self.topo, self.topo_config)
|
||||||
exp.classic_run()
|
exp.classic_run()
|
||||||
else:
|
else:
|
||||||
raise Exception("Unknown experiment {}".format(xp))
|
raise Exception("Unknown experiment {}".format(xp))
|
||||||
@ -107,21 +115,23 @@ if __name__ == '__main__':
|
|||||||
description="Minitopo, a wrapper of Mininet to run multipath experiments")
|
description="Minitopo, a wrapper of Mininet to run multipath experiments")
|
||||||
|
|
||||||
parser.add_argument("--topo_param_file", "-t", required=True,
|
parser.add_argument("--topo_param_file", "-t", required=True,
|
||||||
help="path to the topo parameter file")
|
help="path to the topo parameter file")
|
||||||
parser.add_argument("--experiment_param_file", "-x",
|
parser.add_argument("--experiment_param_file", "-x",
|
||||||
help="path to the experiment parameter file")
|
help="path to the experiment parameter file")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
logging.basicConfig(format="%(asctime)-15s [%(levelname)s] %(funcName)s: %(message)s", level=logging.INFO)
|
logging.basicConfig(
|
||||||
|
format="%(asctime)-15s [%(levelname)s] %(funcName)s: %(message)s", level=logging.INFO)
|
||||||
|
|
||||||
# XXX Currently, there is no alternate topo builder...
|
# XXX Currently, there is no alternate topo builder...
|
||||||
try:
|
try:
|
||||||
Runner(Topo.MININET_BUILDER, args.topo_param_file, args.experiment_param_file)
|
Runner(Topo.MININET_BUILDER, args.topo_param_file,
|
||||||
|
args.experiment_param_file)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.fatal("A fatal error occurred: {}".format(e))
|
logging.fatal("A fatal error occurred: {}".format(e))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
finally:
|
finally:
|
||||||
# Always cleanup Mininet
|
# Always cleanup Mininet
|
||||||
logging.info("cleanup mininet")
|
logging.info("cleanup mininet")
|
||||||
cleanup()
|
cleanup()
|
||||||
|
128
topos/iot_multi_client.py
Normal file
128
topos/iot_multi_client.py
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
from core.topo import TopoParameter
|
||||||
|
from .multi_interface import MultiInterfaceTopo, MultiInterfaceConfig
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
class IoTMultiClientTopo(MultiInterfaceTopo):
|
||||||
|
NAME = "IoTMultiClient"
|
||||||
|
|
||||||
|
def __init__(self, topo_builder, parameterFile):
|
||||||
|
logging.info("Initializing IoTMultiClientTopo...")
|
||||||
|
super(IoTMultiClientTopo, self).__init__(
|
||||||
|
topo_builder, parameterFile)
|
||||||
|
|
||||||
|
for i in range(self.topo_parameter.clients):
|
||||||
|
# For each client-router, add a client, a bottleneck link, and a server
|
||||||
|
self.add_client_with_link()
|
||||||
|
|
||||||
|
# And connect the router to all servers
|
||||||
|
# for s in self.servers[1:]:
|
||||||
|
# self.add_link(self.router, s)
|
||||||
|
|
||||||
|
def add_client_with_link(self):
|
||||||
|
client = self.add_client()
|
||||||
|
for bl in self.c2r_links:
|
||||||
|
self.add_link(client, bl.get_left())
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
s = "IoT Multiple interface topology with several clients and servers\n"
|
||||||
|
# i = 0
|
||||||
|
# nc = len(self.get_client_to_router_links())
|
||||||
|
# for i in range(0, nc):
|
||||||
|
# if i == nc // 2:
|
||||||
|
# s = s + "c- r--s\n"
|
||||||
|
# s = s + "c-\sw---bl---sw-/ \-s\n"
|
||||||
|
# else:
|
||||||
|
# s = s + "c-/sw---bl---sw-\ /-s\n"
|
||||||
|
|
||||||
|
print(self.client_count)
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
class IoTMultiClientConfig(MultiInterfaceConfig):
|
||||||
|
NAME = "IoTMultiClient"
|
||||||
|
|
||||||
|
def __init__(self, topo, param):
|
||||||
|
super(IoTMultiClientConfig, self).__init__(topo, param)
|
||||||
|
|
||||||
|
def configure_routing(self):
|
||||||
|
super(IoTMultiClientConfig, self).configure_routing()
|
||||||
|
for ci in range(len(self.clients)):
|
||||||
|
for i, _ in enumerate(self.topo.c2r_links):
|
||||||
|
# Routing for the congestion client
|
||||||
|
cmd = self.add_global_default_route_command(self.get_router_ip_to_client_switch(i),
|
||||||
|
self.get_client_interface(ci, i))
|
||||||
|
self.topo.command_to(self.clients[ci], cmd)
|
||||||
|
|
||||||
|
for i, s in enumerate(self.topo.servers):
|
||||||
|
# Routing for the congestion server
|
||||||
|
cmd = self.add_simple_default_route_command(
|
||||||
|
self.get_router_ip_to_server_switch(i))
|
||||||
|
self.topo.command_to(s, cmd)
|
||||||
|
|
||||||
|
def configure_interfaces(self):
|
||||||
|
logging.info(
|
||||||
|
"Configure interfaces using IoTMultiClientConfig...")
|
||||||
|
super(IoTMultiClientConfig, self).configure_interfaces()
|
||||||
|
self.clients = [self.topo.get_client(
|
||||||
|
i) for i in range(0, self.topo.client_count())]
|
||||||
|
self.servers = [self.topo.get_server(
|
||||||
|
i) for i in range(0, self.topo.server_count())]
|
||||||
|
netmask = "255.255.255.0"
|
||||||
|
for ci in range(len(self.clients)):
|
||||||
|
self.configure_client(ci)
|
||||||
|
# for i, _ in enumerate(self.topo.c2r_links):
|
||||||
|
# # Congestion client
|
||||||
|
# cmd = self.interface_up_command(self.get_client_interface(
|
||||||
|
# ci, i), self.get_client_ip(i, ci), netmask)
|
||||||
|
# self.topo.command_to(self.clients[ci], cmd)
|
||||||
|
# client_interface_mac = self.clients[ci].intf(
|
||||||
|
# self.get_client_interface(ci, i)).MAC()
|
||||||
|
# self.topo.command_to(self.router, "arp -s {} {}".format(
|
||||||
|
# self.get_client_ip(i, ci), client_interface_mac))
|
||||||
|
|
||||||
|
# router_interface_mac = self.router.intf(
|
||||||
|
# self.get_router_interface_to_client_switch(i)).MAC()
|
||||||
|
# # Congestion client
|
||||||
|
# self.topo.command_to(self.clients[ci], "arp -s {} {}".format(
|
||||||
|
# self.get_router_ip_to_client_switch(i), router_interface_mac))
|
||||||
|
|
||||||
|
for i, s in enumerate(self.servers):
|
||||||
|
cmd = self.interface_up_command(self.get_router_interface_to_server_switch(i),
|
||||||
|
self.get_router_ip_to_server_switch(i), netmask)
|
||||||
|
self.topo.command_to(self.router, cmd)
|
||||||
|
router_interface_mac = self.router.intf(
|
||||||
|
self.get_router_interface_to_server_switch(i)).MAC()
|
||||||
|
self.topo.command_to(s, "arp -s {} {}".format(
|
||||||
|
self.get_router_ip_to_server_switch(i), router_interface_mac))
|
||||||
|
cmd = self.interface_up_command(self.get_server_interface(
|
||||||
|
i, 0), self.get_server_ip(interface_index=i), netmask)
|
||||||
|
self.topo.command_to(s, cmd)
|
||||||
|
server_interface_mac = s.intf(
|
||||||
|
self.get_server_interface(i, 0)).MAC()
|
||||||
|
self.topo.command_to(self.router, "arp -s {} {}".format(
|
||||||
|
self.get_server_ip(interface_index=i), server_interface_mac))
|
||||||
|
|
||||||
|
def configure_client(self, ci):
|
||||||
|
netmask = "255.255.255.0"
|
||||||
|
for i, _ in enumerate(self.topo.c2r_links):
|
||||||
|
# Congestion client
|
||||||
|
cmd = self.interface_up_command(self.get_client_interface(
|
||||||
|
ci, i), self.get_client_ip(i, ci), netmask)
|
||||||
|
self.topo.command_to(self.clients[ci], cmd)
|
||||||
|
client_interface_mac = self.clients[ci].intf(
|
||||||
|
self.get_client_interface(ci, i)).MAC()
|
||||||
|
self.topo.command_to(self.router, "arp -s {} {}".format(
|
||||||
|
self.get_client_ip(i, ci), client_interface_mac))
|
||||||
|
|
||||||
|
router_interface_mac = self.router.intf(
|
||||||
|
self.get_router_interface_to_client_switch(i)).MAC()
|
||||||
|
# Congestion client
|
||||||
|
self.topo.command_to(self.clients[ci], "arp -s {} {}".format(
|
||||||
|
self.get_router_ip_to_client_switch(i), router_interface_mac))
|
||||||
|
|
||||||
|
def get_client_ip(self, interface_index, client_index=100):
|
||||||
|
return "{}{}.{}".format(self.param.get(TopoParameter.LEFT_SUBNET), interface_index, 5+client_index)
|
||||||
|
|
||||||
|
def server_interface_count(self):
|
||||||
|
return max(len(self.servers), 1)
|
@ -16,15 +16,16 @@ class MultiInterfaceTopo(Topo):
|
|||||||
|
|
||||||
# Add client - router links
|
# Add client - router links
|
||||||
for l in self.get_client_to_router_links():
|
for l in self.get_client_to_router_links():
|
||||||
self.c2r_links.append(self.add_bottleneck_link(self.client, self.router, link_characteristics=l))
|
self.c2r_links.append(self.add_bottleneck_link(
|
||||||
|
self.client, self.router, link_characteristics=l))
|
||||||
|
|
||||||
# Special case: if there is no specified link between router and server, directly connect them!
|
# Special case: if there is no specified link between router and server, directly connect them!
|
||||||
if len(self.get_router_to_server_links()) > 0:
|
if len(self.get_router_to_server_links()) > 0:
|
||||||
for l in self.get_router_to_server_links():
|
for l in self.get_router_to_server_links():
|
||||||
self.r2s_links.append(self.add_bottleneck_link(self.router, self.server, link_characteristics=l))
|
self.r2s_links.append(self.add_bottleneck_link(
|
||||||
|
self.router, self.server, link_characteristics=l))
|
||||||
else:
|
else:
|
||||||
self.add_link(self.router, self.server)
|
self.add_link(self.router, self.server)
|
||||||
|
|
||||||
|
|
||||||
def get_client_to_router_links(self):
|
def get_client_to_router_links(self):
|
||||||
return [l for l in self.topo_parameter.link_characteristics if l.link_type == "c2r"]
|
return [l for l in self.topo_parameter.link_characteristics if l.link_type == "c2r"]
|
||||||
@ -65,7 +66,7 @@ class MultiInterfaceTopo(Topo):
|
|||||||
else:
|
else:
|
||||||
s = s + " \-sw---bl---sw-/ \n"
|
s = s + " \-sw---bl---sw-/ \n"
|
||||||
skipped += 1
|
skipped += 1
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
@ -81,12 +82,12 @@ class MultiInterfaceConfig(TopoConfig):
|
|||||||
self.topo.command_to(self.client, cmd)
|
self.topo.command_to(self.client, cmd)
|
||||||
|
|
||||||
cmd = self.add_link_scope_route_command(
|
cmd = self.add_link_scope_route_command(
|
||||||
self.get_client_subnet(i),
|
self.get_client_subnet(i),
|
||||||
self.get_client_interface(0, i), i)
|
self.get_client_interface(0, i), i)
|
||||||
self.topo.command_to(self.client, cmd)
|
self.topo.command_to(self.client, cmd)
|
||||||
|
|
||||||
cmd = self.add_table_default_route_command(self.get_router_ip_to_client_switch(i),
|
cmd = self.add_table_default_route_command(self.get_router_ip_to_client_switch(i),
|
||||||
i)
|
i)
|
||||||
self.topo.command_to(self.client, cmd)
|
self.topo.command_to(self.client, cmd)
|
||||||
|
|
||||||
for i, _ in enumerate(self.topo.r2s_links):
|
for i, _ in enumerate(self.topo.r2s_links):
|
||||||
@ -94,22 +95,22 @@ class MultiInterfaceConfig(TopoConfig):
|
|||||||
self.topo.command_to(self.server, cmd)
|
self.topo.command_to(self.server, cmd)
|
||||||
|
|
||||||
cmd = self.add_link_scope_route_command(
|
cmd = self.add_link_scope_route_command(
|
||||||
self.get_server_subnet(i),
|
self.get_server_subnet(i),
|
||||||
self.get_server_interface(0, i), i)
|
self.get_server_interface(0, i), i)
|
||||||
self.topo.command_to(self.server, cmd)
|
self.topo.command_to(self.server, cmd)
|
||||||
|
|
||||||
cmd = self.add_table_default_route_command(self.get_router_ip_to_server_switch(i),
|
cmd = self.add_table_default_route_command(self.get_router_ip_to_server_switch(i),
|
||||||
i)
|
i)
|
||||||
self.topo.command_to(self.server, cmd)
|
self.topo.command_to(self.server, cmd)
|
||||||
|
|
||||||
cmd = self.add_global_default_route_command(self.get_router_ip_to_client_switch(0),
|
cmd = self.add_global_default_route_command(self.get_router_ip_to_client_switch(0),
|
||||||
self.get_client_interface(0, 0))
|
self.get_client_interface(0, 0))
|
||||||
self.topo.command_to(self.client, cmd)
|
self.topo.command_to(self.client, cmd)
|
||||||
|
|
||||||
cmd = self.add_simple_default_route_command(self.get_router_ip_to_server_switch(0))
|
cmd = self.add_simple_default_route_command(
|
||||||
|
self.get_router_ip_to_server_switch(0))
|
||||||
self.topo.command_to(self.server, cmd)
|
self.topo.command_to(self.server, cmd)
|
||||||
|
|
||||||
|
|
||||||
def configure_interfaces(self):
|
def configure_interfaces(self):
|
||||||
logging.info("Configure interfaces using MultiInterfaceConfig...")
|
logging.info("Configure interfaces using MultiInterfaceConfig...")
|
||||||
super(MultiInterfaceConfig, self).configure_interfaces()
|
super(MultiInterfaceConfig, self).configure_interfaces()
|
||||||
@ -119,55 +120,66 @@ class MultiInterfaceConfig(TopoConfig):
|
|||||||
netmask = "255.255.255.0"
|
netmask = "255.255.255.0"
|
||||||
|
|
||||||
for i, _ in enumerate(self.topo.c2r_links):
|
for i, _ in enumerate(self.topo.c2r_links):
|
||||||
cmd = self.interface_up_command(self.get_client_interface(0, i), self.get_client_ip(i), netmask)
|
cmd = self.interface_up_command(
|
||||||
|
self.get_client_interface(0, i), self.get_client_ip(i), netmask)
|
||||||
self.topo.command_to(self.client, cmd)
|
self.topo.command_to(self.client, cmd)
|
||||||
client_interface_mac = self.client.intf(self.get_client_interface(0, i)).MAC()
|
client_interface_mac = self.client.intf(
|
||||||
self.topo.command_to(self.router, "arp -s {} {}".format(self.get_client_ip(i), client_interface_mac))
|
self.get_client_interface(0, i)).MAC()
|
||||||
|
self.topo.command_to(
|
||||||
|
self.router, "arp -s {} {}".format(self.get_client_ip(i), client_interface_mac))
|
||||||
|
|
||||||
if self.topo.get_client_to_router_links()[i].backup:
|
if self.topo.get_client_to_router_links()[i].backup:
|
||||||
cmd = self.interface_backup_command(self.get_client_interface(0, i))
|
cmd = self.interface_backup_command(
|
||||||
|
self.get_client_interface(0, i))
|
||||||
self.topo.command_to(self.client, cmd)
|
self.topo.command_to(self.client, cmd)
|
||||||
|
|
||||||
for i, _ in enumerate(self.topo.c2r_links):
|
for i, _ in enumerate(self.topo.c2r_links):
|
||||||
cmd = self.interface_up_command(self.get_router_interface_to_client_switch(i),
|
cmd = self.interface_up_command(self.get_router_interface_to_client_switch(i),
|
||||||
self.get_router_ip_to_client_switch(i), netmask)
|
self.get_router_ip_to_client_switch(i), netmask)
|
||||||
self.topo.command_to(self.router, cmd)
|
self.topo.command_to(self.router, cmd)
|
||||||
router_interface_mac = self.router.intf(self.get_router_interface_to_client_switch(i)).MAC()
|
router_interface_mac = self.router.intf(
|
||||||
|
self.get_router_interface_to_client_switch(i)).MAC()
|
||||||
self.topo.command_to(self.client, "arp -s {} {}".format(
|
self.topo.command_to(self.client, "arp -s {} {}".format(
|
||||||
self.get_router_ip_to_client_switch(i), router_interface_mac))
|
self.get_router_ip_to_client_switch(i), router_interface_mac))
|
||||||
|
|
||||||
if len(self.topo.r2s_links) == 0:
|
if len(self.topo.r2s_links) == 0:
|
||||||
# Case no server param is specified
|
# Case no server param is specified
|
||||||
cmd = self.interface_up_command(self.get_router_interface_to_server_switch(0),
|
cmd = self.interface_up_command(self.get_router_interface_to_server_switch(0),
|
||||||
self.get_router_ip_to_server_switch(0), netmask)
|
self.get_router_ip_to_server_switch(0), netmask)
|
||||||
self.topo.command_to(self.router, cmd)
|
self.topo.command_to(self.router, cmd)
|
||||||
router_interface_mac = self.router.intf(self.get_router_interface_to_server_switch(0)).MAC()
|
router_interface_mac = self.router.intf(
|
||||||
|
self.get_router_interface_to_server_switch(0)).MAC()
|
||||||
self.topo.command_to(self.server, "arp -s {} {}".format(
|
self.topo.command_to(self.server, "arp -s {} {}".format(
|
||||||
self.get_router_ip_to_server_switch(0), router_interface_mac))
|
self.get_router_ip_to_server_switch(0), router_interface_mac))
|
||||||
|
|
||||||
cmd = self.interface_up_command(self.get_server_interface(0, 0), self.get_server_ip(0), netmask)
|
cmd = self.interface_up_command(
|
||||||
|
self.get_server_interface(0, 0), self.get_server_ip(0), netmask)
|
||||||
self.topo.command_to(self.server, cmd)
|
self.topo.command_to(self.server, cmd)
|
||||||
server_interface_mac = self.server.intf(self.get_server_interface(0, 0)).MAC()
|
server_interface_mac = self.server.intf(
|
||||||
|
self.get_server_interface(0, 0)).MAC()
|
||||||
self.topo.command_to(self.router, "arp -s {} {}".format(
|
self.topo.command_to(self.router, "arp -s {} {}".format(
|
||||||
self.get_server_ip(0), server_interface_mac))
|
self.get_server_ip(0), server_interface_mac))
|
||||||
|
|
||||||
for i, _ in enumerate(self.topo.r2s_links):
|
for i, _ in enumerate(self.topo.r2s_links):
|
||||||
cmd = self.interface_up_command(self.get_router_interface_to_server_switch(i),
|
cmd = self.interface_up_command(self.get_router_interface_to_server_switch(i),
|
||||||
self.get_router_ip_to_server_switch(i), netmask)
|
self.get_router_ip_to_server_switch(i), netmask)
|
||||||
self.topo.command_to(self.router, cmd)
|
self.topo.command_to(self.router, cmd)
|
||||||
router_interface_mac = self.router.intf(self.get_router_interface_to_server_switch(i)).MAC()
|
router_interface_mac = self.router.intf(
|
||||||
|
self.get_router_interface_to_server_switch(i)).MAC()
|
||||||
self.topo.command_to(self.server, "arp -s {} {}".format(
|
self.topo.command_to(self.server, "arp -s {} {}".format(
|
||||||
self.get_router_ip_to_server_switch(i), router_interface_mac))
|
self.get_router_ip_to_server_switch(i), router_interface_mac))
|
||||||
|
|
||||||
for i, _ in enumerate(self.topo.r2s_links):
|
for i, _ in enumerate(self.topo.r2s_links):
|
||||||
cmd = self.interface_up_command(self.get_server_interface(0, i), self.get_server_ip(i), netmask)
|
cmd = self.interface_up_command(
|
||||||
|
self.get_server_interface(0, i), self.get_server_ip(i), netmask)
|
||||||
self.topo.command_to(self.server, cmd)
|
self.topo.command_to(self.server, cmd)
|
||||||
server_interface_mac = self.server.intf(self.get_server_interface(0, i)).MAC()
|
server_interface_mac = self.server.intf(
|
||||||
|
self.get_server_interface(0, i)).MAC()
|
||||||
self.topo.command_to(self.router, "arp -s {} {}".format(
|
self.topo.command_to(self.router, "arp -s {} {}".format(
|
||||||
self.get_server_ip(i), server_interface_mac))
|
self.get_server_ip(i), server_interface_mac))
|
||||||
|
|
||||||
def get_client_ip(self, interface_index):
|
def get_client_ip(self, interface_index):
|
||||||
return "{}{}.1".format(self.param.get(TopoParameter.LEFT_SUBNET), interface_index)
|
return "{}{}.5".format(self.param.get(TopoParameter.LEFT_SUBNET), interface_index)
|
||||||
|
|
||||||
def get_client_subnet(self, interface_index):
|
def get_client_subnet(self, interface_index):
|
||||||
return "{}{}.0/24".format(self.param.get(TopoParameter.LEFT_SUBNET), interface_index)
|
return "{}{}.0/24".format(self.param.get(TopoParameter.LEFT_SUBNET), interface_index)
|
||||||
@ -200,4 +212,4 @@ class MultiInterfaceConfig(TopoConfig):
|
|||||||
return "{}-eth{}".format(self.topo.get_router_name(0), interface_index)
|
return "{}-eth{}".format(self.topo.get_router_name(0), interface_index)
|
||||||
|
|
||||||
def get_server_interface(self, server_index, interface_index):
|
def get_server_interface(self, server_index, interface_index):
|
||||||
return "{}-eth{}".format(self.topo.get_server_name(server_index), interface_index)
|
return "{}-eth{}".format(self.topo.get_server_name(server_index), interface_index)
|
||||||
|
@ -8,14 +8,17 @@ class MultiInterfaceMultiClientTopo(MultiInterfaceTopo):
|
|||||||
|
|
||||||
def __init__(self, topo_builder, parameterFile):
|
def __init__(self, topo_builder, parameterFile):
|
||||||
logging.info("Initializing MultiInterfaceMultiClientTopo...")
|
logging.info("Initializing MultiInterfaceMultiClientTopo...")
|
||||||
super(MultiInterfaceMultiClientTopo, self).__init__(topo_builder, parameterFile)
|
|
||||||
|
super(MultiInterfaceMultiClientTopo, self).__init__(
|
||||||
|
topo_builder, parameterFile)
|
||||||
|
|
||||||
# For each client-router, add a client, a bottleneck link, and a server
|
# For each client-router, add a client, a bottleneck link, and a server
|
||||||
for bl in self.c2r_links:
|
for bl in self.c2r_links:
|
||||||
client = self.add_client()
|
client = self.add_client()
|
||||||
self.add_server()
|
|
||||||
self.add_link(client, bl.get_left())
|
self.add_link(client, bl.get_left())
|
||||||
|
|
||||||
|
self.add_server()
|
||||||
|
|
||||||
# And connect the router to all servers
|
# And connect the router to all servers
|
||||||
for s in self.servers[1:]:
|
for s in self.servers[1:]:
|
||||||
self.add_link(self.router, s)
|
self.add_link(self.router, s)
|
||||||
@ -24,13 +27,16 @@ class MultiInterfaceMultiClientTopo(MultiInterfaceTopo):
|
|||||||
s = "Multiple interface topology with several clients and servers\n"
|
s = "Multiple interface topology with several clients and servers\n"
|
||||||
i = 0
|
i = 0
|
||||||
nc = len(self.get_client_to_router_links())
|
nc = len(self.get_client_to_router_links())
|
||||||
|
|
||||||
for i in range(0, nc):
|
for i in range(0, nc):
|
||||||
if i == nc // 2:
|
if i == nc // 2:
|
||||||
s = s + "c- r--s\n"
|
s = s + " r--s\n"
|
||||||
s = s + "c-\sw---bl---sw-/ \-s\n"
|
s = s + "c-\sw---bl---sw-/ \-s\n"
|
||||||
else:
|
elif i < nc // 2:
|
||||||
s = s + "c-/sw---bl---sw-\ /-s\n"
|
s = s + "c-/sw---bl---sw-\ /-s\n"
|
||||||
|
else:
|
||||||
|
s = s + "c-\sw---bl---sw-/ \-s\n"
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
@ -45,48 +51,59 @@ class MultiInterfaceMultiClientConfig(MultiInterfaceConfig):
|
|||||||
for i, _ in enumerate(self.topo.c2r_links):
|
for i, _ in enumerate(self.topo.c2r_links):
|
||||||
# Routing for the congestion client
|
# Routing for the congestion client
|
||||||
cmd = self.add_global_default_route_command(self.get_router_ip_to_client_switch(i),
|
cmd = self.add_global_default_route_command(self.get_router_ip_to_client_switch(i),
|
||||||
self.get_client_interface(i+1, 0))
|
self.get_client_interface(i+1, 0))
|
||||||
self.topo.command_to(self.clients[i+1], cmd)
|
self.topo.command_to(self.clients[i+1], cmd)
|
||||||
|
|
||||||
for i, s in enumerate(self.topo.servers):
|
for i, s in enumerate(self.topo.servers):
|
||||||
# Routing for the congestion server
|
# Routing for the congestion server
|
||||||
cmd = self.add_simple_default_route_command(self.get_router_ip_to_server_switch(i))
|
cmd = self.add_simple_default_route_command(
|
||||||
|
self.get_router_ip_to_server_switch(i))
|
||||||
self.topo.command_to(s, cmd)
|
self.topo.command_to(s, cmd)
|
||||||
|
|
||||||
def configure_interfaces(self):
|
def configure_interfaces(self):
|
||||||
logging.info("Configure interfaces using MultiInterfaceMultiClientConfig...")
|
logging.info(
|
||||||
|
"Configure interfaces using MultiInterfaceMultiClientConfig...")
|
||||||
super(MultiInterfaceMultiClientConfig, self).configure_interfaces()
|
super(MultiInterfaceMultiClientConfig, self).configure_interfaces()
|
||||||
self.clients = [self.topo.get_client(i) for i in range(0, self.topo.client_count())]
|
self.clients = [self.topo.get_client(
|
||||||
self.servers = [self.topo.get_server(i) for i in range(0, self.topo.server_count())]
|
i) for i in range(0, self.topo.client_count())]
|
||||||
|
self.servers = [self.topo.get_server(
|
||||||
|
i) for i in range(0, self.topo.server_count())]
|
||||||
netmask = "255.255.255.0"
|
netmask = "255.255.255.0"
|
||||||
|
|
||||||
for i, _ in enumerate(self.topo.c2r_links):
|
for i, _ in enumerate(self.topo.c2r_links):
|
||||||
# Congestion client
|
# Congestion client
|
||||||
cmd = self.interface_up_command(self.get_client_interface(i + 1, 0), self.get_client_ip(i, congestion_client=True), netmask)
|
cmd = self.interface_up_command(self.get_client_interface(
|
||||||
|
i + 1, 0), self.get_client_ip(i, congestion_client=True), netmask)
|
||||||
self.topo.command_to(self.clients[i+1], cmd)
|
self.topo.command_to(self.clients[i+1], cmd)
|
||||||
client_interface_mac = self.clients[i+1].intf(self.get_client_interface(i + 1, 0)).MAC()
|
client_interface_mac = self.clients[i+1].intf(
|
||||||
self.topo.command_to(self.router, "arp -s {} {}".format(self.get_client_ip(i, congestion_client=True), client_interface_mac))
|
self.get_client_interface(i + 1, 0)).MAC()
|
||||||
|
self.topo.command_to(self.router, "arp -s {} {}".format(
|
||||||
|
self.get_client_ip(i, congestion_client=True), client_interface_mac))
|
||||||
|
|
||||||
router_interface_mac = self.router.intf(self.get_router_interface_to_client_switch(i)).MAC()
|
router_interface_mac = self.router.intf(
|
||||||
|
self.get_router_interface_to_client_switch(i)).MAC()
|
||||||
# Congestion client
|
# Congestion client
|
||||||
self.topo.command_to(self.clients[i+1], "arp -s {} {}".format(
|
self.topo.command_to(self.clients[i+1], "arp -s {} {}".format(
|
||||||
self.get_router_ip_to_client_switch(i), router_interface_mac))
|
self.get_router_ip_to_client_switch(i), router_interface_mac))
|
||||||
|
|
||||||
for i, s in enumerate(self.servers):
|
for i, s in enumerate(self.servers):
|
||||||
cmd = self.interface_up_command(self.get_router_interface_to_server_switch(i),
|
cmd = self.interface_up_command(self.get_router_interface_to_server_switch(i),
|
||||||
self.get_router_ip_to_server_switch(i), netmask)
|
self.get_router_ip_to_server_switch(i), netmask)
|
||||||
self.topo.command_to(self.router, cmd)
|
self.topo.command_to(self.router, cmd)
|
||||||
router_interface_mac = self.router.intf(self.get_router_interface_to_server_switch(i)).MAC()
|
router_interface_mac = self.router.intf(
|
||||||
|
self.get_router_interface_to_server_switch(i)).MAC()
|
||||||
self.topo.command_to(s, "arp -s {} {}".format(
|
self.topo.command_to(s, "arp -s {} {}".format(
|
||||||
self.get_router_ip_to_server_switch(i), router_interface_mac))
|
self.get_router_ip_to_server_switch(i), router_interface_mac))
|
||||||
cmd = self.interface_up_command(self.get_server_interface(i, 0), self.get_server_ip(interface_index=i), netmask)
|
cmd = self.interface_up_command(self.get_server_interface(
|
||||||
|
i, 0), self.get_server_ip(interface_index=i), netmask)
|
||||||
self.topo.command_to(s, cmd)
|
self.topo.command_to(s, cmd)
|
||||||
server_interface_mac = s.intf(self.get_server_interface(i, 0)).MAC()
|
server_interface_mac = s.intf(
|
||||||
|
self.get_server_interface(i, 0)).MAC()
|
||||||
self.topo.command_to(self.router, "arp -s {} {}".format(
|
self.topo.command_to(self.router, "arp -s {} {}".format(
|
||||||
self.get_server_ip(interface_index=i), server_interface_mac))
|
self.get_server_ip(interface_index=i), server_interface_mac))
|
||||||
|
|
||||||
def get_client_ip(self, interface_index, congestion_client=False):
|
def get_client_ip(self, interface_index, congestion_client=False):
|
||||||
return "{}{}.{}".format(self.param.get(TopoParameter.LEFT_SUBNET), interface_index, "10" if congestion_client else "1")
|
return "{}{}.{}".format(self.param.get(TopoParameter.LEFT_SUBNET), interface_index, "10" if congestion_client else "1")
|
||||||
|
|
||||||
def server_interface_count(self):
|
def server_interface_count(self):
|
||||||
return max(len(self.servers), 1)
|
return max(len(self.servers), 1)
|
||||||
|
BIN
utils/echo-client
Executable file
BIN
utils/echo-client
Executable file
Binary file not shown.
BIN
utils/server
Executable file
BIN
utils/server
Executable file
Binary file not shown.
Loading…
Reference in New Issue
Block a user