Created
February 19, 2014 13:34
-
-
Save charlesmcchan/9092080 to your computer and use it in GitHub Desktop.
MPTCP test environment
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import sys | |
from time import sleep | |
from math import sqrt | |
import argparse | |
from subprocess import Popen, PIPE | |
from mininet.net import Mininet | |
from mininet.link import TCLink | |
from mininet.topo import Topo | |
from mininet.log import lg | |
""" | |
bandwidth: Mbps | |
delay: ms, 1-way | |
loss rate: 0-100 | |
queue size: # packets | |
""" | |
links = [ | |
[10, 20, 0, 1000000], | |
[10, 20, 0, 1000000] | |
] | |
class TwoHostNLink(Topo): | |
def __init__(self, **opts): | |
super(TwoHostNLink, self).__init__(**opts) | |
# add switches | |
switches = [] | |
for i in range(len(links)): | |
switches.append('s%i' % (i+1)) | |
self.addSwitch('s%i' % (i+1)) | |
# add hosts | |
self.addHost('h1') | |
self.addHost('h2') | |
# add links | |
for i in range(len(links)): | |
bw = links[i][0] | |
delay = links[i][1]/2 | |
loss = (100-sqrt(100-links[i][2]))/100 | |
qsize = links[i][3] | |
self.addLink('h1', switches[i], bw=bw, delay=str(delay)+'ms', loss=loss, max_queue_size=qsize) | |
self.addLink('h2', switches[i], bw=bw, delay=str(delay)+'ms', loss=loss, max_queue_size=qsize) | |
def progress(t): | |
while t > 0: | |
print "%3d seconds left" % t | |
t -= 1 | |
sleep(1) | |
print "\n" | |
def parse_args(): | |
parser = argparse.ArgumentParser(description="MPTCP 2-host n-switch test") | |
parser.add_argument('--mptcp', | |
action="store_true", | |
help="Enable MPTCP (net.mptcp.mptcp_enabled)", | |
default=False) | |
parser.add_argument('--ndiffports', | |
action="store", | |
help="Set # subflows (net.mptcp.mptcp_ndiffports)", | |
default=1) | |
parser.add_argument('-t', | |
action="store", | |
help="Seconds to run the experiment", | |
default=2) | |
args = parser.parse_args() | |
args.ndiffports = int(args.ndiffports) | |
return args | |
def sysctl_set(key, value): | |
"""Issue systcl for given param to given value and check for error.""" | |
p = Popen("sysctl -w %s=%s" % (key, value), shell=True, stdout=PIPE, | |
stderr=PIPE) | |
# Output should be empty; otherwise, we have an issue. | |
stdout, stderr = p.communicate() | |
stdout_expected = "%s = %s\n" % (key, value) | |
if stdout != stdout_expected: | |
raise Exception("Popen returned unexpected stdout: %s != %s" % (stdout, stdout_expected)) | |
if stderr: | |
raise Exception("Popen returned unexpected stderr: %s" % stderr) | |
def set_mptcp_enabled(enabled): | |
"""Enable MPTCP if true, disable if false""" | |
e = 1 if enabled else 0 | |
lg.info("setting MPTCP enabled to %s\n" % e) | |
sysctl_set('net.mptcp.mptcp_enabled', e) | |
def set_mptcp_ndiffports(ports): | |
"""Set ndiffports, the number of subflows to instantiate""" | |
lg.info("setting MPTCP ndiffports to %s\n" % ports) | |
sysctl_set("net.mptcp.mptcp_ndiffports", ports) | |
def setup(args): | |
set_mptcp_enabled(args.mptcp) | |
set_mptcp_ndiffports(args.ndiffports) | |
def end(args): | |
set_mptcp_enabled(False) | |
set_mptcp_ndiffports(1) | |
def run(args, net): | |
seconds = int(args.t) | |
h1 = net.getNodeByName('h1') | |
h2 = net.getNodeByName('h2') | |
for i in range(len(links)): | |
# Setup IPs: | |
h1.cmdPrint('ifconfig h1-eth%i 10.0.%i.3 netmask 255.255.255.0' % (i, i)) | |
h2.cmdPrint('ifconfig h2-eth%i 10.0.%i.4 netmask 255.255.255.0' % (i, i)) | |
if args.mptcp: | |
lg.info("configuring source-specific routing tables for MPTCP\n") | |
# This creates two different routing tables, that we use based on the | |
# source-address. | |
dev = 'h1-eth%i' % i | |
table = '%s' % (i + 1) | |
h1.cmdPrint('ip rule add from 10.0.%i.3 table %s' % (i, table)) | |
h1.cmdPrint('ip route add 10.0.%i.0/24 dev %s scope link table %s' % (i, dev, table)) | |
h1.cmdPrint('ip route add default via 10.0.%i.1 dev %s table %s' % (i, dev, table)) | |
# TODO: expand this to verify connectivity with a ping test. | |
lg.info("pinging each destination interface\n") | |
for i in range(len(links)): | |
h2_out = h2.cmd('ping -c 1 10.0.%i.3' % i) | |
lg.info("ping test output: %s\n" % h2_out) | |
lg.info("iperfing\n") | |
h2.sendCmd('iperf -s -i 1') | |
cmd = 'iperf -c 10.0.0.4 -t %d -i 1' % seconds | |
h1.sendCmd(cmd) | |
progress(seconds + 1) | |
h1_out = h1.waitOutput() | |
lg.info("client output:\n%s\n" % h1_out) | |
sleep(0.1) # hack to wait for iperf server output. | |
out = h2.read(10000) | |
lg.info("server output: %s\n" % out) | |
return None | |
def genericTest(args, topo, setup, run, end): | |
net = Mininet(topo=topo, link=TCLink) | |
setup(args) | |
net.start() | |
data = run(args, net) | |
net.stop() | |
end(args) | |
return data | |
def main(): | |
args = parse_args() | |
lg.setLogLevel('info') | |
topo = TwoHostNLink() | |
genericTest(args, topo, setup, run, end) | |
if __name__ == '__main__': | |
main() |
Hello, I get an assertion error on net.stop(). Do you know how can I solve it?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello,
I wanted to run the above code in Ubuntu 14.04 , running MPTCP kernel and mininet ver 2.2.1. It gives following error, can you help in this regard:
File "mptcp-test.py", line 90, in set_mptcp_enabled
sysctl_set('net.mptcp.mptcp_enabled', e)
File "mptcp-test.py", line 82, in sysctl_set
raise Exception("Popen returned unexpected stdout: %s != %s" % (stdout, stdout_expected))
Exception: Popen returned unexpected stdout: != net.mptcp.mptcp_enabled = 0