get rid of policing

Actually, the policing command, while working reasonably,  might be too
restrictive. The buffer of the router might be never full, and packet losses
tend to happen quickly.

Instead, we could rely on the shaping with the limit argument of tbf to do the
job. However, the tbf command is first and then the netem one. Thanks to the
Mininet magics, the sender can completely ignore queue limitations...

To solve this, we just keep tbf and netem, but we first introduce netem (with
very large buffer) and then tbf. With the delay, there is no more fast path and
we see again realistic results.
This commit is contained in:
Quentin De Coninck 2020-07-13 16:50:24 +02:00
parent b3c1c70a3b
commit ca59fc4f0e

View File

@ -85,12 +85,12 @@ class LinkCharacteristics(object):
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)
def build_bandwidth_cmd(self, ifname, change=False): def build_bandwidth_cmd(self, ifname, change=False):
return "tc qdisc {} dev {} root handle 5:0 tbf rate {}mbit burst 15000 limit {}".format( return "tc qdisc {} dev {} root handle 1:0 tbf rate {}mbit burst 15000 limit {}".format(#; tc qdisc {} dev {} parent 1:0 bfifo limit {}".format(
"change" if change else "add", ifname, self.bandwidth, self.buffer_size()) "change" if change else "add", ifname, self.bandwidth, self.buffer_size())#, "change" if change else "add", ifname, self.buffer_size())
def build_changing_bandwidth_cmd(self, ifname): def build_changing_bandwidth_cmd(self, ifname):
return "&& ".join( return "&& ".join(
["sleep {} && {} ".format( ["sleep {} && ({}) ".format(
n.delta, self.build_bandwidth_cmd(ifname, change=True)) for n in self.netem_at] n.delta, self.build_bandwidth_cmd(ifname, change=True)) for n in self.netem_at]
+ ["true &"] + ["true &"]
) )
@ -106,19 +106,6 @@ class LinkCharacteristics(object):
+ ["true &"] + ["true &"]
) )
def build_policing_cmd(self, ifname, change=False):
return "tc qdisc {} dev {} handle ffff: ingress ; \
tc filter {} dev {} parent ffff: u32 match u32 0 0 police rate {}mbit burst {} drop".format(
"change" if change else "add", ifname, "change" if change else "add", ifname,
self.bandwidth, int(self.buffer_size()) * 1.2)
def build_changing_policing_cmd(self, ifname):
return "&& ".join(
["sleep {} && ({}) ".format(
n.delta, self.build_policing_cmd(ifname, change=True)) for n in self.netem_at]
+ ["true &"]
)
def as_dict(self): def as_dict(self):
""" """
Notably used by BottleneckLink Notably used by BottleneckLink
@ -320,36 +307,27 @@ class BottleneckLink(object):
self.topo.command_to(self.bs2, clean_cmd) self.topo.command_to(self.bs2, clean_cmd)
# Flow bs0 -> bs3 # Flow bs0 -> bs3
policing_cmd = self.link_characteristics.build_policing_cmd(bs1_interface_names[0]) netem_cmd = self.link_characteristics.build_netem_cmd(bs1_interface_names[-1],
logging.info(policing_cmd)
self.topo.command_to(self.bs1, policing_cmd)
shaping_cmd = self.link_characteristics.build_bandwidth_cmd(bs1_interface_names[-1])
logging.info(shaping_cmd)
self.topo.command_to(self.bs1, shaping_cmd)
netem_cmd = self.link_characteristics.build_netem_cmd(bs2_interface_names[-1],
"loss {}".format(self.link_characteristics.loss) if float(self.link_characteristics.loss) > 0 else "")
logging.info(netem_cmd)
self.topo.command_to(self.bs2, netem_cmd)
# Flow bs3 -> bs0
policing_cmd = self.link_characteristics.build_policing_cmd(bs2_interface_names[-1])
logging.info(policing_cmd)
self.topo.command_to(self.bs2, policing_cmd)
shaping_cmd = self.link_characteristics.build_bandwidth_cmd(bs2_interface_names[0])
logging.info(shaping_cmd)
self.topo.command_to(self.bs2, shaping_cmd)
netem_cmd = self.link_characteristics.build_netem_cmd(bs1_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.bs1, netem_cmd) self.topo.command_to(self.bs1, netem_cmd)
shaping_cmd = self.link_characteristics.build_bandwidth_cmd(bs2_interface_names[-1])
logging.info(shaping_cmd)
self.topo.command_to(self.bs2, shaping_cmd)
# Flow bs3 -> bs0
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 "")
logging.info(netem_cmd)
self.topo.command_to(self.bs2, netem_cmd)
shaping_cmd = self.link_characteristics.build_bandwidth_cmd(bs1_interface_names[0])
logging.info(shaping_cmd)
self.topo.command_to(self.bs1, shaping_cmd)
def configure_changing_bottleneck(self): def configure_changing_bottleneck(self):
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
policing_cmd = self.link_characteristics.build_changing_policing_cmd(bs1_interface_names[0])
logging.info(policing_cmd)
self.topo.command_to(self.bs1, policing_cmd)
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)
@ -358,9 +336,6 @@ class BottleneckLink(object):
self.topo.command_to(self.bs2, netem_cmd) self.topo.command_to(self.bs2, netem_cmd)
# Flow bs3 -> bs0 # Flow bs3 -> bs0
policing_cmd = self.link_characteristics.build_changing_policing_cmd(bs2_interface_names[-1])
logging.info(policing_cmd)
self.topo.command_to(self.bs2, policing_cmd)
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)