├── CNAME ├── mininet ├── debian │ ├── compat │ ├── docs │ ├── manpages │ ├── examples │ ├── install │ ├── source │ │ └── format │ ├── watch │ ├── rules │ ├── control │ ├── changelog │ └── copyright ├── mininet │ ├── examples │ ├── mapper │ │ ├── __init__.py │ │ └── shares │ │ │ └── equal10.txt │ ├── provision │ │ ├── __init__.py │ │ ├── basicprovision.py │ │ └── playbooks │ │ │ ├── install-lxd-old.yml │ │ │ ├── install-lxd.yml │ │ │ ├── install-lxd-debian-10.yml │ │ │ ├── install-lxd-snap.yml │ │ │ ├── install-g5k-lxd.yml │ │ │ ├── install-aws-lxd.yml │ │ │ ├── configure-lxd.yml │ │ │ └── configure-lxd-no-clustering.yml │ ├── __init__.py │ ├── test │ │ ├── test_ptyleak.py │ │ ├── runner.py │ │ ├── test_switchdpidassignment.py │ │ └── test_nets.py │ ├── dcli.py │ ├── dutil.py │ ├── moduledeps.py │ ├── term.py │ └── topolib.py ├── .gitattributes ├── examples │ ├── __init__.py │ ├── test │ │ ├── test_mobility.py │ │ ├── test_clusterSanity.py │ │ ├── test_scratchnet.py │ │ ├── test_multitest.py │ │ ├── test_emptynet.py │ │ ├── test_treeping64.py │ │ ├── test_nat.py │ │ ├── test_tree1024.py │ │ ├── test_simpleperf.py │ │ ├── test_limit.py │ │ ├── test_multipoll.py │ │ ├── runner.py │ │ ├── test_popen.py │ │ ├── test_cpu.py │ │ ├── test_controlnet.py │ │ ├── test_controllers.py │ │ ├── test_intfoptions.py │ │ ├── test_vlanhost.py │ │ ├── test_linuxrouter.py │ │ ├── test_multilink.py │ │ ├── test_linearbandwidth.py │ │ ├── test_numberedports.py │ │ ├── test_natnet.py │ │ ├── test_multiping.py │ │ ├── test_sshd.py │ │ ├── test_hwintf.py │ │ ├── test_baresshd.py │ │ └── test_bind.py │ ├── tree1024.py │ ├── clusterSanity.py │ ├── nat.py │ ├── clusterperf.py │ ├── clusterdemo.py │ ├── multilink.py │ ├── treeping64.py │ ├── emptynet.py │ ├── popenpoll.py │ ├── popen.py │ ├── multitest.py │ ├── controllers.py │ ├── baresshd.py │ ├── intfoptions.py │ ├── hwintf.py │ ├── controllers2.py │ ├── natnet.py │ ├── simpleperf.py │ ├── limit.py │ ├── scratchnet.py │ ├── bind.py │ ├── multiping.py │ ├── numberedports.py │ ├── scratchnetuser.py │ ├── multipoll.py │ ├── linuxrouter.py │ ├── sshd.py │ ├── vlanhost.py │ ├── cpu.py │ ├── linearbandwidth.py │ ├── clustercli.py │ └── mobility.py ├── util │ ├── nox-patches │ │ └── README │ ├── openflow-patches │ │ ├── README │ │ ├── controller.patch │ │ └── datapath.patch │ ├── sch_htb-ofbuf │ │ ├── README │ │ └── Makefile │ ├── sysctl_addon │ ├── kbuild │ │ ├── tun.patch │ │ ├── version_vars.patch │ │ └── kbuild │ ├── vm │ │ ├── .bash_profile │ │ └── install-mininet-vm.sh │ ├── versioncheck.py │ ├── m │ ├── colorfilters │ ├── doxify.py │ └── build-ovs-packages.sh ├── .gitignore ├── custom │ ├── README │ ├── topo-2sw-2host.py │ ├── iperf_test.py │ └── hadoop_test.py ├── .github │ └── ISSUE_TEMPLATE ├── .travis.yml ├── CONTRIBUTORS ├── setup.py ├── LICENSE ├── Makefile └── bin │ └── README.md ├── _config.yml ├── .gitmodules ├── tests └── test_dummy.py ├── tox.ini ├── requirements.txt ├── conf ├── general_purpose.json ├── conf.yml └── gros_partial.json ├── Dockerfile ├── .travis.yml ├── README.md ├── LICENSE.md ├── setup.py └── .gitignore /CNAME: -------------------------------------------------------------------------------- 1 | www.distrinet.io -------------------------------------------------------------------------------- /mininet/debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /mininet/debian/docs: -------------------------------------------------------------------------------- 1 | README.md 2 | -------------------------------------------------------------------------------- /mininet/debian/manpages: -------------------------------------------------------------------------------- 1 | *.1 2 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-hacker -------------------------------------------------------------------------------- /mininet/debian/examples: -------------------------------------------------------------------------------- 1 | examples/* 2 | -------------------------------------------------------------------------------- /mininet/mininet/examples: -------------------------------------------------------------------------------- 1 | ../examples -------------------------------------------------------------------------------- /mininet/mininet/mapper/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mininet/mininet/provision/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mininet/.gitattributes: -------------------------------------------------------------------------------- 1 | *.py diff=python 2 | -------------------------------------------------------------------------------- /mininet/debian/install: -------------------------------------------------------------------------------- 1 | mnexec /usr/bin 2 | -------------------------------------------------------------------------------- /mininet/debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /mininet/examples/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Mininet Examples 3 | See README for details 4 | """ 5 | -------------------------------------------------------------------------------- /mininet/mininet/__init__.py: -------------------------------------------------------------------------------- 1 | "Docstring to silence pylint; ignores --ignore option for __init__.py" 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "mininet"] 2 | path = mininet 3 | url = https://github.com/mininet/mininet.git 4 | -------------------------------------------------------------------------------- /mininet/mininet/mapper/shares/equal10.txt: -------------------------------------------------------------------------------- 1 | 0 = 0.1 2 | 1 = 0.1 3 | 2 = 0.1 4 | 3 = 0.1 5 | 4 = 0.1 6 | 5 = 0.1 7 | 6 = 0.1 8 | 7 = 0.1 9 | 8 = 0.1 10 | 9 = 0.1 -------------------------------------------------------------------------------- /mininet/util/nox-patches/README: -------------------------------------------------------------------------------- 1 | 0001: This patch adds the OpenFlow tutorial module source code to nox-destiny. 2 | 0002: This patch hacks nox-destiny to compile on Ubuntu 12.04. 3 | -------------------------------------------------------------------------------- /mininet/.gitignore: -------------------------------------------------------------------------------- 1 | mnexec 2 | *.pyc 3 | *~ 4 | *.1 5 | *.xcodeproj 6 | *.xcworkspace 7 | \#*\# 8 | mininet.egg-info 9 | build 10 | dist 11 | doc/html 12 | doc/latex 13 | trunk 14 | 15 | -------------------------------------------------------------------------------- /mininet/debian/watch: -------------------------------------------------------------------------------- 1 | version=3 2 | opts=filenamemangle=s/(.*)\/archive/$1/,uversionmangle=s/([abdr].*)\.tar\.gz/~$1/ \ 3 | https://github.com/mininet/mininet/tags .*/archive\/(\d.*\.tar\.gz) 4 | -------------------------------------------------------------------------------- /tests/test_dummy.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | class MyTestCase(unittest.TestCase): 4 | def test_something(self): 5 | self.assertEqual(True, True) 6 | 7 | 8 | if __name__ == '__main__': 9 | unittest.main() -------------------------------------------------------------------------------- /mininet/util/openflow-patches/README: -------------------------------------------------------------------------------- 1 | Patches for OpenFlow Reference Implementation 2 | 3 | controller.patch: patch controller to support up to 4096 switches (up from 16!) 4 | 5 | datapath.patch: patch to kernel datapath to compile with CONFIG_NET_NS=y 6 | -------------------------------------------------------------------------------- /mininet/debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | %: 4 | dh $@ --buildsystem=python_distutils --with=python2 5 | 6 | override_dh_auto_build: 7 | make man 8 | make mnexec 9 | dh_auto_build 10 | 11 | get-orig-source: 12 | uscan --force-download --rename 13 | -------------------------------------------------------------------------------- /mininet/util/sch_htb-ofbuf/README: -------------------------------------------------------------------------------- 1 | Modified sch_htb implementation with ofbuf support. 2 | 3 | To compile, just type make. To use this module instead 4 | of regular sch_htb, do: 5 | 6 | 0. make 7 | 1. rmmod sch_htb 8 | 2. insmod ./sch_htb.ko 9 | 10 | To revert, just rmmod sch_htb. 11 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | # content of: tox.ini , put in same dir as setup.py 2 | [tox] 3 | envlist = py36,py37 4 | [testenv] 5 | setenv = PYTHONPATH = {toxinidir}/subdir 6 | deps = -rrequirements.txt 7 | changedir = tests 8 | # run the tests 9 | # ... or run any other command line tool you need to run here 10 | commands = pytest -------------------------------------------------------------------------------- /mininet/custom/README: -------------------------------------------------------------------------------- 1 | This directory should hold configuration files for custom mininets. 2 | 3 | See custom_example.py, which loads the default minimal topology. The advantage of defining a mininet in a separate file is that you then use the --custom option in mn to run the CLI or specific tests with it. 4 | 5 | To start up a mininet with the provided custom topology, do: 6 | sudo mn --custom custom_example.py --topo mytopo 7 | -------------------------------------------------------------------------------- /mininet/util/openflow-patches/controller.patch: -------------------------------------------------------------------------------- 1 | diff --git a/controller/controller.c b/controller/controller.c 2 | index 41f2547..6eec590 100644 3 | --- a/controller/controller.c 4 | +++ b/controller/controller.c 5 | @@ -58,8 +58,8 @@ 6 | #include "vlog.h" 7 | #define THIS_MODULE VLM_controller 8 | 9 | -#define MAX_SWITCHES 16 10 | -#define MAX_LISTENERS 16 11 | +#define MAX_SWITCHES 4096 12 | +#define MAX_LISTENERS 4096 13 | 14 | struct switch_ { 15 | struct lswitch *lswitch; 16 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2018.10.15 2 | chardet==3.0.4 3 | decorator==4.3.0 4 | idna==2.7 5 | ipaddress==1.0.22 6 | #networkx==2.2 7 | pip>=18.0 8 | requests==2.20.0 9 | urllib3==1.24.2 10 | wheel==0.32.0 11 | setuptools==40.8.0 12 | paramiko==2.6.0 13 | #boto3>=1.9.214 14 | pulp==1.6.10 15 | asyncssh==1.17.1 16 | cryptography>=2.7 17 | asyncio==3.4.3 18 | pytest==5.1.0 19 | PyYAML==5.1.2 20 | #awscli>=1.16.224 21 | progressbar2==3.43.1 22 | testresources==2.0.1 23 | git+https://github.com/Giuseppe1992/mapping_distrinet-1.git -------------------------------------------------------------------------------- /mininet/util/sch_htb-ofbuf/Makefile: -------------------------------------------------------------------------------- 1 | obj-m = sch_htb.o 2 | KVERSION = $(shell uname -r) 3 | all: 4 | make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules 5 | install: 6 | test -e /lib/modules/$(KVERSION)/kernel/net/sched/sch_htb.ko.bak || mv /lib/modules/$(KVERSION)/kernel/net/sched/sch_htb.ko /lib/modules/$(KVERSION)/kernel/net/sched/sch_htb.ko.bak 7 | cp sch_htb.ko /lib/modules/$(KVERSION)/kernel/net/sched/sch_htb.ko 8 | rmmod sch_htb 9 | modprobe sch_htb 10 | clean: 11 | make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean 12 | -------------------------------------------------------------------------------- /conf/general_purpose.json: -------------------------------------------------------------------------------- 1 | { 2 | "t3.xlarge": { 3 | "vCPU": 4, 4 | "memory": 16.0, 5 | "hourly_cost": 0.1888 6 | }, 7 | "t3.2xlarge": { 8 | "vCPU": 8, 9 | "memory": 32.0, 10 | "hourly_cost": 0.3776 11 | }, 12 | "m5.4xlarge": { 13 | "vCPU": 16, 14 | "memory": 64.0, 15 | "hourly_cost": 0.896 16 | }, 17 | "m5.12xlarge": { 18 | "vCPU": 48, 19 | "memory": 192.0, 20 | "hourly_cost": 2.688 21 | }, 22 | "m5.24xlarge": { 23 | "vCPU": 96, 24 | "memory": 384.0, 25 | "hourly_cost": 5.376 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /mininet/examples/test/test_mobility.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for mobility.py 5 | """ 6 | 7 | import unittest 8 | from subprocess import check_output 9 | 10 | class testMobility( unittest.TestCase ): 11 | 12 | def testMobility( self ): 13 | "Run the example and verify its 4 ping results" 14 | cmd = 'python -m mininet.examples.mobility 2>&1' 15 | grep = ' | grep -c " 0% dropped" ' 16 | result = check_output( cmd + grep, shell=True ) 17 | assert int( result ) == 4 18 | 19 | if __name__ == '__main__': 20 | unittest.main() 21 | -------------------------------------------------------------------------------- /mininet/util/sysctl_addon: -------------------------------------------------------------------------------- 1 | # Mininet: Increase open file limit 2 | fs.file-max = 100000 3 | 4 | # Mininet: increase network buffer space 5 | net.core.wmem_max = 16777216 6 | net.core.rmem_max = 16777216 7 | net.ipv4.tcp_rmem = 10240 87380 16777216 8 | net.ipv4.tcp_rmem = 10240 87380 16777216 9 | net.core.netdev_max_backlog = 5000 10 | 11 | # Mininet: increase arp cache size 12 | net.ipv4.neigh.default.gc_thresh1 = 4096 13 | net.ipv4.neigh.default.gc_thresh2 = 8192 14 | net.ipv4.neigh.default.gc_thresh3 = 16384 15 | 16 | # Mininet: increase routing table size 17 | net.ipv4.route.max_size=32768 18 | 19 | -------------------------------------------------------------------------------- /mininet/examples/tree1024.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | Create a 1024-host network, and run the CLI on it. 5 | If this fails because of kernel limits, you may have 6 | to adjust them, e.g. by adding entries to /etc/sysctl.conf 7 | and running sysctl -p. Check util/sysctl_addon. 8 | """ 9 | 10 | from mininet.cli import CLI 11 | from mininet.log import setLogLevel 12 | from mininet.node import OVSSwitch 13 | from mininet.topolib import TreeNet 14 | 15 | if __name__ == '__main__': 16 | setLogLevel( 'info' ) 17 | network = TreeNet( depth=2, fanout=32, switch=OVSSwitch ) 18 | network.run( CLI, network ) 19 | -------------------------------------------------------------------------------- /mininet/examples/clusterSanity.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ''' 4 | A sanity check for cluster edition 5 | ''' 6 | 7 | from mininet.examples.cluster import MininetCluster 8 | from mininet.log import setLogLevel 9 | from mininet.examples.clustercli import ClusterCLI as CLI 10 | from mininet.topo import SingleSwitchTopo 11 | 12 | def clusterSanity(): 13 | "Sanity check for cluster mode" 14 | topo = SingleSwitchTopo() 15 | net = MininetCluster( topo=topo ) 16 | net.start() 17 | CLI( net ) 18 | net.stop() 19 | 20 | if __name__ == '__main__': 21 | setLogLevel( 'info' ) 22 | clusterSanity() 23 | -------------------------------------------------------------------------------- /mininet/util/kbuild/tun.patch: -------------------------------------------------------------------------------- 1 | --- linux-2.6.33.1/drivers/net/tun.c 2010-03-24 22:47:32.000000000 -0700 2 | +++ tun-new.c 2010-03-24 22:45:00.000000000 -0700 3 | @@ -1006,7 +1006,9 @@ 4 | if (err < 0) 5 | goto err_free_sk; 6 | 7 | - if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) || 8 | + /* BL hack: check for null parent kobj */ 9 | + if (!tun->dev->dev.kobj.sd || 10 | + device_create_file(&tun->dev->dev, &dev_attr_tun_flags) || 11 | device_create_file(&tun->dev->dev, &dev_attr_owner) || 12 | device_create_file(&tun->dev->dev, &dev_attr_group)) 13 | printk(KERN_ERR "Failed to create tun sysfs files\n"); 14 | -------------------------------------------------------------------------------- /mininet/examples/nat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | Example to create a Mininet topology and connect it to the internet via NAT 5 | """ 6 | 7 | 8 | from mininet.cli import CLI 9 | from mininet.log import lg, info 10 | from mininet.topolib import TreeNet 11 | 12 | 13 | if __name__ == '__main__': 14 | lg.setLogLevel( 'info') 15 | net = TreeNet( depth=1, fanout=4 ) 16 | # Add NAT connectivity 17 | net.addNAT().configDefault() 18 | net.start() 19 | info( "*** Hosts are running and should have internet connectivity\n" ) 20 | info( "*** Type 'exit' or control-D to shut down network\n" ) 21 | CLI( net ) 22 | # Shut down NAT 23 | net.stop() 24 | -------------------------------------------------------------------------------- /mininet/util/vm/.bash_profile: -------------------------------------------------------------------------------- 1 | SSH_ENV="$HOME/.ssh/environment" 2 | 3 | function start_agent { 4 | echo "Initialising new SSH agent..." 5 | /usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}" 6 | echo succeeded 7 | chmod 600 "${SSH_ENV}" 8 | . "${SSH_ENV}" > /dev/null 9 | /usr/bin/ssh-add; 10 | } 11 | 12 | # Source SSH settings, if applicable 13 | 14 | if [ -f "${SSH_ENV}" ]; then 15 | . "${SSH_ENV}" > /dev/null 16 | #ps ${SSH_AGENT_PID} doesn't work under cywgin 17 | ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || { 18 | start_agent; 19 | } 20 | else 21 | start_agent; 22 | fi 23 | 24 | source ~/.bashrc 25 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # docker build -t distrinet:1.1 . 2 | FROM ubuntu:18.04 3 | MAINTAINER Giuseppe Di Lena (giuseppedilena92@gmail.com) 4 | RUN apt-get update && apt-get upgrade -y && apt-get install -y software-properties-common vim build-essential python3.6 python3-pip git 5 | # update pip 6 | RUN python3.6 -m pip install pip --upgrade 7 | WORKDIR / 8 | RUN git clone https://github.com/Giuseppe1992/Distrinet 9 | WORKDIR /Distrinet 10 | ENV PYTHONPATH "${PYTHONPATH}:/Distrinet/mininet/mininet" 11 | RUN pip install -r requirements.txt && python3.6 setup.py install 12 | RUN mkdir -p ~/.aws && echo "[default]\naws_access_key_id=XXXXXXXXXXXXXXXX\naws_secret_access_key=YYYYYYYYYYYYYYYYYYYY">> ~/.aws/credentials 13 | CMD /bin/bash 14 | -------------------------------------------------------------------------------- /mininet/.github/ISSUE_TEMPLATE: -------------------------------------------------------------------------------- 1 | Mininet uses GitHub issues for bug reports and feature requests only. 2 | These issues can be viewed at bugs.mininet.org 3 | 4 | If you have a question that is not a bug report or a feature request, 5 | please use the documentation at docs.mininet.org, the FAQ 6 | at faq.mininet.org, and the mininet-discuss mailing list. 7 | 8 | For bug reports, please fill in the following information in detail, 9 | and also feel free to include additional information such as debug 10 | output from mn -v debug, etc. 11 | --- Cut Here --- 12 | ### Expected/Desired Behavior: 13 | 14 | ### Actual Behavior: 15 | 16 | ### Detailed Steps to Reproduce the Behavior: 17 | 18 | ### Additional Information: 19 | 20 | -------------------------------------------------------------------------------- /mininet/examples/clusterperf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | "clusterperf.py compare the maximum throughput between SSH and GRE tunnels" 4 | 5 | from mininet.examples.cluster import RemoteSSHLink, RemoteGRELink, RemoteHost 6 | from mininet.net import Mininet 7 | from mininet.log import setLogLevel 8 | 9 | def perf(Link): 10 | "Test connectivity nand performance over Link" 11 | net = Mininet( host=RemoteHost, link=Link ) 12 | h1 = net.addHost( 'h1') 13 | h2 = net.addHost( 'h2', server='ubuntu2' ) 14 | net.addLink( h1, h2 ) 15 | net.start() 16 | net.pingAll() 17 | net.iperf() 18 | net.stop() 19 | 20 | if __name__ == '__main__': 21 | setLogLevel('info') 22 | perf( RemoteSSHLink ) 23 | perf( RemoteGRELink ) 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | include: 3 | - os: linux 4 | dist: trusty 5 | - os: linux 6 | dist: xenial 7 | - os: linux 8 | dist: bionic 9 | 10 | language: python 11 | python: 12 | - 3.6 13 | - 3.7 14 | - 3.8 15 | #- pypy3.6-7.1.1 16 | 17 | branches: 18 | only: 19 | - master 20 | 21 | before_install: 22 | - sudo apt-get update -qq 23 | 24 | cache: pip 25 | 26 | install: 27 | - pip install -r requirements.txt 28 | 29 | before_script: 30 | - export PYTHONPATH=$PYTHONPATH:$(pwd) 31 | - python setup.py install 32 | 33 | script: 34 | - echo 1 35 | 36 | 37 | notifications: 38 | email: 39 | recipients: 40 | - giuseppedilena92@gmail.com 41 | on_success: never 42 | on_failure: never 43 | -------------------------------------------------------------------------------- /mininet/examples/test/test_clusterSanity.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ''' 4 | A simple sanity check test for cluster edition 5 | ''' 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | 10 | class clusterSanityCheck( unittest.TestCase ): 11 | 12 | prompt = 'mininet>' 13 | 14 | def testClusterPingAll( self ): 15 | p = pexpect.spawn( 'python -m mininet.examples.clusterSanity' ) 16 | p.expect( self.prompt ) 17 | p.sendline( 'pingall' ) 18 | p.expect ( '(\d+)% dropped' ) 19 | percent = int( p.match.group( 1 ) ) if p.match else -1 20 | self.assertEqual( percent, 0 ) 21 | p.expect( self.prompt ) 22 | p.sendline( 'exit' ) 23 | p.wait() 24 | 25 | 26 | if __name__ == '__main__': 27 | unittest.main() 28 | -------------------------------------------------------------------------------- /mininet/examples/test/test_scratchnet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for scratchnet.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | 10 | class testScratchNet( unittest.TestCase ): 11 | 12 | opts = [ "1 packets transmitted, 1 received, 0% packet loss", pexpect.EOF ] 13 | 14 | def pingTest( self, name ): 15 | "Verify that no ping packets were dropped" 16 | p = pexpect.spawn( 'python -m %s' % name ) 17 | index = p.expect( self.opts, timeout=120 ) 18 | self.assertEqual( index, 0 ) 19 | 20 | def testPingKernel( self ): 21 | self.pingTest( 'mininet.examples.scratchnet' ) 22 | 23 | def testPingUser( self ): 24 | self.pingTest( 'mininet.examples.scratchnetuser' ) 25 | 26 | if __name__ == '__main__': 27 | unittest.main() 28 | -------------------------------------------------------------------------------- /mininet/examples/clusterdemo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | "clusterdemo.py: demo of Mininet Cluster Edition prototype" 4 | 5 | from mininet.examples.cluster import ( MininetCluster, SwitchBinPlacer, 6 | RemoteLink ) 7 | # ^ Could also use: RemoteSSHLink, RemoteGRELink 8 | from mininet.topolib import TreeTopo 9 | from mininet.log import setLogLevel 10 | from mininet.examples.clustercli import ClusterCLI as CLI 11 | 12 | def demo(): 13 | "Simple Demo of Cluster Mode" 14 | servers = [ 'localhost', 'ubuntu2', 'ubuntu3' ] 15 | topo = TreeTopo( depth=3, fanout=3 ) 16 | net = MininetCluster( topo=topo, servers=servers, Link=RemoteLink, 17 | placement=SwitchBinPlacer ) 18 | net.start() 19 | CLI( net ) 20 | net.stop() 21 | 22 | if __name__ == '__main__': 23 | setLogLevel( 'info' ) 24 | demo() 25 | -------------------------------------------------------------------------------- /mininet/mininet/test/test_ptyleak.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Regression test for pty leak in Node() 5 | """ 6 | 7 | import unittest 8 | 9 | from mininet.net import Mininet 10 | from mininet.clean import cleanup 11 | from mininet.topo import SingleSwitchTopo 12 | 13 | class TestPtyLeak( unittest.TestCase ): 14 | "Verify that there is no pty leakage" 15 | 16 | @staticmethod 17 | def testPtyLeak(): 18 | "Test for pty leakage" 19 | net = Mininet( SingleSwitchTopo() ) 20 | net.start() 21 | host = net[ 'h1' ] 22 | for _ in range( 0, 10 ): 23 | oldptys = host.slave, host.master 24 | net.delHost( host ) 25 | host = net.addHost( 'h1' ) 26 | assert ( host.slave, host.master ) == oldptys 27 | net.stop() 28 | 29 | if __name__ == '__main__': 30 | unittest.main() 31 | cleanup() 32 | -------------------------------------------------------------------------------- /mininet/debian/control: -------------------------------------------------------------------------------- 1 | Source: mininet 2 | Section: net 3 | Priority: extra 4 | Maintainer: Ubuntu Developers 5 | XSBC-Original-Maintainer: Bob Lantz 6 | Standards-Version: 3.9.3 7 | Build-Depends: 8 | debhelper (>= 9~), 9 | help2man, 10 | python-dev, 11 | python-pkg-resources, 12 | python-setuptools 13 | Homepage: http://openflow.org/mininet 14 | 15 | Package: mininet 16 | Architecture: any 17 | Depends: 18 | openvswitch-switch, 19 | telnet, 20 | socat, 21 | iperf, 22 | cgroup-bin, 23 | ${misc:Depends}, 24 | ${python:Depends}, 25 | ${shlibs:Depends} 26 | Recommends: openvswitch-controller 27 | Description: Process-based network emulator 28 | Mininet is a network emulator which uses lightweight 29 | virtualization to create virtual networks for rapid 30 | prototyping of Software-Defined Network (SDN) designs 31 | using OpenFlow. 32 | -------------------------------------------------------------------------------- /mininet/mininet/dcli.py: -------------------------------------------------------------------------------- 1 | from mininet.cli import CLI 2 | from mininet.log import info, output, error 3 | 4 | 5 | class DCLI( CLI ): 6 | def do_xterm( self, line, term='xterm' ): 7 | """Spawn xterm(s) for the given node(s). 8 | Usage: xterm node1 node2 ...""" 9 | error ("not supported") 10 | 11 | def do_x( self, line ): 12 | """Create an X11 tunnel to the given node, 13 | optionally starting a client. 14 | Usage: x node [cmd args]""" 15 | error ("not supported") 16 | 17 | def do_gterm( self, line ): 18 | """Spawn gnome-terminal(s) for the given node(s). 19 | Usage: gterm node1 node2 ...""" 20 | error ("not supported") 21 | 22 | def waitForNode( self, node ): 23 | "Wait for a node to finish, and print its output." 24 | while node.waiting: 25 | v = node.monitor(timeoutms=1) 26 | output( v ) 27 | -------------------------------------------------------------------------------- /mininet/examples/multilink.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | This is a simple example that demonstrates multiple links 5 | between nodes. 6 | """ 7 | 8 | from mininet.cli import CLI 9 | from mininet.log import setLogLevel 10 | from mininet.net import Mininet 11 | from mininet.topo import Topo 12 | 13 | def runMultiLink(): 14 | "Create and run multiple link network" 15 | topo = simpleMultiLinkTopo( n=2 ) 16 | net = Mininet( topo=topo ) 17 | net.start() 18 | CLI( net ) 19 | net.stop() 20 | 21 | class simpleMultiLinkTopo( Topo ): 22 | "Simple topology with multiple links" 23 | 24 | def build( self, n, **_kwargs ): 25 | h1, h2 = self.addHost( 'h1' ), self.addHost( 'h2' ) 26 | s1 = self.addSwitch( 's1' ) 27 | 28 | for _ in range( n ): 29 | self.addLink( s1, h1 ) 30 | self.addLink( s1, h2 ) 31 | 32 | if __name__ == '__main__': 33 | setLogLevel( 'info' ) 34 | runMultiLink() 35 | -------------------------------------------------------------------------------- /mininet/util/openflow-patches/datapath.patch: -------------------------------------------------------------------------------- 1 | diff --git a/datapath/datapath.c b/datapath/datapath.c 2 | index 4a4d3a2..365aa25 100644 3 | --- a/datapath/datapath.c 4 | +++ b/datapath/datapath.c 5 | @@ -47,6 +47,9 @@ 6 | 7 | #include "compat.h" 8 | 9 | +#ifdef CONFIG_NET_NS 10 | +#include 11 | +#endif 12 | 13 | /* Strings to describe the manufacturer, hardware, and software. This data 14 | * is queriable through the switch description stats message. */ 15 | @@ -259,6 +262,10 @@ send_openflow_skb(const struct datapath *dp, 16 | struct sk_buff *skb, const struct sender *sender) 17 | { 18 | return (sender 19 | - ? genlmsg_unicast(skb, sender->pid) 20 | +#ifdef CONFIG_NET_NS 21 | + ? genlmsg_unicast(&init_net, skb, sender->pid) 22 | +#else 23 | + ? genlmsg_unicast(skb, sender->pid) 24 | +#endif 25 | : genlmsg_multicast(skb, 0, dp_mc_group(dp), GFP_ATOMIC)); 26 | } 27 | -------------------------------------------------------------------------------- /mininet/custom/topo-2sw-2host.py: -------------------------------------------------------------------------------- 1 | """Custom topology example 2 | 3 | Two directly connected switches plus a host for each switch: 4 | 5 | host --- switch --- switch --- host 6 | 7 | Adding the 'topos' dict with a key/value pair to generate our newly defined 8 | topology enables one to pass in '--topo=mytopo' from the command line. 9 | """ 10 | 11 | from mininet.topo import Topo 12 | 13 | class MyTopo( Topo ): 14 | "Simple topology example." 15 | 16 | def build( self ): 17 | "Create custom topo." 18 | 19 | # Add hosts and switches 20 | leftHost = self.addHost( 'h1' ) 21 | rightHost = self.addHost( 'h2' ) 22 | leftSwitch = self.addSwitch( 's3' ) 23 | rightSwitch = self.addSwitch( 's4' ) 24 | 25 | # Add links 26 | self.addLink( leftHost, leftSwitch ) 27 | self.addLink( leftSwitch, rightSwitch ) 28 | self.addLink( rightSwitch, rightHost ) 29 | 30 | 31 | topos = { 'mytopo': ( lambda: MyTopo() ) } 32 | -------------------------------------------------------------------------------- /mininet/examples/test/test_multitest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for multitest.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | 10 | class testMultiTest( unittest.TestCase ): 11 | 12 | prompt = 'mininet>' 13 | 14 | def testMultiTest( self ): 15 | "Verify pingall (0% dropped) and hX-eth0 interface for each host (ifconfig)" 16 | p = pexpect.spawn( 'python -m mininet.examples.multitest' ) 17 | p.expect( '(\d+)% dropped' ) 18 | dropped = int( p.match.group( 1 ) ) 19 | self.assertEqual( dropped, 0 ) 20 | ifCount = 0 21 | while True: 22 | index = p.expect( [ 'h\d-eth0', self.prompt ] ) 23 | if index == 0: 24 | ifCount += 1 25 | elif index == 1: 26 | p.sendline( 'exit' ) 27 | break 28 | p.wait() 29 | self.assertEqual( ifCount, 4 ) 30 | 31 | if __name__ == '__main__': 32 | unittest.main() 33 | -------------------------------------------------------------------------------- /mininet/util/versioncheck.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from subprocess import check_output as co 4 | from sys import exit, version_info 5 | 6 | def run(*args, **kwargs): 7 | "Run co and decode for python3" 8 | result = co(*args, **kwargs) 9 | return result.decode() if version_info[ 0 ] >= 3 else result 10 | 11 | # Actually run bin/mn rather than importing via python path 12 | version = 'Mininet ' + run( 'PYTHONPATH=. bin/mn --version 2>&1', shell=True ) 13 | version = version.strip() 14 | 15 | # Find all Mininet path references 16 | lines = run( "egrep -or 'Mininet [0-9\.\+]+\w*' *", shell=True ) 17 | 18 | error = False 19 | 20 | for line in lines.split( '\n' ): 21 | if line and 'Binary' not in line: 22 | fname, fversion = line.split( ':' ) 23 | if version != fversion: 24 | print( "%s: incorrect version '%s' (should be '%s')" % ( 25 | fname, fversion, version ) ) 26 | error = True 27 | 28 | if error: 29 | exit( 1 ) 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 2 | ![python](https://img.shields.io/badge/python-3.6%20%7C%203.7-blue.svg?cacheSeconds=2592000) 3 | [![Build Status](https://travis-ci.org/Giuseppe1992/Distrinet.svg?branch=master)](https://travis-ci.org/github/Giuseppe1992/Distrinet) 4 | 5 | # Archive Soon 6 | 7 | From Giuseppe: "Hi, unfortunately I am not able to maintain Distrinet regularly since I am working on other projects. I will Archive the project soon, so you are free to clone and extend it, but I will not maintain it. Best Regards Giuseppe" 8 | 9 | # Distrinet 10 | 11 | Distrinet is a Distributed SDN Network Emulation Tool able to run in Cloud (Amazon AWS Platform in this version) or Physical Clusters ( Beta Version ). 12 | 13 | You can find the installation and configuration tutorial at: https://distrinet-emu.github.io 14 | 15 | Distrinet is based on [Mininet](http://mininet.org) (https://github.com/mininet/mininet) 16 | 17 | 18 | -------------------------------------------------------------------------------- /mininet/examples/test/test_emptynet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for emptynet.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | 10 | class testEmptyNet( unittest.TestCase ): 11 | 12 | prompt = 'mininet>' 13 | 14 | def testEmptyNet( self ): 15 | "Run simple CLI tests: pingall (verify 0% drop) and iperf (sanity)" 16 | p = pexpect.spawn( 'python -m mininet.examples.emptynet' ) 17 | p.expect( self.prompt ) 18 | # pingall test 19 | p.sendline( 'pingall' ) 20 | p.expect ( '(\d+)% dropped' ) 21 | percent = int( p.match.group( 1 ) ) if p.match else -1 22 | self.assertEqual( percent, 0 ) 23 | p.expect( self.prompt ) 24 | # iperf test 25 | p.sendline( 'iperf' ) 26 | p.expect( "Results: \['[\d.]+ .bits/sec', '[\d.]+ .bits/sec'\]" ) 27 | p.expect( self.prompt ) 28 | p.sendline( 'exit' ) 29 | p.wait() 30 | 31 | if __name__ == '__main__': 32 | unittest.main() 33 | -------------------------------------------------------------------------------- /mininet/util/m: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Attach to a Mininet host and run a command 4 | 5 | if [ -z $1 ]; then 6 | echo "usage: $0 host cmd [args...]" 7 | exit 1 8 | else 9 | host=$1 10 | fi 11 | 12 | pid=`ps ax | grep "mininet:$host$" | grep bash | grep -v mnexec | awk '{print $1};'` 13 | 14 | if echo $pid | grep -q ' '; then 15 | echo "Error: found multiple mininet:$host processes" 16 | exit 2 17 | fi 18 | 19 | if [ "$pid" == "" ]; then 20 | echo "Could not find Mininet host $host" 21 | exit 3 22 | fi 23 | 24 | if [ -z $2 ]; then 25 | cmd='bash' 26 | else 27 | shift 28 | cmd=$* 29 | fi 30 | 31 | cgroup=/sys/fs/cgroup/cpu/$host 32 | if [ -d "$cgroup" ]; then 33 | cg="-g $host" 34 | fi 35 | 36 | # Check whether host should be running in a chroot dir 37 | rootdir="/var/run/mn/$host/root" 38 | if [ -d $rootdir -a -x $rootdir/bin/bash ]; then 39 | cmd="'cd `pwd`; exec $cmd'" 40 | cmd="chroot $rootdir /bin/bash -c $cmd" 41 | fi 42 | 43 | cmd="exec sudo mnexec $cg -a $pid $cmd" 44 | eval $cmd 45 | -------------------------------------------------------------------------------- /mininet/.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | sudo: required 3 | 4 | matrix: 5 | include: 6 | - dist: trusty 7 | python: 2.7 8 | env: dist="14.04 LTS trusty" 9 | - dist: trusty 10 | python: 3.6 11 | env: dist="14.04 LTS trusty" 12 | 13 | before_install: 14 | - sudo apt-get update -qq 15 | - sudo apt-get install -qq vlan 16 | - PYTHON=`which python` util/install.sh -n 17 | 18 | install: 19 | - bash -c "if [ `lsb_release -rs` == '14.04' ]; then make codecheck; fi" 20 | - pip install pexpect || pip3 install pexpect 21 | - util/install.sh -nfvw 22 | 23 | script: 24 | - alias sudo="sudo env PATH=$PATH" 25 | - export PYTHON=`which python` 26 | - echo 'px import sys; print(sys.version_info)' | sudo $PYTHON bin/mn -v output 27 | - sudo $PYTHON bin/mn --test pingall 28 | - sudo $PYTHON mininet/test/runner.py -v -quick 29 | - sudo $PYTHON examples/test/runner.py -v -quick 30 | 31 | notifications: 32 | email: 33 | on_success: never 34 | 35 | # More details: https://docs.travis-ci.com/user/notifications 36 | -------------------------------------------------------------------------------- /mininet/examples/test/test_treeping64.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for treeping64.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | import sys 10 | 11 | class testTreePing64( unittest.TestCase ): 12 | 13 | prompt = 'mininet>' 14 | 15 | @unittest.skipIf( '-quick' in sys.argv, 'long test' ) 16 | def testTreePing64( self ): 17 | "Run the example and verify ping results" 18 | p = pexpect.spawn( 'python -m mininet.examples.treeping64' ) 19 | p.expect( 'Tree network ping results:', timeout=6000 ) 20 | count = 0 21 | while True: 22 | index = p.expect( [ '(\d+)% packet loss', pexpect.EOF ] ) 23 | if index == 0: 24 | percent = int( p.match.group( 1 ) ) if p.match else -1 25 | self.assertEqual( percent, 0 ) 26 | count += 1 27 | else: 28 | break 29 | self.assertTrue( count > 0 ) 30 | 31 | if __name__ == '__main__': 32 | unittest.main() 33 | -------------------------------------------------------------------------------- /mininet/examples/test/test_nat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for nat.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | from mininet.util import quietRun 10 | 11 | destIP = '8.8.8.8' # Google DNS 12 | 13 | class testNAT( unittest.TestCase ): 14 | 15 | prompt = 'mininet>' 16 | 17 | @unittest.skipIf( '0 received' in quietRun( 'ping -c 1 %s' % destIP ), 18 | 'Destination IP is not reachable' ) 19 | def testNAT( self ): 20 | "Attempt to ping an IP on the Internet and verify 0% packet loss" 21 | p = pexpect.spawn( 'python -m mininet.examples.nat' ) 22 | p.expect( self.prompt ) 23 | p.sendline( 'h1 ping -c 1 %s' % destIP ) 24 | p.expect ( '(\d+)% packet loss' ) 25 | percent = int( p.match.group( 1 ) ) if p.match else -1 26 | p.expect( self.prompt ) 27 | p.sendline( 'exit' ) 28 | p.wait() 29 | self.assertEqual( percent, 0 ) 30 | 31 | if __name__ == '__main__': 32 | unittest.main() 33 | -------------------------------------------------------------------------------- /conf/conf.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | ssh: 4 | pub_id: "YOUR PUBLIC ID" 5 | user: "root" 6 | client_keys: ["/Users/giuseppe/.ssh/id_rsa"] 7 | bastion: "Bastion host IP 'xxx.xxx.xxx.xxx'" 8 | 9 | port_forwarding: 10 | - local: 8181 11 | proto: 'tcp' 12 | ip: '192.168.0.250' 13 | remote: 8181 14 | 15 | aws: 16 | region: "eu-central-1" 17 | user: "ubuntu" 18 | volumeSize: "8" 19 | image_name: "ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-20190722.1" 20 | key_name_aws: "id_rsa" 21 | network_acl: 22 | - IpProtocol: "-1" 23 | FromPort: 1 24 | ToPort: 65353 25 | IpRanges: 26 | - CidrIp: "0.0.0.0/0" 27 | 28 | g5k: 29 | g5k_user: "your username" 30 | g5k_password: "your password" 31 | image_name: "ubuntu1804-x64-python3" 32 | location: "nancy" 33 | cluster: "grisou" 34 | 35 | cluster: 36 | user: "root" 37 | 38 | mapper: 39 | physical_infrastructure_path: "PATH TO JSON FILE (do not include .json)" 40 | cloud_instances_prices: "PATH TO JSON FILE (do not include .json)" 41 | -------------------------------------------------------------------------------- /mininet/debian/changelog: -------------------------------------------------------------------------------- 1 | mininet (2.1.0-0ubuntu1) saucy; urgency=low 2 | 3 | * Add 2.1.0 final packaging 4 | 5 | -- Bob Lantz Wed, 18 Sep 2013 22:43:47 -0700 6 | 7 | mininet (2.1.0~rc1-0ubuntu1) saucy; urgency=low 8 | 9 | * New upstream release candidate: 10 | - d/control: Drop dependency on python-networkx, add iperf, socat 11 | and cgroup-bin to Depends. 12 | 13 | -- James Page Wed, 28 Aug 2013 10:10:20 +0100 14 | 15 | mininet (2.0.0-0ubuntu1) raring; urgency=low 16 | 17 | * New upstream release. 18 | 19 | -- James Page Wed, 19 Dec 2012 15:48:01 +0000 20 | 21 | mininet (2.0.0~rc1-0ubuntu1) quantal; urgency=low 22 | 23 | * New upstream release. 24 | * Update copyright to match upstream release 25 | * Fix this message 26 | 27 | -- Bob Lantz Sun, 18 Nov 2012 00:15:09 -0800 28 | 29 | mininet (2.0.0~d4-0ubuntu1) quantal; urgency=low 30 | 31 | * Initial release. 32 | 33 | -- Bob Lantz Tue, 07 Aug 2012 14:11:27 -0700 34 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2019 Giuseppe Di Lena, Damien Saucez 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | -------------------------------------------------------------------------------- /mininet/examples/test/test_tree1024.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for tree1024.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | import sys 10 | 11 | class testTree1024( unittest.TestCase ): 12 | 13 | prompt = 'mininet>' 14 | 15 | @unittest.skipIf( '-quick' in sys.argv, 'long test' ) 16 | def testTree1024( self ): 17 | "Run the example and do a simple ping test from h1 to h1024" 18 | p = pexpect.spawn( 'python -m mininet.examples.tree1024' ) 19 | p.expect( self.prompt, timeout=6000 ) # it takes awhile to set up 20 | p.sendline( 'h1 ping -c 20 h1024' ) 21 | p.expect ( '(\d+)% packet loss' ) 22 | packetLossPercent = int( p.match.group( 1 ) ) if p.match else -1 23 | p.expect( self.prompt ) 24 | p.sendline( 'exit' ) 25 | p.wait() 26 | # Tolerate slow startup on some systems - we should revisit this 27 | # and determine the root cause. 28 | self.assertLess( packetLossPercent, 60 ) 29 | 30 | if __name__ == '__main__': 31 | unittest.main() 32 | -------------------------------------------------------------------------------- /mininet/examples/treeping64.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | "Create a 64-node tree network, and test connectivity using ping." 4 | 5 | 6 | from mininet.log import setLogLevel, info 7 | from mininet.node import UserSwitch, OVSKernelSwitch # , KernelSwitch 8 | from mininet.topolib import TreeNet 9 | 10 | def treePing64(): 11 | "Run ping test on 64-node tree networks." 12 | 13 | results = {} 14 | switches = { # 'reference kernel': KernelSwitch, 15 | 'reference user': UserSwitch, 16 | 'Open vSwitch kernel': OVSKernelSwitch } 17 | 18 | for name in switches: 19 | info( "*** Testing", name, "datapath\n" ) 20 | switch = switches[ name ] 21 | network = TreeNet( depth=2, fanout=8, switch=switch ) 22 | result = network.run( network.pingAll ) 23 | results[ name ] = result 24 | 25 | info( "\n*** Tree network ping results:\n" ) 26 | for name in switches: 27 | info( "%s: %d%% packet loss\n" % ( name, results[ name ] ) ) 28 | info( '\n' ) 29 | 30 | if __name__ == '__main__': 31 | setLogLevel( 'info' ) 32 | treePing64() 33 | -------------------------------------------------------------------------------- /mininet/util/kbuild/version_vars.patch: -------------------------------------------------------------------------------- 1 | --- /usr/share/kernel-package/ruleset/misc/version_vars.mk 2010-03-25 18:14:41.000000000 -0700 2 | +++ version_vars.mk 2010-03-03 06:46:59.000000000 -0800 3 | @@ -138,11 +138,13 @@ 4 | EXTRAV_ARG := 5 | endif 6 | 7 | -UTS_RELEASE_HEADER=$(call doit,if [ -f include/linux/utsrelease.h ]; then \ 8 | +UTS_RELEASE_HEADER=$(call doit, if [ -f include/generated/utsrelease.h ]; then \ 9 | + echo include/generated/utsrelease.h; \ 10 | + else if [ -f include/linux/utsrelease.h ]; then \ 11 | echo include/linux/utsrelease.h; \ 12 | else \ 13 | echo include/linux/version.h ; \ 14 | - fi) 15 | + fi fi) 16 | UTS_RELEASE_VERSION=$(call doit,if [ -f $(UTS_RELEASE_HEADER) ]; then \ 17 | grep 'define UTS_RELEASE' $(UTS_RELEASE_HEADER) | \ 18 | perl -nle 'm/^\s*\#define\s+UTS_RELEASE\s+("?)(\S+)\1/g && print $$2;';\ 19 | -------------------------------------------------------------------------------- /mininet/mininet/test/runner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Run all mininet core tests 5 | -v : verbose output 6 | -quick : skip tests that take more than ~30 seconds 7 | """ 8 | 9 | from unittest import defaultTestLoader, TextTestRunner 10 | import os 11 | import sys 12 | from mininet.util import ensureRoot 13 | from mininet.clean import cleanup 14 | from mininet.log import setLogLevel 15 | 16 | def runTests( testDir, verbosity=1 ): 17 | "discover and run all tests in testDir" 18 | # ensure root and cleanup before starting tests 19 | ensureRoot() 20 | cleanup() 21 | # discover all tests in testDir 22 | testSuite = defaultTestLoader.discover( testDir ) 23 | # run tests 24 | success = ( TextTestRunner( verbosity=verbosity ) 25 | .run( testSuite ).wasSuccessful() ) 26 | sys.exit( 0 if success else 1 ) 27 | 28 | if __name__ == '__main__': 29 | setLogLevel( 'warning' ) 30 | # get the directory containing example tests 31 | thisdir = os.path.dirname( os.path.realpath( __file__ ) ) 32 | vlevel = 2 if '-v' in sys.argv else 1 33 | runTests( testDir=thisdir, verbosity=vlevel ) 34 | -------------------------------------------------------------------------------- /mininet/examples/emptynet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | This example shows how to create an empty Mininet object 5 | (without a topology object) and add nodes to it manually. 6 | """ 7 | 8 | from mininet.net import Mininet 9 | from mininet.node import Controller 10 | from mininet.cli import CLI 11 | from mininet.log import setLogLevel, info 12 | 13 | def emptyNet(): 14 | 15 | "Create an empty network and add nodes to it." 16 | 17 | net = Mininet( controller=Controller ) 18 | 19 | info( '*** Adding controller\n' ) 20 | net.addController( 'c0' ) 21 | 22 | info( '*** Adding hosts\n' ) 23 | h1 = net.addHost( 'h1', ip='10.0.0.1' ) 24 | h2 = net.addHost( 'h2', ip='10.0.0.2' ) 25 | 26 | info( '*** Adding switch\n' ) 27 | s3 = net.addSwitch( 's3' ) 28 | 29 | info( '*** Creating links\n' ) 30 | net.addLink( h1, s3 ) 31 | net.addLink( h2, s3 ) 32 | 33 | info( '*** Starting network\n') 34 | net.start() 35 | 36 | info( '*** Running CLI\n' ) 37 | CLI( net ) 38 | 39 | info( '*** Stopping network' ) 40 | net.stop() 41 | 42 | if __name__ == '__main__': 43 | setLogLevel( 'info' ) 44 | emptyNet() 45 | -------------------------------------------------------------------------------- /mininet/examples/test/test_simpleperf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for simpleperf.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | import sys 10 | from mininet.log import setLogLevel 11 | 12 | from mininet.examples.simpleperf import SingleSwitchTopo 13 | 14 | class testSimplePerf( unittest.TestCase ): 15 | 16 | @unittest.skipIf( '-quick' in sys.argv, 'long test' ) 17 | def testE2E( self ): 18 | "Run the example and verify iperf results" 19 | # 10 Mb/s, plus or minus 20% tolerance 20 | BW = 10 21 | TOLERANCE = .2 22 | p = pexpect.spawn( 'python -m mininet.examples.simpleperf testmode' ) 23 | # check iperf results 24 | p.expect( "Results: \['10M', '([\d\.]+) .bits/sec", timeout=480 ) 25 | measuredBw = float( p.match.group( 1 ) ) 26 | lowerBound = BW * ( 1 - TOLERANCE ) 27 | upperBound = BW + ( 1 + TOLERANCE ) 28 | self.assertGreaterEqual( measuredBw, lowerBound ) 29 | self.assertLessEqual( measuredBw, upperBound ) 30 | p.wait() 31 | 32 | if __name__ == '__main__': 33 | setLogLevel( 'warning' ) 34 | unittest.main() 35 | -------------------------------------------------------------------------------- /mininet/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Mininet Contributors 2 | 3 | Mininet is an open source project and we gratefully acknowledge 4 | the many contributions to the project! If you have contributed 5 | code into the project and are not on this list, please let us know 6 | or send a pull request. 7 | 8 | Contributors include: 9 | 10 | Mininet Core Team (and alumni) 11 | 12 | Bob Lantz 13 | Brandon Heller 14 | Nikhil Handigol 15 | Vimal Jeyakumar 16 | Brian O'Connor 17 | Cody Burkard 18 | 19 | Additional Mininet Contributors 20 | 21 | Tomasz Buchert 22 | Gustavo Pantuza Coelho Pinto 23 | Fernando Cappi 24 | Ryan Cox 25 | Shaun Crampton 26 | David Erickson 27 | Glen Gibb 28 | Andrew Ferguson 29 | Eder Leao Fernandes 30 | Gregory Gee 31 | Jon Hall 32 | Roan Huang 33 | Vitaly Ivanov 34 | Babis Kaidos 35 | Rich Lane 36 | Rémy Léone 37 | Zi Shen Lim 38 | David Mahler 39 | Murphy McCauley 40 | José Pedro Oliveira 41 | James Page 42 | Angad Singh 43 | Piyush Srivastava 44 | Ed Swierk 45 | Darshan Thaker 46 | Andreas Wundsam 47 | Isaku Yamahata 48 | Baohua Yang 49 | 50 | Thanks also to everyone who has submitted issues and pull 51 | requests on github, and to our friendly mininet-discuss 52 | mailing list! 53 | -------------------------------------------------------------------------------- /mininet/examples/popenpoll.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | "Monitor multiple hosts using popen()/pmonitor()" 4 | 5 | from mininet.net import Mininet 6 | from mininet.topo import SingleSwitchTopo 7 | from mininet.util import pmonitor 8 | from mininet.log import setLogLevel, info 9 | 10 | from time import time 11 | from signal import SIGINT 12 | 13 | def pmonitorTest( N=3, seconds=10 ): 14 | "Run pings and monitor multiple hosts using pmonitor" 15 | topo = SingleSwitchTopo( N ) 16 | net = Mininet( topo ) 17 | net.start() 18 | hosts = net.hosts 19 | info( "Starting test...\n" ) 20 | server = hosts[ 0 ] 21 | popens = {} 22 | for h in hosts: 23 | popens[ h ] = h.popen('ping', server.IP() ) 24 | info( "Monitoring output for", seconds, "seconds\n" ) 25 | endTime = time() + seconds 26 | for h, line in pmonitor( popens, timeoutms=500 ): 27 | if h: 28 | info( '<%s>: %s' % ( h.name, line ) ) 29 | if time() >= endTime: 30 | for p in popens.values(): 31 | p.send_signal( SIGINT ) 32 | net.stop() 33 | 34 | if __name__ == '__main__': 35 | setLogLevel( 'info' ) 36 | pmonitorTest() 37 | -------------------------------------------------------------------------------- /mininet/examples/popen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | This example monitors a number of hosts using host.popen() and 5 | pmonitor() 6 | """ 7 | 8 | 9 | from mininet.net import Mininet 10 | from mininet.node import CPULimitedHost 11 | from mininet.topo import SingleSwitchTopo 12 | from mininet.log import setLogLevel, info 13 | from mininet.util import custom, pmonitor 14 | 15 | def monitorhosts( hosts=5, sched='cfs' ): 16 | "Start a bunch of pings and monitor them using popen" 17 | mytopo = SingleSwitchTopo( hosts ) 18 | cpu = .5 / hosts 19 | myhost = custom( CPULimitedHost, cpu=cpu, sched=sched ) 20 | net = Mininet( topo=mytopo, host=myhost ) 21 | net.start() 22 | # Start a bunch of pings 23 | popens = {} 24 | last = net.hosts[ -1 ] 25 | for host in net.hosts: 26 | popens[ host ] = host.popen( "ping -c5 %s" % last.IP() ) 27 | last = host 28 | # Monitor them and print output 29 | for host, line in pmonitor( popens ): 30 | if host: 31 | info( "<%s>: %s" % ( host.name, line ) ) 32 | # Done 33 | net.stop() 34 | 35 | if __name__ == '__main__': 36 | setLogLevel( 'info' ) 37 | monitorhosts( hosts=5 ) 38 | -------------------------------------------------------------------------------- /mininet/custom/iperf_test.py: -------------------------------------------------------------------------------- 1 | import time 2 | from mininet.log import info, debug, warn, error, output 3 | from mininet.dutil import (default_images) 4 | 5 | def iperf_test(mn): 6 | topo = mn.topo 7 | # iperf servers 8 | for h in mn.hosts: 9 | cmd = "nohup iperf -s &" 10 | h.cmd(cmd) 11 | 12 | # iperf clients 13 | l = len(mn.hosts) 14 | half = int(l/2) 15 | info ("*** Generate background traffic:") 16 | for i in range(half-1): 17 | info (" {}->{}".format(mn.hosts[i], mn.hosts[-i-1])) 18 | t = 120 19 | cmd = "nohup iperf -t {} -c {} &".format(t, mn.hosts[-i-1].IP()) 20 | mn.hosts[i].cmd(cmd) 21 | info ("\n") 22 | 23 | info ("*** Measure throughput: {}->{}\n".format(mn.hosts[half-1], mn.hosts[-(half-1)-1])) 24 | time.sleep(20) 25 | cmd = "iperf -t {} -c {}".format(60, mn.hosts[-(half-1)-1].IP()) 26 | iperfOutput = mn.hosts[half-1].cmd(cmd) 27 | output (mn._parseIperf(iperfOutput)) 28 | 29 | for h in mn.hosts: 30 | h.cmd("killall -9 iperf") 31 | 32 | # we need the right images to run iperf 33 | PREBUILD = [default_images] 34 | 35 | # adding the test in the suite 36 | TESTS = {'iperfall':iperf_test} 37 | -------------------------------------------------------------------------------- /mininet/examples/multitest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | This example shows how to create a network and run multiple tests. 5 | For a more complicated test example, see udpbwtest.py. 6 | """ 7 | 8 | from mininet.cli import CLI 9 | from mininet.log import lg, info 10 | from mininet.net import Mininet 11 | from mininet.node import OVSKernelSwitch 12 | from mininet.topolib import TreeTopo 13 | 14 | def ifconfigTest( net ): 15 | "Run ifconfig on all hosts in net." 16 | hosts = net.hosts 17 | for host in hosts: 18 | info( host.cmd( 'ifconfig' ) ) 19 | 20 | if __name__ == '__main__': 21 | lg.setLogLevel( 'info' ) 22 | info( "*** Initializing Mininet and kernel modules\n" ) 23 | OVSKernelSwitch.setup() 24 | info( "*** Creating network\n" ) 25 | network = Mininet( TreeTopo( depth=2, fanout=2 ), switch=OVSKernelSwitch ) 26 | info( "*** Starting network\n" ) 27 | network.start() 28 | info( "*** Running ping test\n" ) 29 | network.pingAll() 30 | info( "*** Running ifconfig test\n" ) 31 | ifconfigTest( network ) 32 | info( "*** Starting CLI (type 'exit' to exit)\n" ) 33 | CLI( network ) 34 | info( "*** Stopping network\n" ) 35 | network.stop() 36 | -------------------------------------------------------------------------------- /mininet/examples/controllers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | Create a network where different switches are connected to 5 | different controllers, by creating a custom Switch() subclass. 6 | """ 7 | 8 | from mininet.net import Mininet 9 | from mininet.node import OVSSwitch, Controller, RemoteController 10 | from mininet.topolib import TreeTopo 11 | from mininet.log import setLogLevel 12 | from mininet.cli import CLI 13 | 14 | setLogLevel( 'info' ) 15 | 16 | # Two local and one "external" controller (which is actually c0) 17 | # Ignore the warning message that the remote isn't (yet) running 18 | c0 = Controller( 'c0', port=6633 ) 19 | c1 = Controller( 'c1', port=6634 ) 20 | c2 = RemoteController( 'c2', ip='127.0.0.1', port=6633 ) 21 | 22 | cmap = { 's1': c0, 's2': c1, 's3': c2 } 23 | 24 | class MultiSwitch( OVSSwitch ): 25 | "Custom Switch() subclass that connects to different controllers" 26 | def start( self, controllers ): 27 | return OVSSwitch.start( self, [ cmap[ self.name ] ] ) 28 | 29 | topo = TreeTopo( depth=2, fanout=2 ) 30 | net = Mininet( topo=topo, switch=MultiSwitch, build=False ) 31 | for c in [ c0, c1 ]: 32 | net.addController(c) 33 | net.build() 34 | net.start() 35 | CLI( net ) 36 | net.stop() 37 | -------------------------------------------------------------------------------- /mininet/examples/test/test_limit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for limit.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | import sys 10 | 11 | class testLimit( unittest.TestCase ): 12 | 13 | @unittest.skipIf( '-quick' in sys.argv, 'long test' ) 14 | def testLimit( self ): 15 | "Verify that CPU limits are within a 2% tolerance of limit for each scheduler" 16 | p = pexpect.spawn( 'python -m mininet.examples.limit' ) 17 | opts = [ '\*\*\* Testing network ([\d\.]+) Mbps', 18 | '\*\*\* Results: \[([\d\., ]+)\]', 19 | pexpect.EOF ] 20 | count = 0 21 | bw = 0 22 | tolerance = 2 23 | while True: 24 | index = p.expect( opts ) 25 | if index == 0: 26 | bw = float( p.match.group( 1 ) ) 27 | count += 1 28 | elif index == 1: 29 | results = p.match.group( 1 ) 30 | for x in results.split( ',' ): 31 | result = float( x ) 32 | self.assertTrue( result < bw + tolerance ) 33 | self.assertTrue( result > bw - tolerance ) 34 | else: 35 | break 36 | 37 | self.assertTrue( count > 0 ) 38 | 39 | if __name__ == '__main__': 40 | unittest.main() 41 | -------------------------------------------------------------------------------- /mininet/examples/baresshd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | "This example doesn't use OpenFlow, but attempts to run sshd in a namespace." 4 | 5 | import sys 6 | 7 | from mininet.node import Host 8 | from mininet.util import ensureRoot, waitListening 9 | from mininet.log import info, warn, output 10 | 11 | 12 | ensureRoot() 13 | timeout = 5 14 | 15 | info( "*** Creating nodes\n" ) 16 | h1 = Host( 'h1' ) 17 | 18 | root = Host( 'root', inNamespace=False ) 19 | 20 | info( "*** Creating link\n" ) 21 | h1.linkTo( root ) 22 | 23 | info( h1 ) 24 | 25 | info( "*** Configuring nodes\n" ) 26 | h1.setIP( '10.0.0.1', 8 ) 27 | root.setIP( '10.0.0.2', 8 ) 28 | 29 | info( "*** Creating banner file\n" ) 30 | f = open( '/tmp/%s.banner' % h1.name, 'w' ) 31 | f.write( 'Welcome to %s at %s\n' % ( h1.name, h1.IP() ) ) 32 | f.close() 33 | 34 | info( "*** Running sshd\n" ) 35 | cmd = '/usr/sbin/sshd -o UseDNS=no -u0 -o "Banner /tmp/%s.banner"' % h1.name 36 | # add arguments from the command line 37 | if len( sys.argv ) > 1: 38 | cmd += ' ' + ' '.join( sys.argv[ 1: ] ) 39 | h1.cmd( cmd ) 40 | listening = waitListening( server=h1, port=22, timeout=timeout ) 41 | 42 | if listening: 43 | output( "*** You may now ssh into", h1.name, "at", h1.IP(), '\n' ) 44 | else: 45 | warn( "*** Warning: after %s seconds, %s is not listening on port 22" 46 | % ( timeout, h1.name ), '\n' ) 47 | -------------------------------------------------------------------------------- /mininet/mininet/provision/basicprovision.py: -------------------------------------------------------------------------------- 1 | from mininet.provision.provision import Provision 2 | 3 | import requests 4 | import base64 5 | import json 6 | from time import sleep 7 | import paramiko 8 | import os 9 | 10 | SRC_PLAYBOOKS_DIR = "../../../../src/playbooks" 11 | DST_PLAYBOOKS_DIR = "/tmp/playbooks" 12 | 13 | 14 | class basicprovision(Provision): 15 | def __init__(self, username, master_ip, workers_ip, **kwargs): 16 | super(Provision, self).__init__(username, master_ip, workers_ip, **kwargs) 17 | self.username = username 18 | self.master = master_ip 19 | self.workers = workers_ip 20 | 21 | def deploy(self): 22 | sshMasterSession = self.createSshSession(host=self.master, username=self.username) 23 | self.setupMasterHost(SshSession=sshMasterSession) 24 | sleep(2) 25 | self.setAnsibleHosts(SshSession=sshMasterSession, MasterHostIp=self.master, WorkersList=self.workers) 26 | self.copyFilesInHost(SshSession=sshMasterSession, SrcDir=SRC_PLAYBOOKS_DIR, DstDir=DST_PLAYBOOKS_DIR) 27 | sleep(2) 28 | self.installEnvironment(SshSession=sshMasterSession, PlaybookPath=DST_PLAYBOOKS_DIR + "/install-lxd.yml") 29 | sleep(2) 30 | self.configureLxd(SshSession=sshMasterSession, MasterPrivateIp=self.master, PlaybookPath=DST_PLAYBOOKS_DIR) 31 | return self.master, self.workers 32 | -------------------------------------------------------------------------------- /mininet/examples/test/test_multipoll.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for multipoll.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | 10 | class testMultiPoll( unittest.TestCase ): 11 | 12 | def testMultiPoll( self ): 13 | "Verify that we receive one ping per second per host" 14 | p = pexpect.spawn( 'python -m mininet.examples.multipoll' ) 15 | opts = [ "\*\*\* (h\d) :" , 16 | "(h\d+): \d+ bytes from", 17 | "Monitoring output for (\d+) seconds", 18 | pexpect.EOF ] 19 | pings, seconds = {}, -1 20 | while True: 21 | index = p.expect( opts ) 22 | if index == 0: 23 | name = p.match.group( 1 ) 24 | pings[ name ] = 0 25 | elif index == 1: 26 | name = p.match.group( 1 ) 27 | pings[ name ] += 1 28 | elif index == 2: 29 | seconds = int( p.match.group( 1 ) ) 30 | else: 31 | break 32 | self.assertTrue( len( pings ) > 0 ) 33 | # make sure we have received at least one ping per second 34 | for count in pings.values(): 35 | self.assertTrue( count >= seconds, 36 | '%d pings < %d seconds' % ( count, seconds ) ) 37 | 38 | if __name__ == '__main__': 39 | unittest.main() 40 | -------------------------------------------------------------------------------- /mininet/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | "Setuptools params" 4 | 5 | from setuptools import setup, find_packages 6 | from os.path import join 7 | 8 | # Get version number from source tree 9 | import sys 10 | sys.path.append( '.' ) 11 | from mininet.net import VERSION 12 | 13 | scripts = [ join( 'bin', filename ) for filename in [ 'mn' ] ] 14 | 15 | modname = distname = 'mininet' 16 | 17 | setup( 18 | name=distname, 19 | version=VERSION, 20 | description='Process-based OpenFlow emulator', 21 | author='Bob Lantz', 22 | author_email='rlantz@cs.stanford.edu', 23 | packages=[ 'mininet', 'mininet.examples' ], 24 | long_description=""" 25 | Mininet is a network emulator which uses lightweight 26 | virtualization to create virtual networks for rapid 27 | prototyping of Software-Defined Network (SDN) designs 28 | using OpenFlow. http://mininet.org 29 | """, 30 | classifiers=[ 31 | "License :: OSI Approved :: BSD License", 32 | "Programming Language :: Python", 33 | "Development Status :: 5 - Production/Stable", 34 | "Intended Audience :: Developers", 35 | "Topic :: System :: Emulators", 36 | ], 37 | keywords='networking emulator protocol Internet OpenFlow SDN', 38 | license='BSD', 39 | install_requires=[ 40 | 'setuptools' 41 | ], 42 | scripts=scripts, 43 | ) 44 | -------------------------------------------------------------------------------- /mininet/util/colorfilters: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT THIS FILE! It was created by Wireshark 2 | @Bad TCP@tcp.analysis.flags@[0,0,0][65535,24383,24383] 3 | @HSRP State Change@hsrp.state != 8 && hsrp.state != 16@[0,0,0][65535,63222,0] 4 | @Spanning Tree Topology Change@stp.type == 0x80@[0,0,0][65535,63222,0] 5 | @OSPF State Change@ospf.msg != 1@[0,0,0][65535,63222,0] 6 | @ICMP errors@icmp.type eq 3 || icmp.type eq 4 || icmp.type eq 5 || icmp.type eq 11@[0,0,0][0,65535,3616] 7 | @ARP@arp@[55011,59486,65534][0,0,0] 8 | @ICMP@icmp@[49680,49737,65535][0,0,0] 9 | @TCP RST@tcp.flags.reset eq 1@[37008,0,0][65535,63121,32911] 10 | @TTL low or unexpected@( ! ip.dst == 224.0.0.0/4 && ip.ttl < 5) || (ip.dst == 224.0.0.0/24 && ip.ttl != 1)@[37008,0,0][65535,65535,65535] 11 | @of@of@[0,5,65535][65535,65535,65535] 12 | @Checksum Errors@cdp.checksum_bad==1 || edp.checksum_bad==1 || ip.checksum_bad==1 || tcp.checksum_bad==1 || udp.checksum_bad==1@[0,0,0][65535,24383,24383] 13 | @SMB@smb || nbss || nbns || nbipx || ipxsap || netbios@[65534,64008,39339][0,0,0] 14 | @HTTP@http || tcp.port == 80@[36107,65535,32590][0,0,0] 15 | @IPX@ipx || spx@[65534,58325,58808][0,0,0] 16 | @DCERPC@dcerpc@[51199,38706,65533][0,0,0] 17 | @Routing@hsrp || eigrp || ospf || bgp || cdp || vrrp || gvrp || igmp || ismp@[65534,62325,54808][0,0,0] 18 | @TCP SYN/FIN@tcp.flags & 0x02 || tcp.flags.fin == 1@[41026,41026,41026][0,0,0] 19 | @TCP@tcp@[59345,58980,65534][0,0,0] 20 | @UDP@udp@[28834,57427,65533][0,0,0] 21 | @Broadcast@eth[0] & 1@[65535,65535,65535][32768,32768,32768] 22 | -------------------------------------------------------------------------------- /mininet/examples/test/runner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Run all mininet.examples tests 5 | -v : verbose output 6 | -quick : skip tests that take more than ~30 seconds 7 | """ 8 | 9 | import unittest 10 | import os 11 | import sys 12 | from mininet.util import ensureRoot 13 | from mininet.clean import cleanup 14 | 15 | class MininetTestResult( unittest.TextTestResult ): 16 | def addFailure( self, test, err ): 17 | super( MininetTestResult, self ).addFailure( test, err ) 18 | cleanup() 19 | def addError( self,test, err ): 20 | super( MininetTestResult, self ).addError( test, err ) 21 | cleanup() 22 | 23 | class MininetTestRunner( unittest.TextTestRunner ): 24 | def _makeResult( self ): 25 | return MininetTestResult( self.stream, self.descriptions, self.verbosity ) 26 | 27 | def runTests( testDir, verbosity=1 ): 28 | "discover and run all tests in testDir" 29 | # ensure root and cleanup before starting tests 30 | ensureRoot() 31 | cleanup() 32 | # discover all tests in testDir 33 | testSuite = unittest.defaultTestLoader.discover( testDir ) 34 | # run tests 35 | success = MininetTestRunner( verbosity=verbosity ).run( testSuite ).wasSuccessful() 36 | sys.exit( 0 if success else 1 ) 37 | 38 | if __name__ == '__main__': 39 | # get the directory containing example tests 40 | testDir = os.path.dirname( os.path.realpath( __file__ ) ) 41 | verbosity = 2 if '-v' in sys.argv else 1 42 | runTests( testDir, verbosity ) 43 | -------------------------------------------------------------------------------- /mininet/examples/intfoptions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ''' 4 | example of using various TCIntf options. 5 | reconfigures a single interface using intf.config() 6 | to use different traffic control commands to test 7 | bandwidth, loss, and delay 8 | ''' 9 | 10 | from mininet.net import Mininet 11 | from mininet.log import setLogLevel, info 12 | from mininet.link import TCLink 13 | 14 | def intfOptions(): 15 | "run various traffic control commands on a single interface" 16 | net = Mininet( autoStaticArp=True ) 17 | net.addController( 'c0' ) 18 | h1 = net.addHost( 'h1' ) 19 | h2 = net.addHost( 'h2' ) 20 | s1 = net.addSwitch( 's1' ) 21 | link1 = net.addLink( h1, s1, cls=TCLink ) 22 | net.addLink( h2, s1 ) 23 | net.start() 24 | 25 | # flush out latency from reactive forwarding delay 26 | net.pingAll() 27 | 28 | info( '\n*** Configuring one intf with bandwidth of 5 Mb\n' ) 29 | link1.intf1.config( bw=5 ) 30 | info( '\n*** Running iperf to test\n' ) 31 | net.iperf() 32 | 33 | info( '\n*** Configuring one intf with loss of 50%\n' ) 34 | link1.intf1.config( loss=50 ) 35 | info( '\n' ) 36 | net.iperf( ( h1, h2 ), l4Type='UDP' ) 37 | 38 | info( '\n*** Configuring one intf with delay of 15ms\n' ) 39 | link1.intf1.config( delay='15ms' ) 40 | info( '\n*** Run a ping to confirm delay\n' ) 41 | net.pingPairFull() 42 | 43 | info( '\n*** Done testing\n' ) 44 | net.stop() 45 | 46 | if __name__ == '__main__': 47 | setLogLevel( 'info' ) 48 | intfOptions() 49 | -------------------------------------------------------------------------------- /mininet/examples/test/test_popen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for popen.py and popenpoll.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | 10 | class testPopen( unittest.TestCase ): 11 | 12 | def pingTest( self, name ): 13 | "Verify that there are no dropped packets for each host" 14 | p = pexpect.spawn( 'python -m %s' % name ) 15 | opts = [ "<(h\d+)>: PING ", 16 | "<(h\d+)>: (\d+) packets transmitted, (\d+) received", 17 | pexpect.EOF ] 18 | pings = {} 19 | while True: 20 | index = p.expect( opts ) 21 | if index == 0: 22 | name = p.match.group(1) 23 | pings[ name ] = 0 24 | elif index == 1: 25 | name = p.match.group(1) 26 | transmitted = p.match.group(2) 27 | received = p.match.group(3) 28 | # verify no dropped packets 29 | self.assertEqual( received, transmitted ) 30 | pings[ name ] += 1 31 | else: 32 | break 33 | self.assertTrue( len(pings) > 0 ) 34 | # verify that each host has gotten results 35 | for count in pings.values(): 36 | self.assertEqual( count, 1 ) 37 | 38 | def testPopen( self ): 39 | self.pingTest( 'mininet.examples.popen' ) 40 | 41 | def testPopenPoll( self ): 42 | self.pingTest( 'mininet.examples.popenpoll' ) 43 | 44 | if __name__ == '__main__': 45 | unittest.main() 46 | -------------------------------------------------------------------------------- /mininet/examples/test/test_cpu.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for cpu.py 5 | 6 | results format: 7 | 8 | sched cpu received bits/sec 9 | cfs 50% 8.14e+09 10 | cfs 40% 6.48e+09 11 | cfs 30% 4.56e+09 12 | cfs 20% 2.84e+09 13 | cfs 10% 1.29e+09 14 | 15 | """ 16 | 17 | import unittest 18 | from mininet.util import pexpect 19 | import sys 20 | 21 | class testCPU( unittest.TestCase ): 22 | 23 | prompt = 'mininet>' 24 | 25 | @unittest.skipIf( '-quick' in sys.argv, 'long test' ) 26 | def testCPU( self ): 27 | "Verify that CPU utilization is monotonically decreasing for each scheduler" 28 | p = pexpect.spawn( 'python -m mininet.examples.cpu', timeout=300 ) 29 | # matches each line from results( shown above ) 30 | opts = [ '([a-z]+)\t([\d\.]+)%\t([\d\.e\+]+)', 31 | pexpect.EOF ] 32 | scheds = [] 33 | while True: 34 | index = p.expect( opts ) 35 | if index == 0: 36 | sched = p.match.group( 1 ) 37 | cpu = float( p.match.group( 2 ) ) 38 | bw = float( p.match.group( 3 ) ) 39 | if sched not in scheds: 40 | scheds.append( sched ) 41 | else: 42 | self.assertTrue( bw < previous_bw, 43 | "%e should be less than %e\n" % 44 | ( bw, previous_bw ) ) 45 | previous_bw = bw 46 | else: 47 | break 48 | 49 | self.assertTrue( len( scheds ) > 0 ) 50 | 51 | if __name__ == '__main__': 52 | unittest.main() 53 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | from pathlib import Path 3 | from shutil import copy 4 | from os import system 5 | 6 | # create .distrinet/conf.yml configuration in the user home directory 7 | home_dir = Path.home() 8 | conf_dir = home_dir / ".distrinet" 9 | conf_dir.mkdir(0o777, parents=True, exist_ok=True) 10 | copy('conf/conf.yml', str(conf_dir)) 11 | copy('conf/general_purpose.json', str(conf_dir)) 12 | copy('conf/gros_partial.json', str(conf_dir)) 13 | # get the required packages form requiremets.txt 14 | with open('requirements.txt') as f: 15 | required = f.read().splitlines() 16 | required = list(filter(lambda x: not x.startswith("#") and not x.startswith("git"), required)) 17 | print(f"packages required from requirements.txt: {required}") 18 | 19 | #install mininet 20 | system("mininet/util/install.sh -a") 21 | system("sudo pip3 install git+git://github.com/Giuseppe1992/mapping_distrinet-1.git") 22 | 23 | setup( 24 | name='Distrinet', 25 | version='1.2', 26 | python_requires='>=3.6', 27 | packages=["mininet"], 28 | url='https://github.com/Giuseppe1992/Distrinet/tree/master', 29 | dependency_links=['http://github.com/mininet/mininet/tarball/master#egg=mininet', 30 | "https://github.com/Giuseppe1992/mapping_distrinet-1.git"], 31 | install_requires=required, 32 | license='MIT', 33 | author='Giuseppe Di Lena', 34 | author_email='giuseppedilena92@gmail.com', 35 | description='Distrinet v.1.2', 36 | data_files= [(".distrinet", ["conf/conf.yml"])], 37 | scripts=["mininet/bin/dmn"], 38 | include_package_data = True, 39 | zip_safe = True 40 | ) 41 | -------------------------------------------------------------------------------- /mininet/mininet/provision/playbooks/install-lxd-old.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # 3 | - hosts : master 4 | remote_user: root 5 | tasks : 6 | 7 | - name : Download switch 8 | get_url: 9 | url : http://www-sop.inria.fr/members/Damien.Saucez/images/switch.tar.gz 10 | dest: ~/switch.tar.gz 11 | mode: 0666 12 | 13 | - name : Download ubuntu18:04 14 | get_url: 15 | url : http://www-sop.inria.fr/members/Damien.Saucez/images/ubuntu.tar.gz 16 | dest: ~/ubuntu.tar.gz 17 | mode: 0666 18 | 19 | 20 | 21 | - hosts : all 22 | remote_user: root 23 | tasks : 24 | - name: install python3-pip 25 | apt : 26 | update_cache: true 27 | name : python3-pip 28 | 29 | - name: install python-pip 30 | apt : 31 | name : python-pip 32 | 33 | - name: install htop 34 | apt : 35 | name: htop 36 | 37 | - name: install ethtool 38 | apt : 39 | name: ethtool 40 | 41 | - name: install bridge-utils 42 | apt : 43 | name: bridge-utils 44 | 45 | - name: install net-tools 46 | apt : 47 | name: net-tools 48 | 49 | - name: install pexpect 50 | pip : 51 | name: pexpect 52 | 53 | - name: install ovs 54 | apt : 55 | name: openvswitch-switch 56 | 57 | - name: install btrfs-tools 58 | apt: 59 | name: btrfs-tools 60 | 61 | - name: install lxd 62 | apt: 63 | name: lxd 64 | 65 | - name: install lxd-client 66 | apt : 67 | name: lxd-client 68 | 69 | - name: install ryu 70 | apt: 71 | name: python3-ryu 72 | -------------------------------------------------------------------------------- /conf/gros_partial.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": [ 3 | { 4 | "id": "gros-76.nancy.grid5000.fr", 5 | "cores": 48, 6 | "memory": 131072.0 7 | }, 8 | { 9 | "id": "gros-84.nancy.grid5000.fr", 10 | "cores": 48, 11 | "memory": 131072.0 12 | }, 13 | { 14 | "id": "gros-89.nancy.grid5000.fr", 15 | "cores": 48, 16 | "memory": 131072.0 17 | }, 18 | { 19 | "id": "gros-97.nancy.grid5000.fr", 20 | "cores": 48, 21 | "memory": 131072.0 22 | }], 23 | "links": [ 24 | { 25 | "source": "gros-76.nancy.grid5000.fr", 26 | "target": "gw-nancy", 27 | "devices": [ 28 | { 29 | "source_device": "eth0", 30 | "target_device": "Ethernet7/1", 31 | "rate": 10000.0 32 | } 33 | ] 34 | }, 35 | { 36 | "source": "gros-84.nancy.grid5000.fr", 37 | "target": "gw-nancy", 38 | "devices": [ 39 | { 40 | "source_device": "eth0", 41 | "target_device": "Ethernet7/2", 42 | "rate": 10000.0 43 | } 44 | ] 45 | }, 46 | { 47 | "source": "gros-89.nancy.grid5000.fr", 48 | "target": "gw-nancy", 49 | "devices": [ 50 | { 51 | "source_device": "eth0", 52 | "target_device": "Ethernet7/3", 53 | "rate": 10000.0 54 | } 55 | ] 56 | }, 57 | { 58 | "source": "gros-97.nancy.grid5000.fr", 59 | "target": "gw-nancy", 60 | "devices": [ 61 | { 62 | "source_device": "eth0", 63 | "target_device": "Ethernet7/4", 64 | "rate": 10000.0 65 | } 66 | ] 67 | } 68 | 69 | ] 70 | } 71 | -------------------------------------------------------------------------------- /mininet/examples/test/test_controlnet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for controlnet.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | 10 | class testControlNet( unittest.TestCase ): 11 | 12 | prompt = 'mininet>' 13 | 14 | def testPingall( self ): 15 | "Simple pingall test that verifies 0% packet drop in data network" 16 | p = pexpect.spawn( 'python -m mininet.examples.controlnet' ) 17 | p.expect( self.prompt ) 18 | p.sendline( 'pingall' ) 19 | p.expect ( '(\d+)% dropped' ) 20 | percent = int( p.match.group( 1 ) ) if p.match else -1 21 | self.assertEqual( percent, 0 ) 22 | p.expect( self.prompt ) 23 | p.sendline( 'exit' ) 24 | p.wait() 25 | 26 | def testFailover( self ): 27 | "Kill controllers and verify that switch, s1, fails over properly" 28 | count = 1 29 | p = pexpect.spawn( 'python -m mininet.examples.controlnet' ) 30 | p.expect( self.prompt ) 31 | lp = pexpect.spawn( 'tail -f /tmp/s1-ofp.log' ) 32 | lp.expect( 'tcp:\d+\.\d+\.\d+\.(\d+):\d+: connected' ) 33 | ip = int( lp.match.group( 1 ) ) 34 | self.assertEqual( count, ip ) 35 | count += 1 36 | for c in [ 'c0', 'c1' ]: 37 | p.sendline( '%s ifconfig %s-eth0 down' % ( c, c) ) 38 | p.expect( self.prompt ) 39 | lp.expect( 'tcp:\d+\.\d+\.\d+\.(\d+):\d+: connected' ) 40 | ip = int( lp.match.group( 1 ) ) 41 | self.assertEqual( count, ip ) 42 | count += 1 43 | p.sendline( 'exit' ) 44 | p.wait() 45 | 46 | if __name__ == '__main__': 47 | unittest.main() 48 | -------------------------------------------------------------------------------- /mininet/examples/test/test_controllers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Tests for controllers.py and controllers2.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | 10 | class testControllers( unittest.TestCase ): 11 | 12 | prompt = 'mininet>' 13 | 14 | def connectedTest( self, name, cmap ): 15 | "Verify that switches are connected to the controller specified by cmap" 16 | p = pexpect.spawn( 'python -m %s' % name ) 17 | p.expect( self.prompt ) 18 | # but first a simple ping test 19 | p.sendline( 'pingall' ) 20 | p.expect ( '(\d+)% dropped' ) 21 | percent = int( p.match.group( 1 ) ) if p.match else -1 22 | self.assertEqual( percent, 0 ) 23 | p.expect( self.prompt ) 24 | # verify connected controller 25 | for switch in cmap: 26 | p.sendline( 'sh ovs-vsctl get-controller %s' % switch ) 27 | p.expect( 'tcp:([\d.:]+)') 28 | actual = p.match.group(1) 29 | expected = cmap[ switch ] 30 | self.assertEqual( actual, expected ) 31 | p.expect( self.prompt ) 32 | p.sendline( 'exit' ) 33 | p.wait() 34 | 35 | def testControllers( self ): 36 | c0 = '127.0.0.1:6633' 37 | c1 = '127.0.0.1:6634' 38 | cmap = { 's1': c0, 's2': c1, 's3': c0 } 39 | self.connectedTest( 'mininet.examples.controllers', cmap ) 40 | 41 | def testControllers2( self ): 42 | c0 = '127.0.0.1:6633' 43 | c1 = '127.0.0.1:6634' 44 | cmap = { 's1': c0, 's2': c1 } 45 | self.connectedTest( 'mininet.examples.controllers2', cmap ) 46 | 47 | if __name__ == '__main__': 48 | unittest.main() 49 | -------------------------------------------------------------------------------- /mininet/examples/test/test_intfoptions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for intfOptions.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | import sys 10 | 11 | class testIntfOptions( unittest.TestCase ): 12 | 13 | def testIntfOptions( self ): 14 | "verify that intf.config is correctly limiting traffic" 15 | p = pexpect.spawn( 'python -m mininet.examples.intfoptions ' ) 16 | tolerance = .2 # plus or minus 20% 17 | opts = [ "Results: \['([\d\.]+) .bits/sec", 18 | "Results: \['10M', '([\d\.]+) .bits/sec", 19 | "h(\d+)->h(\d+): (\d)/(\d)," 20 | "rtt min/avg/max/mdev ([\d\.]+)/([\d\.]+)/([\d\.]+)/([\d\.]+) ms", 21 | pexpect.EOF ] 22 | while True: 23 | index = p.expect( opts, timeout=600 ) 24 | if index == 0: 25 | BW = 5 26 | bw = float( p.match.group( 1 ) ) 27 | self.assertGreaterEqual( bw, BW * ( 1 - tolerance ) ) 28 | self.assertLessEqual( bw, BW * ( 1 + tolerance ) ) 29 | elif index == 1: 30 | BW = 10 31 | measuredBw = float( p.match.group( 1 ) ) 32 | loss = ( measuredBw / BW ) * 100 33 | self.assertGreaterEqual( loss, 50 * ( 1 - tolerance ) ) 34 | self.assertLessEqual( loss, 50 * ( 1 + tolerance ) ) 35 | elif index == 2: 36 | delay = float( p.match.group( 6 ) ) 37 | self.assertGreaterEqual( delay, 15 * ( 1 - tolerance ) ) 38 | self.assertLessEqual( delay, 15 * ( 1 + tolerance ) ) 39 | else: 40 | break 41 | 42 | 43 | if __name__ == '__main__': 44 | unittest.main() 45 | -------------------------------------------------------------------------------- /mininet/examples/hwintf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | This example shows how to add an interface (for example a real 5 | hardware interface) to a network after the network is created. 6 | """ 7 | 8 | import re 9 | import sys 10 | 11 | from mininet.cli import CLI 12 | from mininet.log import setLogLevel, info, error 13 | from mininet.net import Mininet 14 | from mininet.link import Intf 15 | from mininet.topolib import TreeTopo 16 | from mininet.util import quietRun 17 | 18 | def checkIntf( intf ): 19 | "Make sure intf exists and is not configured." 20 | config = quietRun( 'ifconfig %s 2>/dev/null' % intf, shell=True ) 21 | if not config: 22 | error( 'Error:', intf, 'does not exist!\n' ) 23 | exit( 1 ) 24 | ips = re.findall( r'\d+\.\d+\.\d+\.\d+', config ) 25 | if ips: 26 | error( 'Error:', intf, 'has an IP address,' 27 | 'and is probably in use!\n' ) 28 | exit( 1 ) 29 | 30 | if __name__ == '__main__': 31 | setLogLevel( 'info' ) 32 | 33 | # try to get hw intf from the command line; by default, use eth1 34 | intfName = sys.argv[ 1 ] if len( sys.argv ) > 1 else 'eth1' 35 | info( '*** Connecting to hw intf: %s' % intfName ) 36 | 37 | info( '*** Checking', intfName, '\n' ) 38 | checkIntf( intfName ) 39 | 40 | info( '*** Creating network\n' ) 41 | net = Mininet( topo=TreeTopo( depth=1, fanout=2 ) ) 42 | 43 | switch = net.switches[ 0 ] 44 | info( '*** Adding hardware interface', intfName, 'to switch', 45 | switch.name, '\n' ) 46 | _intf = Intf( intfName, node=switch ) 47 | 48 | info( '*** Note: you may need to reconfigure the interfaces for ' 49 | 'the Mininet hosts:\n', net.hosts, '\n' ) 50 | 51 | net.start() 52 | CLI( net ) 53 | net.stop() 54 | -------------------------------------------------------------------------------- /mininet/examples/test/test_vlanhost.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for vlanhost.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | import sys 10 | from mininet.util import quietRun 11 | 12 | class testVLANHost( unittest.TestCase ): 13 | 14 | prompt = 'mininet>' 15 | 16 | @unittest.skipIf( '-quick' in sys.argv, 'long test' ) 17 | def testVLANTopo( self ): 18 | "Test connectivity (or lack thereof) between hosts in VLANTopo" 19 | p = pexpect.spawn( 'python -m mininet.examples.vlanhost' ) 20 | p.expect( self.prompt ) 21 | p.sendline( 'pingall 1' ) #ping timeout=1 22 | p.expect( '(\d+)% dropped', timeout=30 ) # there should be 24 failed pings 23 | percent = int( p.match.group( 1 ) ) if p.match else -1 24 | p.expect( self.prompt ) 25 | p.sendline( 'exit' ) 26 | p.wait() 27 | self.assertEqual( percent, 80 ) 28 | 29 | def testSpecificVLAN( self ): 30 | "Test connectivity between hosts on a specific VLAN" 31 | vlan = 1001 32 | p = pexpect.spawn( 'python -m mininet.examples.vlanhost %d' % vlan ) 33 | p.expect( self.prompt ) 34 | 35 | p.sendline( 'h1 ping -c 1 h2' ) 36 | p.expect ( '(\d+)% packet loss' ) 37 | percent = int( p.match.group( 1 ) ) if p.match else -1 38 | p.expect( self.prompt ) 39 | 40 | p.sendline( 'h1 ifconfig' ) 41 | i = p.expect( ['h1-eth0.%d' % vlan, pexpect.TIMEOUT ], timeout=2 ) 42 | p.expect( self.prompt ) 43 | 44 | p.sendline( 'exit' ) 45 | p.wait() 46 | self.assertEqual( percent, 0 ) # no packet loss on ping 47 | self.assertEqual( i, 0 ) # check vlan intf is present 48 | 49 | if __name__ == '__main__': 50 | unittest.main() 51 | -------------------------------------------------------------------------------- /mininet/examples/test/test_linuxrouter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for linuxrouter.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | from mininet.util import quietRun 10 | 11 | class testLinuxRouter( unittest.TestCase ): 12 | 13 | prompt = 'mininet>' 14 | 15 | def testPingall( self ): 16 | "Test connectivity between hosts" 17 | p = pexpect.spawn( 'python -m mininet.examples.linuxrouter' ) 18 | p.expect( self.prompt ) 19 | p.sendline( 'pingall' ) 20 | p.expect ( '(\d+)% dropped' ) 21 | percent = int( p.match.group( 1 ) ) if p.match else -1 22 | p.expect( self.prompt ) 23 | p.sendline( 'exit' ) 24 | p.wait() 25 | self.assertEqual( percent, 0 ) 26 | 27 | def testRouterPing( self ): 28 | "Test connectivity from h1 to router" 29 | p = pexpect.spawn( 'python -m mininet.examples.linuxrouter' ) 30 | p.expect( self.prompt ) 31 | p.sendline( 'h1 ping -c 1 r0' ) 32 | p.expect ( '(\d+)% packet loss' ) 33 | percent = int( p.match.group( 1 ) ) if p.match else -1 34 | p.expect( self.prompt ) 35 | p.sendline( 'exit' ) 36 | p.wait() 37 | self.assertEqual( percent, 0 ) 38 | 39 | def testTTL( self ): 40 | "Verify that the TTL is decremented" 41 | p = pexpect.spawn( 'python -m mininet.examples.linuxrouter' ) 42 | p.expect( self.prompt ) 43 | p.sendline( 'h1 ping -c 1 h2' ) 44 | p.expect ( 'ttl=(\d+)' ) 45 | ttl = int( p.match.group( 1 ) ) if p.match else -1 46 | p.expect( self.prompt ) 47 | p.sendline( 'exit' ) 48 | p.wait() 49 | self.assertEqual( ttl, 63 ) # 64 - 1 50 | 51 | if __name__ == '__main__': 52 | unittest.main() 53 | -------------------------------------------------------------------------------- /mininet/LICENSE: -------------------------------------------------------------------------------- 1 | Mininet 2.3.0d6 License 2 | 3 | Copyright (c) 2013-2019 Open Networking Laboratory 4 | Copyright (c) 2009-2012 Bob Lantz and The Board of Trustees of 5 | The Leland Stanford Junior University 6 | 7 | Original authors: Bob Lantz and Brandon Heller 8 | 9 | We are making Mininet available for public use and benefit with the 10 | expectation that others will use, modify and enhance the Software and 11 | contribute those enhancements back to the community. However, since we 12 | would like to make the Software available for broadest use, with as few 13 | restrictions as possible permission is hereby granted, free of charge, to 14 | any person obtaining a copy of this Software to deal in the Software 15 | under the copyrights without restriction, including without limitation 16 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 | and/or sell copies of the Software, and to permit persons to whom the 18 | Software is furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included 21 | in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 24 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 26 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 27 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 28 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 29 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | The name and trademarks of copyright holder(s) may NOT be used in 32 | advertising or publicity pertaining to the Software or any derivatives 33 | without specific, written prior permission. 34 | -------------------------------------------------------------------------------- /mininet/examples/test/test_multilink.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ''' 4 | Test for multiple links between nodes 5 | validates mininet interfaces against systems interfaces 6 | ''' 7 | 8 | import unittest 9 | from mininet.util import pexpect 10 | 11 | class testMultiLink( unittest.TestCase ): 12 | 13 | prompt = 'mininet>' 14 | 15 | def testMultiLink(self): 16 | p = pexpect.spawn( 'python -m mininet.examples.multilink' ) 17 | p.expect( self.prompt ) 18 | p.sendline( 'intfs' ) 19 | p.expect( 's(\d): lo' ) 20 | intfsOutput = p.before 21 | # parse interfaces from mininet intfs, and store them in a list 22 | hostToIntfs = intfsOutput.split( '\r\n' )[ 1:3 ] 23 | intfList = [] 24 | for hostToIntf in hostToIntfs: 25 | intfList += [ intf for intf in 26 | hostToIntf.split()[1].split(',') ] 27 | 28 | # get interfaces from system by running ifconfig on every host 29 | sysIntfList = [] 30 | opts = [ 'h(\d)-eth(\d)', self.prompt ] 31 | p.expect( self.prompt ) 32 | 33 | p.sendline( 'h1 ifconfig' ) 34 | while True: 35 | p.expect( opts ) 36 | if p.after == self.prompt: 37 | break 38 | sysIntfList.append( p.after ) 39 | 40 | p.sendline( 'h2 ifconfig' ) 41 | while True: 42 | p.expect( opts ) 43 | if p.after == self.prompt: 44 | break 45 | sysIntfList.append( p.after ) 46 | 47 | failMsg = ( 'The systems interfaces and mininet interfaces\n' 48 | 'are not the same' ) 49 | 50 | self.assertEqual( sysIntfList, intfList, msg=failMsg ) 51 | p.sendline( 'exit' ) 52 | p.wait() 53 | 54 | if __name__ == '__main__': 55 | unittest.main() 56 | -------------------------------------------------------------------------------- /mininet/util/vm/install-mininet-vm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script is intended to install Mininet into 4 | # a brand-new Ubuntu virtual machine, 5 | # to create a fully usable "tutorial" VM. 6 | # 7 | # optional argument: Mininet branch to install 8 | set -e 9 | echo "$(whoami) ALL=(ALL) NOPASSWD:ALL" | sudo tee -a /etc/sudoers > /dev/null 10 | sudo sed -i -e 's/Default/#Default/' /etc/sudoers 11 | echo mininet-vm | sudo tee /etc/hostname > /dev/null 12 | sudo sed -i -e 's/ubuntu/mininet-vm/g' /etc/hosts 13 | sudo hostname `cat /etc/hostname` 14 | sudo sed -i -e 's/splash//' /etc/default/grub 15 | sudo sed -i -e 's/quiet/text/' /etc/default/grub 16 | sudo update-grub 17 | # Update from official archive 18 | sudo apt-get update 19 | # 12.10 and earlier 20 | #sudo sed -i -e 's/us.archive.ubuntu.com/mirrors.kernel.org/' \ 21 | # /etc/apt/sources.list 22 | # 13.04 and later 23 | #sudo sed -i -e 's/\/archive.ubuntu.com/\/mirrors.kernel.org/' \ 24 | # /etc/apt/sources.list 25 | # Clean up vmware easy install junk if present 26 | if [ -e /etc/issue.backup ]; then 27 | sudo mv /etc/issue.backup /etc/issue 28 | fi 29 | if [ -e /etc/rc.local.backup ]; then 30 | sudo mv /etc/rc.local.backup /etc/rc.local 31 | fi 32 | # Fetch Mininet 33 | sudo apt-get -y install git-core openssh-server 34 | git clone git://github.com/mininet/mininet 35 | # Optionally check out branch 36 | if [ "$1" != "" ]; then 37 | pushd mininet 38 | #git checkout -b $1 $1 39 | # TODO branch will in detached HEAD state if it is not master 40 | git checkout $1 41 | popd 42 | fi 43 | # Install Mininet 44 | time mininet/util/install.sh 45 | # Finalize VM 46 | time mininet/util/install.sh -tcd 47 | # Ignoring this since NOX classic is deprecated 48 | #if ! grep NOX_CORE_DIR .bashrc; then 49 | # echo "export NOX_CORE_DIR=~/noxcore/build/src/" >> .bashrc 50 | #fi 51 | echo "Done preparing Mininet VM." 52 | -------------------------------------------------------------------------------- /mininet/mininet/provision/playbooks/install-lxd.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # 3 | - hosts : master 4 | remote_user: root 5 | tasks : 6 | 7 | - name : Download switch 8 | get_url: 9 | url : http://www-sop.inria.fr/members/Damien.Saucez/images/switch.tar.gz 10 | dest: ~/switch.tar.gz 11 | mode: 0666 12 | 13 | - name : Download ubuntu18:04 14 | get_url: 15 | url : http://www-sop.inria.fr/members/Damien.Saucez/images/ubuntu.tar.gz 16 | dest: ~/ubuntu.tar.gz 17 | mode: 0666 18 | 19 | # - name : Download Debian:10 20 | # get_url: 21 | # url : http://www-sop.inria.fr/members/Damien.Saucez/images/debian.tar.gz 22 | # dest: ~/debian.tar.gz 23 | # mode: 0666 24 | 25 | - hosts : all 26 | remote_user: root 27 | tasks : 28 | - name: install python3-pip 29 | apt : 30 | update_cache: true 31 | name : python3-pip 32 | 33 | # - name: install python-pip 34 | # apt : 35 | # name : python-pip 36 | 37 | - name: install htop 38 | apt : 39 | name: htop 40 | 41 | - name: install ethtool 42 | apt : 43 | name: ethtool 44 | 45 | - name: install bridge-utils 46 | apt : 47 | name: bridge-utils 48 | 49 | - name: install net-tools 50 | apt : 51 | name: net-tools 52 | 53 | - name: install pexpect 54 | pip : 55 | name: pexpect 56 | 57 | - name: install ovs 58 | apt : 59 | name: openvswitch-switch 60 | 61 | # - name: install btrfs-tools 62 | # apt: 63 | # name: btrfs-tools 64 | 65 | - name: install lxd 66 | apt: 67 | name: lxd 68 | 69 | - name: install lxd-client 70 | apt : 71 | name: lxd-client 72 | 73 | - name: install ryu 74 | apt: 75 | name: python3-ryu 76 | -------------------------------------------------------------------------------- /mininet/examples/test/test_linearbandwidth.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for linearbandwidth.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | import sys 10 | 11 | class testLinearBandwidth( unittest.TestCase ): 12 | 13 | @unittest.skipIf( '-quick' in sys.argv, 'long test' ) 14 | def testLinearBandwidth( self ): 15 | "Verify that bandwidth is monotonically decreasing as # of hops increases" 16 | p = pexpect.spawn( 'python -m mininet.examples.linearbandwidth' ) 17 | count = 0 18 | opts = [ '\*\*\* Linear network results', 19 | '(\d+)\s+([\d\.]+) (.bits)', 20 | pexpect.EOF ] 21 | while True: 22 | index = p.expect( opts, timeout=600 ) 23 | if index == 0: 24 | count += 1 25 | elif index == 1: 26 | n = int( p.match.group( 1 ) ) 27 | bw = float( p.match.group( 2 ) ) 28 | unit = p.match.group( 3 ) 29 | if unit[ 0 ] == 'K': 30 | bw *= 10 ** 3 31 | elif unit[ 0 ] == 'M': 32 | bw *= 10 ** 6 33 | elif unit[ 0 ] == 'G': 34 | bw *= 10 ** 9 35 | # check that we have a previous result to compare to 36 | if n != 1: 37 | info = ( 'bw: %.2e bits/s across %d switches, ' 38 | 'previous: %.2e bits/s across %d switches' % 39 | ( bw, n, previous_bw, previous_n ) ) 40 | self.assertTrue( bw < previous_bw, info ) 41 | previous_bw, previous_n = bw, n 42 | else: 43 | break 44 | 45 | # verify that we received results from at least one switch 46 | self.assertTrue( count > 0 ) 47 | 48 | if __name__ == '__main__': 49 | unittest.main() 50 | -------------------------------------------------------------------------------- /mininet/examples/controllers2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | This example creates a multi-controller network from semi-scratch by 5 | using the net.add*() API and manually starting the switches and controllers. 6 | 7 | This is the "mid-level" API, which is an alternative to the "high-level" 8 | Topo() API which supports parametrized topology classes. 9 | 10 | Note that one could also create a custom switch class and pass it into 11 | the Mininet() constructor. 12 | """ 13 | 14 | 15 | from mininet.net import Mininet 16 | from mininet.node import Controller, OVSSwitch 17 | from mininet.cli import CLI 18 | from mininet.log import setLogLevel, info 19 | 20 | def multiControllerNet(): 21 | "Create a network from semi-scratch with multiple controllers." 22 | 23 | net = Mininet( controller=Controller, switch=OVSSwitch ) 24 | 25 | info( "*** Creating (reference) controllers\n" ) 26 | c1 = net.addController( 'c1', port=6633 ) 27 | c2 = net.addController( 'c2', port=6634 ) 28 | 29 | info( "*** Creating switches\n" ) 30 | s1 = net.addSwitch( 's1' ) 31 | s2 = net.addSwitch( 's2' ) 32 | 33 | info( "*** Creating hosts\n" ) 34 | hosts1 = [ net.addHost( 'h%d' % n ) for n in ( 3, 4 ) ] 35 | hosts2 = [ net.addHost( 'h%d' % n ) for n in ( 5, 6 ) ] 36 | 37 | info( "*** Creating links\n" ) 38 | for h in hosts1: 39 | net.addLink( s1, h ) 40 | for h in hosts2: 41 | net.addLink( s2, h ) 42 | net.addLink( s1, s2 ) 43 | 44 | info( "*** Starting network\n" ) 45 | net.build() 46 | c1.start() 47 | c2.start() 48 | s1.start( [ c1 ] ) 49 | s2.start( [ c2 ] ) 50 | 51 | info( "*** Testing network\n" ) 52 | net.pingAll() 53 | 54 | info( "*** Running CLI\n" ) 55 | CLI( net ) 56 | 57 | info( "*** Stopping network\n" ) 58 | net.stop() 59 | 60 | if __name__ == '__main__': 61 | setLogLevel( 'info' ) # for CLI output 62 | multiControllerNet() 63 | -------------------------------------------------------------------------------- /mininet/examples/test/test_numberedports.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for numberedports.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | from collections import defaultdict 10 | from mininet.node import OVSSwitch 11 | 12 | class testNumberedports( unittest.TestCase ): 13 | 14 | @unittest.skipIf( OVSSwitch.setup() or OVSSwitch.isOldOVS(), "old version of OVS" ) 15 | def testConsistency( self ): 16 | """verify consistency between mininet and ovs ports""" 17 | p = pexpect.spawn( 'python -m mininet.examples.numberedports' ) 18 | opts = [ 'Validating that s1-eth\d is actually on port \d ... Validated.', 19 | 'Validating that s1-eth\d is actually on port \d ... WARNING', 20 | pexpect.EOF ] 21 | correct_ports = True 22 | count = 0 23 | while True: 24 | index = p.expect( opts ) 25 | if index == 0: 26 | count += 1 27 | elif index == 1: 28 | correct_ports = False 29 | elif index == 2: 30 | self.assertNotEqual( 0, count ) 31 | break 32 | self.assertTrue( correct_ports ) 33 | 34 | def testNumbering( self ): 35 | """verify that all of the port numbers are printed correctly and consistent with their interface""" 36 | p = pexpect.spawn( 'python -m mininet.examples.numberedports' ) 37 | opts = [ 's1-eth(\d+) : (\d+)', 38 | pexpect.EOF ] 39 | count_intfs = 0 40 | while True: 41 | index = p.expect( opts ) 42 | if index == 0: 43 | count_intfs += 1 44 | intfport = p.match.group( 1 ) 45 | ofport = p.match.group( 2 ) 46 | self.assertEqual( intfport, ofport ) 47 | elif index == 1: 48 | break 49 | self.assertNotEqual( 0, count_intfs ) 50 | 51 | if __name__ == '__main__': 52 | unittest.main() 53 | -------------------------------------------------------------------------------- /mininet/mininet/provision/playbooks/install-lxd-debian-10.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # 3 | - hosts : master 4 | remote_user: root 5 | tasks : 6 | 7 | - name : Download switch 8 | get_url: 9 | url : http://www-sop.inria.fr/members/Damien.Saucez/images/switch.tar.gz 10 | dest: ~/switch.tar.gz 11 | mode: 0666 12 | 13 | - name : Download ubuntu18:04 14 | get_url: 15 | url : http://www-sop.inria.fr/members/Damien.Saucez/images/ubuntu.tar.gz 16 | dest: ~/ubuntu.tar.gz 17 | mode: 0666 18 | 19 | # - name : Download Debian:10 20 | # get_url: 21 | # url : http://www-sop.inria.fr/members/Damien.Saucez/images/debian.tar.gz 22 | # dest: ~/debian.tar.gz 23 | # mode: 0666 24 | 25 | - hosts : all 26 | remote_user: root 27 | tasks : 28 | - name: install python3-pip 29 | apt : 30 | update_cache: true 31 | name : python3-pip 32 | 33 | - name: install python-pip 34 | apt : 35 | name : python-pip 36 | 37 | - name: install htop 38 | apt : 39 | name: htop 40 | 41 | - name: install ethtool 42 | apt : 43 | name: ethtool 44 | 45 | - name: install bridge-utils 46 | apt : 47 | name: bridge-utils 48 | 49 | - name: install net-tools 50 | apt : 51 | name: net-tools 52 | 53 | - name: install pexpect 54 | pip : 55 | name: pexpect 56 | 57 | - name: install ovs 58 | apt : 59 | name: openvswitch-switch 60 | 61 | - name: install btrfs-tools 62 | apt: 63 | name: btrfs-tools 64 | 65 | - name: snapd 66 | apt: 67 | name: snapd 68 | 69 | - name: lxd 70 | raw: snap install lxd --channel=3.0/stable 71 | 72 | - name: add LXC to the path 73 | raw: ln -s /snap/bin/lxc /sbin 74 | 75 | - name: add LXD to the path 76 | raw: ln -s /snap/bin/lxd /sbin 77 | 78 | - name: install ryu 79 | apt: 80 | name: python3-ryu 81 | -------------------------------------------------------------------------------- /mininet/debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0 2 | Upstream-Name: mininet 3 | Source: https://github.com/mininet/mininet 4 | 5 | Files: * 6 | Copyright: 2012-2013 Open Networking Laboratory, 7 | 2009-2012 Bob Lantz, 8 | 2009-2012 The Board of Trustees of the Leland Stanford Junior 9 | University 10 | License: 11 | Original authors: Bob Lantz and Brandon Heller 12 | . 13 | We are making Mininet available for public use and benefit with the 14 | expectation that others will use, modify and enhance the Software and 15 | contribute those enhancements back to the community. However, since we 16 | would like to make the Software available for broadest use, with as few 17 | restrictions as possible permission is hereby granted, free of charge, to 18 | any person obtaining a copy of this Software to deal in the Software 19 | under the copyrights without restriction, including without limitation 20 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 21 | and/or sell copies of the Software, and to permit persons to whom the 22 | Software is furnished to do so, subject to the following conditions: 23 | . 24 | The above copyright notice and this permission notice shall be included 25 | in all copies or substantial portions of the Software. 26 | . 27 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 28 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 29 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 30 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 31 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 32 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 33 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 34 | . 35 | The name and trademarks of copyright holder(s) may NOT be used in 36 | advertising or publicity pertaining to the Software or any derivatives 37 | without specific, written prior permission. 38 | -------------------------------------------------------------------------------- /mininet/examples/test/test_natnet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for natnet.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | from mininet.util import quietRun 10 | 11 | class testNATNet( unittest.TestCase ): 12 | 13 | prompt = 'mininet>' 14 | 15 | def setUp( self ): 16 | self.net = pexpect.spawn( 'python -m mininet.examples.natnet' ) 17 | self.net.expect( self.prompt ) 18 | 19 | def testPublicPing( self ): 20 | "Attempt to ping the public server (h0) from h1 and h2" 21 | self.net.sendline( 'h1 ping -c 1 h0' ) 22 | self.net.expect ( '(\d+)% packet loss' ) 23 | percent = int( self.net.match.group( 1 ) ) if self.net.match else -1 24 | self.assertEqual( percent, 0 ) 25 | self.net.expect( self.prompt ) 26 | 27 | self.net.sendline( 'h2 ping -c 1 h0' ) 28 | self.net.expect ( '(\d+)% packet loss' ) 29 | percent = int( self.net.match.group( 1 ) ) if self.net.match else -1 30 | self.assertEqual( percent, 0 ) 31 | self.net.expect( self.prompt ) 32 | 33 | def testPrivatePing( self ): 34 | "Attempt to ping h1 and h2 from public server" 35 | self.net.sendline( 'h0 ping -c 1 -t 1 h1' ) 36 | result = self.net.expect ( [ 'unreachable', 'loss' ] ) 37 | self.assertEqual( result, 0 ) 38 | self.net.expect( self.prompt ) 39 | 40 | self.net.sendline( 'h0 ping -c 1 -t 1 h2' ) 41 | result = self.net.expect ( [ 'unreachable', 'loss' ] ) 42 | self.assertEqual( result, 0 ) 43 | self.net.expect( self.prompt ) 44 | 45 | def testPrivateToPrivatePing( self ): 46 | "Attempt to ping from NAT'ed host h1 to NAT'ed host h2" 47 | self.net.sendline( 'h1 ping -c 1 -t 1 h2' ) 48 | result = self.net.expect ( [ '[Uu]nreachable', 'loss' ] ) 49 | self.assertEqual( result, 0 ) 50 | self.net.expect( self.prompt ) 51 | 52 | def tearDown( self ): 53 | self.net.sendline( 'exit' ) 54 | self.net.wait() 55 | 56 | if __name__ == '__main__': 57 | unittest.main() 58 | -------------------------------------------------------------------------------- /mininet/examples/test/test_multiping.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for multiping.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | from collections import defaultdict 10 | 11 | class testMultiPing( unittest.TestCase ): 12 | 13 | def testMultiPing( self ): 14 | """Verify that each target is pinged at least once, and 15 | that pings to 'real' targets are successful and unknown targets fail""" 16 | p = pexpect.spawn( 'python -m mininet.examples.multiping' ) 17 | opts = [ "Host (h\d+) \(([\d.]+)\) will be pinging ips: ([\d\. ]+)", 18 | "(h\d+): ([\d.]+) -> ([\d.]+) \d packets transmitted, (\d) received", 19 | pexpect.EOF ] 20 | pings = defaultdict( list ) 21 | while True: 22 | index = p.expect( opts ) 23 | if index == 0: 24 | name = p.match.group(1) 25 | ip = p.match.group(2) 26 | targets = p.match.group(3).split() 27 | pings[ name ] += targets 28 | elif index == 1: 29 | name = p.match.group(1) 30 | ip = p.match.group(2) 31 | target = p.match.group(3) 32 | received = int( p.match.group(4) ) 33 | if target == '10.0.0.200': 34 | self.assertEqual( received, 0, p.match.group(0) + '\n' + 35 | target + ' received %d != 0 packets' % received ) 36 | else: 37 | self.assertEqual( received, 1, p.match.group(0) + '\n' + 38 | target + ' received %d != 1 packets' % received ) 39 | try: 40 | pings[ name ].remove( target ) 41 | except: 42 | pass 43 | else: 44 | break 45 | self.assertTrue( len( pings ) > 0, 'too few pings' ) 46 | for t in pings.values(): 47 | self.assertEqual( len( t ), 0, 'missed ping target(s): %s' % t ) 48 | 49 | if __name__ == '__main__': 50 | unittest.main() 51 | -------------------------------------------------------------------------------- /mininet/examples/test/test_sshd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for sshd.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | from mininet.clean import sh 10 | 11 | class testSSHD( unittest.TestCase ): 12 | 13 | opts = [ '\(yes/no\)\?', 'refused', 'Welcome|\$|#', pexpect.EOF, pexpect.TIMEOUT ] 14 | 15 | def connected( self, ip ): 16 | "Log into ssh server, check banner, then exit" 17 | # Note: this test will fail if "Welcome" is not in the sshd banner 18 | # and '#'' or '$'' are not in the prompt 19 | p = pexpect.spawn( 'ssh -i /tmp/ssh/test_rsa %s' % ip, timeout=10 ) 20 | while True: 21 | index = p.expect( self.opts ) 22 | if index == 0: 23 | print( p.match.group(0) ) 24 | p.sendline( 'yes' ) 25 | elif index == 1: 26 | return False 27 | elif index == 2: 28 | p.sendline( 'exit' ) 29 | p.wait() 30 | return True 31 | else: 32 | return False 33 | 34 | def setUp( self ): 35 | # create public key pair for testing 36 | sh( 'rm -rf /tmp/ssh' ) 37 | sh( 'mkdir /tmp/ssh' ) 38 | sh( "ssh-keygen -t rsa -P '' -f /tmp/ssh/test_rsa" ) 39 | sh( 'cat /tmp/ssh/test_rsa.pub >> /tmp/ssh/authorized_keys' ) 40 | cmd = ( 'python -m mininet.examples.sshd -D ' 41 | '-o AuthorizedKeysFile=/tmp/ssh/authorized_keys ' 42 | '-o StrictModes=no -o UseDNS=no -u0' ) 43 | # run example with custom sshd args 44 | self.net = pexpect.spawn( cmd ) 45 | self.net.expect( 'mininet>' ) 46 | 47 | def testSSH( self ): 48 | "Verify that we can ssh into all hosts (h1 to h4)" 49 | for h in range( 1, 5 ): 50 | self.assertTrue( self.connected( '10.0.0.%d' % h ) ) 51 | 52 | def tearDown( self ): 53 | self.net.sendline( 'exit' ) 54 | self.net.wait() 55 | # remove public key pair 56 | sh( 'rm -rf /tmp/ssh' ) 57 | 58 | if __name__ == '__main__': 59 | unittest.main() 60 | 61 | -------------------------------------------------------------------------------- /mininet/examples/natnet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | natnet.py: Example network with NATs 5 | 6 | 7 | h0 8 | | 9 | s0 10 | | 11 | ---------------- 12 | | | 13 | nat1 nat2 14 | | | 15 | s1 s2 16 | | | 17 | h1 h2 18 | 19 | """ 20 | 21 | from mininet.topo import Topo 22 | from mininet.net import Mininet 23 | from mininet.nodelib import NAT 24 | from mininet.log import setLogLevel 25 | from mininet.cli import CLI 26 | from mininet.util import irange 27 | 28 | class InternetTopo(Topo): 29 | "Single switch connected to n hosts." 30 | def build(self, n=2, **_kwargs ): 31 | # set up inet switch 32 | inetSwitch = self.addSwitch('s0') 33 | # add inet host 34 | inetHost = self.addHost('h0') 35 | self.addLink(inetSwitch, inetHost) 36 | 37 | # add local nets 38 | for i in irange(1, n): 39 | inetIntf = 'nat%d-eth0' % i 40 | localIntf = 'nat%d-eth1' % i 41 | localIP = '192.168.%d.1' % i 42 | localSubnet = '192.168.%d.0/24' % i 43 | natParams = { 'ip' : '%s/24' % localIP } 44 | # add NAT to topology 45 | nat = self.addNode('nat%d' % i, cls=NAT, subnet=localSubnet, 46 | inetIntf=inetIntf, localIntf=localIntf) 47 | switch = self.addSwitch('s%d' % i) 48 | # connect NAT to inet and local switches 49 | self.addLink(nat, inetSwitch, intfName1=inetIntf) 50 | self.addLink(nat, switch, intfName1=localIntf, params1=natParams) 51 | # add host and connect to local switch 52 | host = self.addHost('h%d' % i, 53 | ip='192.168.%d.100/24' % i, 54 | defaultRoute='via %s' % localIP) 55 | self.addLink(host, switch) 56 | 57 | def run(): 58 | "Create network and run the CLI" 59 | topo = InternetTopo() 60 | net = Mininet(topo=topo) 61 | net.start() 62 | CLI(net) 63 | net.stop() 64 | 65 | if __name__ == '__main__': 66 | setLogLevel('info') 67 | run() 68 | -------------------------------------------------------------------------------- /mininet/examples/simpleperf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | Simple example of setting network and CPU parameters 5 | 6 | NOTE: link params limit BW, add latency, and loss. 7 | There is a high chance that pings WILL fail and that 8 | iperf will hang indefinitely if the TCP handshake fails 9 | to complete. 10 | """ 11 | 12 | 13 | from mininet.topo import Topo 14 | from mininet.net import Mininet 15 | from mininet.node import CPULimitedHost 16 | from mininet.link import TCLink 17 | from mininet.util import dumpNodeConnections 18 | from mininet.log import setLogLevel, info 19 | 20 | from sys import argv 21 | 22 | # It would be nice if we didn't have to do this: 23 | # pylint: disable=arguments-differ 24 | 25 | class SingleSwitchTopo( Topo ): 26 | "Single switch connected to n hosts." 27 | def build( self, n=2, lossy=True ): 28 | switch = self.addSwitch('s1') 29 | for h in range(n): 30 | # Each host gets 50%/n of system CPU 31 | host = self.addHost('h%s' % (h + 1), 32 | cpu=.5 / n) 33 | if lossy: 34 | # 10 Mbps, 5ms delay, 10% packet loss 35 | self.addLink(host, switch, 36 | bw=10, delay='5ms', loss=10, use_htb=True) 37 | else: 38 | # 10 Mbps, 5ms delay, no packet loss 39 | self.addLink(host, switch, 40 | bw=10, delay='5ms', loss=0, use_htb=True) 41 | 42 | 43 | def perfTest( lossy=True ): 44 | "Create network and run simple performance test" 45 | topo = SingleSwitchTopo( n=4, lossy=lossy ) 46 | net = Mininet( topo=topo, 47 | host=CPULimitedHost, link=TCLink, 48 | autoStaticArp=True ) 49 | net.start() 50 | info( "Dumping host connections\n" ) 51 | dumpNodeConnections(net.hosts) 52 | info( "Testing bandwidth between h1 and h4\n" ) 53 | h1, h4 = net.getNodeByName('h1', 'h4') 54 | net.iperf( ( h1, h4 ), l4Type='UDP' ) 55 | net.stop() 56 | 57 | if __name__ == '__main__': 58 | setLogLevel( 'info' ) 59 | # Prevent test_simpleperf from failing due to packet loss 60 | perfTest( lossy=( 'testmode' not in argv ) ) 61 | -------------------------------------------------------------------------------- /mininet/examples/test/test_hwintf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for hwintf.py 5 | """ 6 | 7 | import unittest 8 | import re 9 | 10 | from mininet.util import pexpect 11 | 12 | from mininet.log import setLogLevel 13 | from mininet.node import Node 14 | from mininet.link import Link 15 | 16 | 17 | class testHwintf( unittest.TestCase ): 18 | 19 | prompt = 'mininet>' 20 | 21 | def setUp( self ): 22 | self.h3 = Node( 't0', ip='10.0.0.3/8' ) 23 | self.n0 = Node( 't1', inNamespace=False ) 24 | Link( self.h3, self.n0 ) 25 | self.h3.configDefault() 26 | 27 | def testLocalPing( self ): 28 | "Verify connectivity between virtual hosts using pingall" 29 | p = pexpect.spawn( 'python -m mininet.examples.hwintf %s' % self.n0.intf() ) 30 | p.expect( self.prompt ) 31 | p.sendline( 'pingall' ) 32 | p.expect ( '(\d+)% dropped' ) 33 | percent = int( p.match.group( 1 ) ) if p.match else -1 34 | self.assertEqual( percent, 0 ) 35 | p.expect( self.prompt ) 36 | p.sendline( 'exit' ) 37 | p.wait() 38 | 39 | def testExternalPing( self ): 40 | "Verify connnectivity between virtual host and virtual-physical 'external' host " 41 | p = pexpect.spawn( 'python -m mininet.examples.hwintf %s' % self.n0.intf() ) 42 | p.expect( self.prompt ) 43 | # test ping external to internal 44 | expectStr = '(\d+) packets transmitted, (\d+) received' 45 | m = re.search( expectStr, self.h3.cmd( 'ping -v -c 1 10.0.0.1' ) ) 46 | tx = m.group( 1 ) 47 | rx = m.group( 2 ) 48 | self.assertEqual( tx, rx ) 49 | # test ping internal to external 50 | p.sendline( 'h1 ping -c 1 10.0.0.3') 51 | p.expect( expectStr ) 52 | tx = p.match.group( 1 ) 53 | rx = p.match.group( 2 ) 54 | self.assertEqual( tx, rx ) 55 | p.expect( self.prompt ) 56 | p.sendline( 'exit' ) 57 | p.wait() 58 | 59 | def tearDown( self ): 60 | self.h3.stop( deleteIntfs=True ) 61 | self.n0.stop( deleteIntfs=True ) 62 | 63 | if __name__ == '__main__': 64 | setLogLevel( 'warning' ) 65 | unittest.main() 66 | -------------------------------------------------------------------------------- /mininet/mininet/provision/playbooks/install-lxd-snap.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # 3 | - hosts : master 4 | remote_user: root 5 | tasks : 6 | 7 | - name : Download switch 8 | get_url: 9 | url : http://www-sop.inria.fr/members/Damien.Saucez/images/switch.tar.gz 10 | dest: ~/switch.tar.gz 11 | mode: 0666 12 | 13 | - name : Download ubuntu18:04 14 | get_url: 15 | url : http://www-sop.inria.fr/members/Damien.Saucez/images/ubuntu.tar.gz 16 | dest: ~/ubuntu.tar.gz 17 | mode: 0666 18 | 19 | # - name : Download Debian:10 20 | # get_url: 21 | # url : http://www-sop.inria.fr/members/Damien.Saucez/images/debian.tar.gz 22 | # dest: ~/debian.tar.gz 23 | # mode: 0666 24 | 25 | - hosts : all 26 | remote_user: root 27 | tasks : 28 | - name: install python3-pip 29 | apt : 30 | update_cache: true 31 | name : python3-pip 32 | 33 | - name: install python-pip 34 | apt : 35 | name : python-pip 36 | 37 | - name: install htop 38 | apt : 39 | name: htop 40 | 41 | - name: install ethtool 42 | apt : 43 | name: ethtool 44 | 45 | - name: install bridge-utils 46 | apt : 47 | name: bridge-utils 48 | 49 | - name: install net-tools 50 | apt : 51 | name: net-tools 52 | 53 | - name: install pexpect 54 | pip : 55 | name: pexpect 56 | 57 | - name: install ovs 58 | apt : 59 | name: openvswitch-switch 60 | 61 | - name: install btrfs-tools 62 | apt: 63 | name: btrfs-tools 64 | 65 | - name: remove lxd 66 | apt: 67 | name: lxd 68 | state: absent 69 | 70 | - name: snapd 71 | apt: 72 | name: snapd 73 | 74 | - name: snap core 75 | snap: 76 | name: core 77 | 78 | - name: lxd 79 | snap: 80 | name: lxd 81 | channel: 3.0/stable 82 | 83 | - name: add LXC to the path 84 | raw: ln -s /snap/bin/lxc /sbin 85 | 86 | - name: add LXD to the path 87 | raw: ln -s /snap/bin/lxd /sbin 88 | 89 | - name: install ryu 90 | apt: 91 | name: python3-ryu 92 | -------------------------------------------------------------------------------- /mininet/util/kbuild/kbuild: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script to build new Debian kernel packages for 2.6.33.1 4 | # 5 | # Caveats: 6 | # 7 | # Since kernel-package in debian-stable doesn't work with 8 | # 2.6.33.1, we attempt to patch it in place. This may not be the 9 | # right thing to do. A possibly better alternative is to install 10 | # a later version of kernel-package, although that could potentially 11 | # cause problems with upgrades, etc.. 12 | # 13 | # The patch to tun.c is a workaround rather than a real fix. 14 | # 15 | # Building a full Debian kernel package with all drivers takes a long 16 | # time, 60-80 minutes on my laptop. 17 | # 18 | # Re-running a make-kpkg may not work without running 'make-kpkg clean' 19 | 20 | # Season to taste 21 | # export PATH=/usr/lib/ccache:$PATH 22 | export CONCURRENCY_LEVEL=3 23 | 24 | debversion=2.6.26-2-686-bigmem 25 | 26 | image=linux-image-$debversion 27 | 28 | echo "*** Installing $image" 29 | sudo aptitude install $image 30 | 31 | newversion=2.6.33.1 32 | archive=linux-$newversion.tar.bz2 33 | location=http://www.kernel.org/pub/linux/kernel/v2.6 34 | 35 | echo "*** Fetching $location/$archive" 36 | wget -c $location/$archive 37 | 38 | tree=linux-$newversion 39 | if [ -e $tree ]; then 40 | echo "*** $tree already exists" 41 | else 42 | echo "*** Extracting $archive" 43 | tar xjf $archive 44 | fi 45 | 46 | echo "*** Patching tun driver" 47 | patch $tree/drivers/net/tun.c < tun.patch 48 | 49 | echo "*** Patching debian build script" 50 | sudo patch /usr/share/kernel-package/ruleset/misc/version_vars.mk < version_vars.patch 51 | 52 | config=/boot/config-$debversion 53 | echo "*** Copying $config to $tree/.config" 54 | cp $config $tree/.config 55 | 56 | echo "*** Updating config" 57 | cd $tree 58 | yes '' | make oldconfig 1> /dev/null 59 | sed 's/# CONFIG_NET_NS is not set/CONFIG_NET_NS=y/' .config > .config-new 60 | mv .config-new .config 61 | echo "*** Result: " `grep CONFIG_NET_NS .config` 62 | 63 | echo "*** Building kernel" 64 | time fakeroot make-kpkg --initrd --append-to-version=-mininet kernel_image kernel_headers 65 | 66 | cd .. 67 | echo "*** Done - package should be in current directory" 68 | ls *$newversion*.deb 69 | 70 | echo "To install:" 71 | echo "# dpkg -i " *$newversion*.deb 72 | -------------------------------------------------------------------------------- /mininet/mininet/provision/playbooks/install-g5k-lxd.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts : master 4 | remote_user: root 5 | tasks : 6 | 7 | 8 | - name : Download switch 9 | get_url: 10 | url : http://www-sop.inria.fr/members/Damien.Saucez/images/switch.tar.gz 11 | dest: ~/switch.tar.gz 12 | mode: 0666 13 | 14 | - name : Download ubuntu18:04 15 | get_url: 16 | url : http://www-sop.inria.fr/members/Damien.Saucez/images/ubuntu.tar.gz 17 | dest: ~/ubuntu.tar.gz 18 | mode: 0666 19 | 20 | 21 | - name : Download slave 22 | get_url: 23 | url : http://www-sop.inria.fr/members/Damien.Saucez/images/ubuntu-hadoop-slave.tar.gz 24 | dest: ~/ubuntu-hadoop-slave.tar.gz 25 | mode: 0666 26 | 27 | - name : Download master 28 | get_url: 29 | url : http://www-sop.inria.fr/members/Damien.Saucez/images/ubuntu-hadoop-master.tar.gz 30 | dest: ~/ubuntu-hadoop-master.tar.gz 31 | mode: 0666 32 | 33 | - name: Download onos-image 34 | get_url: 35 | url: http://www-sop.inria.fr/members/Damien.Saucez/images/ubuntu-onos-2.1.0.tar.gz 36 | dest: ~/ubuntu-onos-2.1.0.tar.gz 37 | mode: 0666 38 | 39 | 40 | - hosts : all 41 | remote_user: root 42 | tasks : 43 | - name: install python3-pip 44 | apt : 45 | update_cache: true 46 | name : python3-pip 47 | 48 | - name: install htop 49 | apt : 50 | name: htop 51 | 52 | - name: install ethtool 53 | apt : 54 | name: ethtool 55 | 56 | - name: install bridge-utils 57 | apt : 58 | name: bridge-utils 59 | 60 | - name: install net-tools 61 | apt : 62 | name: net-tools 63 | 64 | - name: install pexpect 65 | pip : 66 | name: pexpect 67 | 68 | - name: install ovs 69 | apt : 70 | name: openvswitch-switch 71 | 72 | - name: install btrfs-tools 73 | apt: 74 | name: btrfs-tools 75 | 76 | - name: install lxd 77 | apt: 78 | name: lxd 79 | 80 | - name: install lxd-client 81 | apt : 82 | name: lxd-client 83 | 84 | - name: install ryu 85 | apt: 86 | name: python3-ryu 87 | 88 | -------------------------------------------------------------------------------- /mininet/Makefile: -------------------------------------------------------------------------------- 1 | MININET = mininet/*.py 2 | TEST = mininet/test/*.py 3 | EXAMPLES = mininet/examples/*.py 4 | MN = bin/mn 5 | PYTHON ?= python 6 | PYMN = $(PYTHON) -B bin/mn 7 | BIN = $(MN) 8 | PYSRC = $(MININET) $(TEST) $(EXAMPLES) $(BIN) 9 | MNEXEC = mnexec 10 | MANPAGES = mn.1 mnexec.1 11 | P8IGN = E251,E201,E302,E202,E126,E127,E203,E226 12 | PREFIX ?= /usr 13 | BINDIR ?= $(PREFIX)/bin 14 | MANDIR ?= $(PREFIX)/share/man/man1 15 | DOCDIRS = doc/html doc/latex 16 | PDF = doc/latex/refman.pdf 17 | 18 | CFLAGS += -Wall -Wextra 19 | 20 | all: codecheck test 21 | 22 | clean: 23 | rm -rf build dist *.egg-info *.pyc $(MNEXEC) $(MANPAGES) $(DOCDIRS) 24 | 25 | codecheck: $(PYSRC) 26 | -echo "Running code check" 27 | util/versioncheck.py 28 | pyflakes $(PYSRC) 29 | pylint --rcfile=.pylint $(PYSRC) 30 | # Exclude miniedit from pep8 checking for now 31 | pep8 --repeat --ignore=$(P8IGN) `ls $(PYSRC) | grep -v miniedit.py` 32 | 33 | errcheck: $(PYSRC) 34 | -echo "Running check for errors only" 35 | pyflakes $(PYSRC) 36 | pylint -E --rcfile=.pylint $(PYSRC) 37 | 38 | test: $(MININET) $(TEST) 39 | -echo "Running tests" 40 | mininet/test/test_nets.py 41 | mininet/test/test_hifi.py 42 | 43 | slowtest: $(MININET) 44 | -echo "Running slower tests (walkthrough, examples)" 45 | mininet/test/test_walkthrough.py -v 46 | mininet/examples/test/runner.py -v 47 | 48 | mnexec: mnexec.c $(MN) mininet/net.py 49 | cc $(CFLAGS) $(LDFLAGS) -DVERSION=\"`PYTHONPATH=. $(PYMN) --version`\" $< -o $@ 50 | 51 | install-mnexec: $(MNEXEC) 52 | install -D $(MNEXEC) $(BINDIR)/$(MNEXEC) 53 | 54 | install-manpages: $(MANPAGES) 55 | install -D -t $(MANDIR) $(MANPAGES) 56 | 57 | install: install-mnexec install-manpages 58 | $(PYTHON) setup.py install 59 | 60 | develop: $(MNEXEC) $(MANPAGES) 61 | # Perhaps we should link these as well 62 | install $(MNEXEC) $(BINDIR) 63 | install $(MANPAGES) $(MANDIR) 64 | $(PYTHON) setup.py develop 65 | 66 | man: $(MANPAGES) 67 | 68 | mn.1: $(MN) 69 | PYTHONPATH=. help2man -N -n "create a Mininet network." \ 70 | --no-discard-stderr "$(PYMN)" -o $@ 71 | 72 | mnexec.1: mnexec 73 | help2man -N -n "execution utility for Mininet." \ 74 | -h "-h" -v "-v" --no-discard-stderr ./$< -o $@ 75 | 76 | .PHONY: doc 77 | 78 | doc: man 79 | doxygen doc/doxygen.cfg 80 | make -C doc/latex 81 | -------------------------------------------------------------------------------- /mininet/examples/limit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | limit.py: example of using link and CPU limits 5 | """ 6 | 7 | from mininet.net import Mininet 8 | from mininet.link import TCIntf 9 | from mininet.node import CPULimitedHost 10 | from mininet.topolib import TreeTopo 11 | from mininet.util import custom, quietRun 12 | from mininet.log import setLogLevel, info 13 | 14 | 15 | def testLinkLimit( net, bw ): 16 | "Run bandwidth limit test" 17 | info( '*** Testing network %.2f Mbps bandwidth limit\n' % bw ) 18 | net.iperf() 19 | 20 | def limit( bw=10, cpu=.1 ): 21 | """Example/test of link and CPU bandwidth limits 22 | bw: interface bandwidth limit in Mbps 23 | cpu: cpu limit as fraction of overall CPU time""" 24 | intf = custom( TCIntf, bw=bw ) 25 | myTopo = TreeTopo( depth=1, fanout=2 ) 26 | for sched in 'rt', 'cfs': 27 | info( '*** Testing with', sched, 'bandwidth limiting\n' ) 28 | if sched == 'rt': 29 | release = quietRun( 'uname -r' ).strip('\r\n') 30 | output = quietRun( 'grep CONFIG_RT_GROUP_SCHED /boot/config-%s' 31 | % release ) 32 | if output == '# CONFIG_RT_GROUP_SCHED is not set\n': 33 | info( '*** RT Scheduler is not enabled in your kernel. ' 34 | 'Skipping this test\n' ) 35 | continue 36 | host = custom( CPULimitedHost, sched=sched, cpu=cpu ) 37 | net = Mininet( topo=myTopo, intf=intf, host=host ) 38 | net.start() 39 | testLinkLimit( net, bw=bw ) 40 | net.runCpuLimitTest( cpu=cpu ) 41 | net.stop() 42 | 43 | def verySimpleLimit( bw=150 ): 44 | "Absurdly simple limiting test" 45 | intf = custom( TCIntf, bw=bw ) 46 | net = Mininet( intf=intf ) 47 | h1, h2 = net.addHost( 'h1' ), net.addHost( 'h2' ) 48 | net.addLink( h1, h2 ) 49 | net.start() 50 | net.pingAll() 51 | net.iperf() 52 | h1.cmdPrint( 'tc -s qdisc ls dev', h1.defaultIntf() ) 53 | h2.cmdPrint( 'tc -d class show dev', h2.defaultIntf() ) 54 | h1.cmdPrint( 'tc -s qdisc ls dev', h1.defaultIntf() ) 55 | h2.cmdPrint( 'tc -d class show dev', h2.defaultIntf() ) 56 | net.stop() 57 | 58 | if __name__ == '__main__': 59 | setLogLevel( 'info' ) 60 | limit() 61 | -------------------------------------------------------------------------------- /mininet/examples/scratchnet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | Build a simple network from scratch, using mininet primitives. 5 | This is more complicated than using the higher-level classes, 6 | but it exposes the configuration details and allows customization. 7 | 8 | For most tasks, the higher-level API will be preferable. 9 | """ 10 | 11 | 12 | from mininet.net import Mininet 13 | from mininet.node import Node 14 | from mininet.link import Link 15 | from mininet.log import setLogLevel, info 16 | from mininet.util import quietRun 17 | 18 | from time import sleep 19 | 20 | def scratchNet( cname='controller', cargs='-v ptcp:' ): 21 | "Create network from scratch using Open vSwitch." 22 | 23 | info( "*** Creating nodes\n" ) 24 | controller = Node( 'c0', inNamespace=False ) 25 | switch = Node( 's0', inNamespace=False ) 26 | h0 = Node( 'h0' ) 27 | h1 = Node( 'h1' ) 28 | 29 | info( "*** Creating links\n" ) 30 | Link( h0, switch ) 31 | Link( h1, switch ) 32 | 33 | info( "*** Configuring hosts\n" ) 34 | h0.setIP( '192.168.123.1/24' ) 35 | h1.setIP( '192.168.123.2/24' ) 36 | info( str( h0 ) + '\n' ) 37 | info( str( h1 ) + '\n' ) 38 | 39 | info( "*** Starting network using Open vSwitch\n" ) 40 | controller.cmd( cname + ' ' + cargs + '&' ) 41 | switch.cmd( 'ovs-vsctl del-br dp0' ) 42 | switch.cmd( 'ovs-vsctl add-br dp0' ) 43 | for intf in switch.intfs.values(): 44 | switch.cmd( 'ovs-vsctl add-port dp0 %s\n' % intf ) 45 | 46 | # Note: controller and switch are in root namespace, and we 47 | # can connect via loopback interface 48 | switch.cmd( 'ovs-vsctl set-controller dp0 tcp:127.0.0.1:6633' ) 49 | 50 | info( '*** Waiting for switch to connect to controller' ) 51 | while 'is_connected' not in quietRun( 'ovs-vsctl show' ): 52 | sleep( 1 ) 53 | info( '.' ) 54 | info( '\n' ) 55 | 56 | info( "*** Running test\n" ) 57 | h0.cmdPrint( 'ping -c1 ' + h1.IP() ) 58 | 59 | info( "*** Stopping network\n" ) 60 | controller.cmd( 'kill %' + cname ) 61 | switch.cmd( 'ovs-vsctl del-br dp0' ) 62 | switch.deleteIntfs() 63 | info( '\n' ) 64 | 65 | if __name__ == '__main__': 66 | setLogLevel( 'info' ) 67 | info( '*** Scratch network demo (kernel datapath)\n' ) 68 | Mininet.init() 69 | scratchNet() 70 | -------------------------------------------------------------------------------- /mininet/mininet/dutil.py: -------------------------------------------------------------------------------- 1 | from mininet.provision.provision import Provision 2 | from mininet.log import info, error, debug, output, warn 3 | 4 | def _info(*args, **kwargs): 5 | pass 6 | 7 | def default_images(*args, **kwargs): 8 | conf = Provision.get_configurations() 9 | ssh_conf = conf["ssh"] 10 | pub_id = ssh_conf["pub_id"] 11 | 12 | topo = kwargs['topo'] 13 | # TODO: you need to specify cpu for LXD and cores for mininet API 14 | sopts={ "image":"switch","controller":"c0", 'pub_id':pub_id, "cpu":2, "memory":"1GB"} 15 | hopts={ "image":"ubuntu", 'pub_id':pub_id, "cpu":2, "memory":"1GB"} 16 | lopts={ "bw":100 } #, "delay":"10ms"} 17 | 18 | topo.hopts.update(hopts) 19 | topo.sopts.update(sopts) 20 | topo.lopts.update(lopts) 21 | for n in topo.hosts(): 22 | infos = {} 23 | infos.update(hopts) 24 | infos.update(topo.nodeInfo(n)) 25 | topo.setNodeInfo(n, infos) 26 | 27 | for n in topo.switches(): 28 | infos = {} 29 | infos.update(sopts) 30 | infos.update(topo.nodeInfo(n)) 31 | 32 | topo.setNodeInfo(n, infos) 33 | 34 | for l in topo.links(): 35 | src, dst = l[0],l[1] 36 | infos = {} 37 | infos.update(lopts) 38 | infos.update(topo.linkInfo(src=src, dst=dst)) 39 | topo.setlinkInfo(src=src, dst=dst, info=infos) 40 | 41 | def makeFile(net, host, lines, filename, overwrite=True, wait=True): 42 | ln = 1 43 | cmds = [] 44 | for line in lines: 45 | command = 'echo %s' % (line) 46 | if overwrite and ln == 1: 47 | command = "%s > %s" % (command, filename) 48 | else: 49 | command = "%s >> %s"% (command, filename) 50 | cmds.append(command) 51 | 52 | cmd = ";".join(cmds) 53 | 54 | if wait: 55 | net.nameToNode[host].cmd(cmd) 56 | else: 57 | net.nameToNode[host].sendCmd(cmd) 58 | 59 | def makeHosts(topo, net, wait=True): 60 | lines = [] 61 | for host in topo.hosts(): 62 | lines.append("{} {}".format(net.nameToNode[host].IP(), host)) 63 | info (" >>> {} \n".format(lines)) 64 | for host in topo.hosts(): 65 | info (" Adding to host {}".format(lines)) 66 | makeFile(net=net, host=host, lines=lines, filename="/etc/hosts", overwrite=False, wait=wait) 67 | info ("\n") 68 | -------------------------------------------------------------------------------- /mininet/util/doxify.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | Convert simple documentation to epydoc/pydoctor-compatible markup 5 | """ 6 | 7 | from sys import stdin, stdout, argv 8 | import os 9 | from tempfile import mkstemp 10 | from subprocess import call 11 | 12 | import re 13 | 14 | spaces = re.compile( r'\s+' ) 15 | singleLineExp = re.compile( r'\s+"([^"]+)"' ) 16 | commentStartExp = re.compile( r'\s+"""' ) 17 | commentEndExp = re.compile( r'"""$' ) 18 | returnExp = re.compile( r'\s+(returns:.*)' ) 19 | lastindent = '' 20 | 21 | 22 | comment = False 23 | 24 | def fixParam( line ): 25 | "Change foo: bar to @foo bar" 26 | result = re.sub( r'(\w+):', r'@param \1', line ) 27 | result = re.sub( r' @', r'@', result) 28 | return result 29 | 30 | def fixReturns( line ): 31 | "Change returns: foo to @return foo" 32 | return re.sub( 'returns:', r'@returns', line ) 33 | 34 | def fixLine( line ): 35 | global comment 36 | match = spaces.match( line ) 37 | if not match: 38 | return line 39 | else: 40 | indent = match.group(0) 41 | if singleLineExp.match( line ): 42 | return re.sub( '"', '"""', line ) 43 | if commentStartExp.match( line ): 44 | comment = True 45 | if comment: 46 | line = fixReturns( line ) 47 | line = fixParam( line ) 48 | if commentEndExp.search( line ): 49 | comment = False 50 | return line 51 | 52 | 53 | def test(): 54 | "Test transformations" 55 | assert fixLine(' "foo"') == ' """foo"""' 56 | assert fixParam( 'foo: bar' ) == '@param foo bar' 57 | assert commentStartExp.match( ' """foo"""') 58 | 59 | def funTest(): 60 | testFun = ( 61 | 'def foo():\n' 62 | ' "Single line comment"\n' 63 | ' """This is a test"""\n' 64 | ' bar: int\n' 65 | ' baz: string\n' 66 | ' returns: junk"""\n' 67 | ' if True:\n' 68 | ' print "OK"\n' 69 | ).splitlines( True ) 70 | 71 | fixLines( testFun ) 72 | 73 | def fixLines( lines, fid ): 74 | for line in lines: 75 | os.write( fid, fixLine( line ) ) 76 | 77 | if __name__ == '__main__': 78 | if False: 79 | funTest() 80 | infile = open( argv[1] ) 81 | outfid, outname = mkstemp() 82 | fixLines( infile.readlines(), outfid ) 83 | infile.close() 84 | os.close( outfid ) 85 | call( [ 'doxypy', outname ] ) 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /mininet/examples/test/test_baresshd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Tests for baresshd.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | from mininet.clean import cleanup, sh 10 | from sys import stdout 11 | 12 | class testBareSSHD( unittest.TestCase ): 13 | 14 | opts = [ 'Welcome to h1', pexpect.EOF, pexpect.TIMEOUT ] 15 | 16 | def connected( self ): 17 | "Log into ssh server, check banner, then exit" 18 | p = pexpect.spawn( 'ssh 10.0.0.1 -o ConnectTimeout=1 ' 19 | '-o StrictHostKeyChecking=no ' 20 | '-i /tmp/ssh/test_rsa exit' ) 21 | while True: 22 | index = p.expect( self.opts ) 23 | if index == 0: 24 | return True 25 | else: 26 | return False 27 | 28 | 29 | def setUp( self ): 30 | # verify that sshd is not running 31 | self.assertFalse( self.connected() ) 32 | # create public key pair for testing 33 | sh( 'rm -rf /tmp/ssh' ) 34 | sh( 'mkdir /tmp/ssh' ) 35 | sh( "ssh-keygen -t rsa -P '' -f /tmp/ssh/test_rsa" ) 36 | sh( 'cat /tmp/ssh/test_rsa.pub >> /tmp/ssh/authorized_keys' ) 37 | # run example with custom sshd args 38 | cmd = ( 'python -m mininet.examples.baresshd ' 39 | '-o AuthorizedKeysFile=/tmp/ssh/authorized_keys ' 40 | '-o StrictModes=no' ) 41 | p = pexpect.spawn( cmd ) 42 | runOpts = [ 'You may now ssh into h1 at 10.0.0.1', 43 | 'after 5 seconds, h1 is not listening on port 22', 44 | pexpect.EOF, pexpect.TIMEOUT ] 45 | while True: 46 | index = p.expect( runOpts ) 47 | if index == 0: 48 | break 49 | else: 50 | self.tearDown() 51 | self.fail( 'sshd failed to start in host h1' ) 52 | 53 | def testSSH( self ): 54 | "Simple test to verify that we can ssh into h1" 55 | result = False 56 | # try to connect up to 3 times; sshd can take a while to start 57 | result = self.connected() 58 | self.assertTrue( result ) 59 | 60 | def tearDown( self ): 61 | # kill the ssh process 62 | sh( "ps aux | grep ssh |grep Banner| awk '{ print $2 }' | xargs kill" ) 63 | cleanup() 64 | # remove public key pair 65 | sh( 'rm -rf /tmp/ssh' ) 66 | 67 | if __name__ == '__main__': 68 | unittest.main() 69 | -------------------------------------------------------------------------------- /mininet/examples/test/test_bind.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Tests for bind.py 5 | """ 6 | 7 | import unittest 8 | from mininet.util import pexpect 9 | 10 | class testBind( unittest.TestCase ): 11 | 12 | prompt = 'mininet>' 13 | 14 | def setUp( self ): 15 | self.net = pexpect.spawn( 'python -m mininet.examples.bind' ) 16 | self.net.expect( "Private Directories: \[([\w\s,'/]+)\]" ) 17 | self.directories = [] 18 | # parse directories from mn output 19 | for d in self.net.match.group(1).split(', '): 20 | self.directories.append( d.strip("'") ) 21 | self.net.expect( self.prompt ) 22 | self.assertTrue( len( self.directories ) > 0 ) 23 | 24 | def testCreateFile( self ): 25 | "Create a file, a.txt, in the first private directory and verify" 26 | fileName = 'a.txt' 27 | directory = self.directories[ 0 ] 28 | path = directory + '/' + fileName 29 | self.net.sendline( 'h1 touch %s; ls %s' % ( path, directory ) ) 30 | index = self.net.expect( [ fileName, self.prompt ] ) 31 | self.assertTrue( index == 0 ) 32 | self.net.expect( self.prompt ) 33 | self.net.sendline( 'h1 rm %s' % path ) 34 | self.net.expect( self.prompt ) 35 | 36 | def testIsolation( self ): 37 | "Create a file in two hosts and verify that contents are different" 38 | fileName = 'b.txt' 39 | directory = self.directories[ 0 ] 40 | path = directory + '/' + fileName 41 | contents = { 'h1' : '1', 'h2' : '2' } 42 | # Verify file doesn't exist, then write private copy of file 43 | for host in contents: 44 | value = contents[ host ] 45 | self.net.sendline( '%s cat %s' % ( host, path ) ) 46 | self.net.expect( 'No such file' ) 47 | self.net.expect( self.prompt ) 48 | self.net.sendline( '%s echo %s > %s' % ( host, value, path ) ) 49 | self.net.expect( self.prompt ) 50 | # Verify file contents 51 | for host in contents: 52 | value = contents[ host ] 53 | self.net.sendline( '%s cat %s' % ( host, path ) ) 54 | self.net.expect( value ) 55 | self.net.expect( self.prompt ) 56 | self.net.sendline( '%s rm %s' % ( host, path ) ) 57 | self.net.expect( self.prompt ) 58 | 59 | # TODO: need more tests 60 | 61 | def tearDown( self ): 62 | self.net.sendline( 'exit' ) 63 | self.net.wait() 64 | 65 | if __name__ == '__main__': 66 | unittest.main() 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Python template 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | pip-wheel-metadata/ 26 | share/python-wheels/ 27 | *.egg-info/ 28 | .installed.cfg 29 | *.egg 30 | MANIFEST 31 | 32 | # PyInstaller 33 | # Usually these files are written by a python script from a template 34 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 35 | *.manifest 36 | *.spec 37 | 38 | # Installer logs 39 | pip-log.txt 40 | pip-delete-this-directory.txt 41 | 42 | # Unit test / coverage reports 43 | htmlcov/ 44 | .tox/ 45 | .nox/ 46 | .coverage 47 | .coverage.* 48 | .cache 49 | nosetests.xml 50 | coverage.xml 51 | *.cover 52 | .hypothesis/ 53 | .pytest_cache/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | db.sqlite3 63 | db.sqlite3-journal 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | .python-version 87 | 88 | # pipenv 89 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 90 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 91 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 92 | # install all needed dependencies. 93 | #Pipfile.lock 94 | 95 | # celery beat schedule file 96 | celerybeat-schedule 97 | 98 | # SageMath parsed files 99 | *.sage.py 100 | 101 | # Environments 102 | .env 103 | .venv 104 | env/ 105 | venv/ 106 | ENV/ 107 | env.bak/ 108 | venv.bak/ 109 | 110 | # Spyder project settings 111 | .spyderproject 112 | .spyproject 113 | 114 | # Rope project settings 115 | .ropeproject 116 | 117 | # mkdocs documentation 118 | /site 119 | 120 | # mypy 121 | .mypy_cache/ 122 | .dmypy.json 123 | dmypy.json 124 | 125 | # Pyre type checker 126 | .pyre/ 127 | # PyCharm directory 128 | .idea/ 129 | conf/conf.yml 130 | src/distrinet/cloud/g5k_credentials.json 131 | -------------------------------------------------------------------------------- /mininet/examples/bind.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | bind.py: Bind mount example 5 | 6 | This creates hosts with private directories that the user specifies. 7 | These hosts may have persistent directories that will be available 8 | across multiple mininet session, or temporary directories that will 9 | only last for one mininet session. To specify a persistent 10 | directory, add a tuple to a list of private directories: 11 | 12 | [ ( 'directory to be mounted on', 'directory to be mounted' ) ] 13 | 14 | String expansion may be used to create a directory template for 15 | each host. To do this, add a %(name)s in place of the host name 16 | when creating your list of directories: 17 | 18 | [ ( '/var/run', '/tmp/%(name)s/var/run' ) ] 19 | 20 | If no persistent directory is specified, the directories will default 21 | to temporary private directories. To do this, simply create a list of 22 | directories to be made private. A tmpfs will then be mounted on them. 23 | 24 | You may use both temporary and persistent directories at the same 25 | time. In the following privateDirs string, each host will have a 26 | persistent directory in the root filesystem at 27 | "/tmp/(hostname)/var/run" mounted on "/var/run". Each host will also 28 | have a temporary private directory mounted on "/var/log". 29 | 30 | [ ( '/var/run', '/tmp/%(name)s/var/run' ), '/var/log' ] 31 | 32 | This example has both persistent directories mounted on '/var/log' 33 | and '/var/run'. It also has a temporary private directory mounted 34 | on '/var/mn' 35 | """ 36 | 37 | from mininet.net import Mininet 38 | from mininet.node import Host 39 | from mininet.cli import CLI 40 | from mininet.topo import SingleSwitchTopo 41 | from mininet.log import setLogLevel, info 42 | 43 | from functools import partial 44 | 45 | 46 | # Sample usage 47 | 48 | def testHostWithPrivateDirs(): 49 | "Test bind mounts" 50 | topo = SingleSwitchTopo( 10 ) 51 | privateDirs = [ ( '/var/log', '/tmp/%(name)s/var/log' ), 52 | ( '/var/run', '/tmp/%(name)s/var/run' ), 53 | '/var/mn' ] 54 | host = partial( Host, 55 | privateDirs=privateDirs ) 56 | net = Mininet( topo=topo, host=host ) 57 | net.start() 58 | directories = [ directory[ 0 ] if isinstance( directory, tuple ) 59 | else directory for directory in privateDirs ] 60 | info( 'Private Directories:', directories, '\n' ) 61 | CLI( net ) 62 | net.stop() 63 | 64 | if __name__ == '__main__': 65 | setLogLevel( 'info' ) 66 | testHostWithPrivateDirs() 67 | info( 'Done.\n') 68 | -------------------------------------------------------------------------------- /mininet/examples/multiping.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | multiping.py: monitor multiple sets of hosts using ping 5 | 6 | This demonstrates how one may send a simple shell script to 7 | multiple hosts and monitor their output interactively for a period= 8 | of time. 9 | """ 10 | 11 | 12 | from mininet.net import Mininet 13 | from mininet.node import Node 14 | from mininet.topo import SingleSwitchTopo 15 | from mininet.log import info, setLogLevel 16 | 17 | from select import poll, POLLIN 18 | from time import time 19 | 20 | def chunks( l, n ): 21 | "Divide list l into chunks of size n - thanks Stackoverflow" 22 | return [ l[ i: i + n ] for i in range( 0, len( l ), n ) ] 23 | 24 | def startpings( host, targetips ): 25 | "Tell host to repeatedly ping targets" 26 | 27 | targetips = ' '.join( targetips ) 28 | 29 | # Simple ping loop 30 | cmd = ( 'while true; do ' 31 | ' for ip in %s; do ' % targetips + 32 | ' echo -n %s "->" $ip ' % host.IP() + 33 | ' `ping -c1 -w 1 $ip | grep packets` ;' 34 | ' sleep 1;' 35 | ' done; ' 36 | 'done &' ) 37 | 38 | info( '*** Host %s (%s) will be pinging ips: %s\n' % 39 | ( host.name, host.IP(), targetips ) ) 40 | 41 | host.cmd( cmd ) 42 | 43 | def multiping( netsize, chunksize, seconds): 44 | "Ping subsets of size chunksize in net of size netsize" 45 | 46 | # Create network and identify subnets 47 | topo = SingleSwitchTopo( netsize ) 48 | net = Mininet( topo=topo, waitConnected=True ) 49 | net.start() 50 | hosts = net.hosts 51 | subnets = chunks( hosts, chunksize ) 52 | 53 | # Create polling object 54 | fds = [ host.stdout.fileno() for host in hosts ] 55 | poller = poll() 56 | for fd in fds: 57 | poller.register( fd, POLLIN ) 58 | 59 | # Start pings 60 | for subnet in subnets: 61 | ips = [ host.IP() for host in subnet ] 62 | #adding bogus to generate packet loss 63 | ips.append( '10.0.0.200' ) 64 | for host in subnet: 65 | startpings( host, ips ) 66 | 67 | # Monitor output 68 | endTime = time() + seconds 69 | while time() < endTime: 70 | readable = poller.poll(1000) 71 | for fd, _mask in readable: 72 | node = Node.outToNode[ fd ] 73 | info( '%s:' % node.name, node.monitor().strip(), '\n' ) 74 | 75 | # Stop pings 76 | for host in hosts: 77 | host.cmd( 'kill %while' ) 78 | 79 | net.stop() 80 | 81 | 82 | if __name__ == '__main__': 83 | setLogLevel( 'info' ) 84 | multiping( netsize=20, chunksize=4, seconds=10 ) 85 | -------------------------------------------------------------------------------- /mininet/examples/numberedports.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | Create a network with 5 hosts, numbered 1-4 and 9. 5 | Validate that the port numbers match to the interface name, 6 | and that the ovs ports match the mininet ports. 7 | """ 8 | 9 | 10 | from mininet.net import Mininet 11 | from mininet.node import Controller 12 | from mininet.log import setLogLevel, info, warn 13 | 14 | def validatePort( switch, intf ): 15 | "Validate intf's OF port number" 16 | ofport = int( switch.cmd( 'ovs-vsctl get Interface', intf, 17 | 'ofport' ) ) 18 | if ofport != switch.ports[ intf ]: 19 | warn( 'WARNING: ofport for', intf, 'is actually', ofport, '\n' ) 20 | return 0 21 | else: 22 | return 1 23 | 24 | def testPortNumbering(): 25 | 26 | """Test port numbering: 27 | Create a network with 5 hosts (using Mininet's 28 | mid-level API) and check that implicit and 29 | explicit port numbering works as expected.""" 30 | 31 | net = Mininet( controller=Controller ) 32 | 33 | info( '*** Adding controller\n' ) 34 | net.addController( 'c0' ) 35 | 36 | info( '*** Adding hosts\n' ) 37 | h1 = net.addHost( 'h1', ip='10.0.0.1' ) 38 | h2 = net.addHost( 'h2', ip='10.0.0.2' ) 39 | h3 = net.addHost( 'h3', ip='10.0.0.3' ) 40 | h4 = net.addHost( 'h4', ip='10.0.0.4' ) 41 | h5 = net.addHost( 'h5', ip='10.0.0.5' ) 42 | 43 | info( '*** Adding switch\n' ) 44 | s1 = net.addSwitch( 's1' ) 45 | 46 | info( '*** Creating links\n' ) 47 | # host 1-4 connect to ports 1-4 on the switch 48 | net.addLink( h1, s1 ) 49 | net.addLink( h2, s1 ) 50 | net.addLink( h3, s1 ) 51 | net.addLink( h4, s1 ) 52 | # specify a different port to connect host 5 to on the switch. 53 | net.addLink( h5, s1, port1=1, port2= 9) 54 | 55 | info( '*** Starting network\n' ) 56 | net.start() 57 | 58 | # print the interfaces and their port numbers 59 | info( '\n*** printing and validating the ports ' 60 | 'running on each interface\n' ) 61 | for intfs in s1.intfList(): 62 | if not intfs.name == "lo": 63 | info( intfs, ': ', s1.ports[intfs], 64 | '\n' ) 65 | info( 'Validating that', intfs, 66 | 'is actually on port', s1.ports[intfs], '... ' ) 67 | if validatePort( s1, intfs ): 68 | info( 'Validated.\n' ) 69 | info( '\n' ) 70 | 71 | # test the network with pingall 72 | net.pingAll() 73 | info( '\n' ) 74 | 75 | info( '*** Stopping network\n' ) 76 | net.stop() 77 | 78 | if __name__ == '__main__': 79 | setLogLevel( 'info' ) 80 | testPortNumbering() 81 | -------------------------------------------------------------------------------- /mininet/examples/scratchnetuser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | Build a simple network from scratch, using mininet primitives. 5 | This is more complicated than using the higher-level classes, 6 | but it exposes the configuration details and allows customization. 7 | 8 | For most tasks, the higher-level API will be preferable. 9 | 10 | This version uses the user datapath and an explicit control network. 11 | """ 12 | 13 | from mininet.net import Mininet 14 | from mininet.node import Node 15 | from mininet.link import Link 16 | from mininet.log import setLogLevel, info 17 | 18 | def linkIntfs( node1, node2 ): 19 | "Create link from node1 to node2 and return intfs" 20 | link = Link( node1, node2 ) 21 | return link.intf1, link.intf2 22 | 23 | def scratchNetUser( cname='controller', cargs='ptcp:' ): 24 | "Create network from scratch using user switch." 25 | 26 | # It's not strictly necessary for the controller and switches 27 | # to be in separate namespaces. For performance, they probably 28 | # should be in the root namespace. However, it's interesting to 29 | # see how they could work even if they are in separate namespaces. 30 | 31 | info( '*** Creating Network\n' ) 32 | controller = Node( 'c0' ) 33 | switch = Node( 's0') 34 | h0 = Node( 'h0' ) 35 | h1 = Node( 'h1' ) 36 | cintf, sintf = linkIntfs( controller, switch ) 37 | h0intf, sintf1 = linkIntfs( h0, switch ) 38 | h1intf, sintf2 = linkIntfs( h1, switch ) 39 | 40 | info( '*** Configuring control network\n' ) 41 | controller.setIP( '10.0.123.1/24', intf=cintf ) 42 | switch.setIP( '10.0.123.2/24', intf=sintf) 43 | 44 | info( '*** Configuring hosts\n' ) 45 | h0.setIP( '192.168.123.1/24', intf=h0intf ) 46 | h1.setIP( '192.168.123.2/24', intf=h1intf ) 47 | 48 | info( '*** Network state:\n' ) 49 | for node in controller, switch, h0, h1: 50 | info( str( node ) + '\n' ) 51 | 52 | info( '*** Starting controller and user datapath\n' ) 53 | controller.cmd( cname + ' ' + cargs + '&' ) 54 | switch.cmd( 'ifconfig lo 127.0.0.1' ) 55 | intfs = str( sintf1 ), str( sintf2 ) 56 | switch.cmd( 'ofdatapath -i ' + ','.join( intfs ) + ' ptcp: &' ) 57 | switch.cmd( 'ofprotocol tcp:' + controller.IP() + ' tcp:localhost &' ) 58 | 59 | info( '*** Running test\n' ) 60 | h0.cmdPrint( 'ping -c1 ' + h1.IP() ) 61 | 62 | info( '*** Stopping network\n' ) 63 | controller.cmd( 'kill %' + cname ) 64 | switch.cmd( 'kill %ofdatapath' ) 65 | switch.cmd( 'kill %ofprotocol' ) 66 | switch.deleteIntfs() 67 | info( '\n' ) 68 | 69 | if __name__ == '__main__': 70 | setLogLevel( 'info' ) 71 | info( '*** Scratch network demo (user datapath)\n' ) 72 | Mininet.init() 73 | scratchNetUser() 74 | -------------------------------------------------------------------------------- /mininet/mininet/moduledeps.py: -------------------------------------------------------------------------------- 1 | "Module dependency utility functions for Mininet." 2 | 3 | from mininet.util import quietRun, BaseString 4 | from mininet.log import info, error, debug 5 | from os import environ 6 | 7 | def lsmod(): 8 | "Return output of lsmod." 9 | return quietRun( 'lsmod' ) 10 | 11 | def rmmod( mod ): 12 | """Return output of lsmod. 13 | mod: module string""" 14 | return quietRun( [ 'rmmod', mod ] ) 15 | 16 | def modprobe( mod ): 17 | """Return output of modprobe 18 | mod: module string""" 19 | return quietRun( [ 'modprobe', mod ] ) 20 | 21 | OF_KMOD = 'ofdatapath' 22 | OVS_KMOD = 'openvswitch_mod' # Renamed 'openvswitch' in OVS 1.7+/Linux 3.5+ 23 | TUN = 'tun' 24 | 25 | def moduleDeps( subtract=None, add=None ): 26 | """Handle module dependencies. 27 | subtract: string or list of module names to remove, if already loaded 28 | add: string or list of module names to add, if not already loaded""" 29 | subtract = subtract if subtract is not None else [] 30 | add = add if add is not None else [] 31 | if isinstance( subtract, BaseString ): 32 | subtract = [ subtract ] 33 | if isinstance( add, BaseString ): 34 | add = [ add ] 35 | for mod in subtract: 36 | if mod in lsmod(): 37 | info( '*** Removing ' + mod + '\n' ) 38 | rmmodOutput = rmmod( mod ) 39 | if rmmodOutput: 40 | error( 'Error removing ' + mod + ': "%s">\n' % rmmodOutput ) 41 | exit( 1 ) 42 | if mod in lsmod(): 43 | error( 'Failed to remove ' + mod + '; still there!\n' ) 44 | exit( 1 ) 45 | for mod in add: 46 | if mod not in lsmod(): 47 | info( '*** Loading ' + mod + '\n' ) 48 | modprobeOutput = modprobe( mod ) 49 | if modprobeOutput: 50 | error( 'Error inserting ' + mod + 51 | ' - is it installed and available via modprobe?\n' + 52 | 'Error was: "%s"\n' % modprobeOutput ) 53 | if mod not in lsmod(): 54 | error( 'Failed to insert ' + mod + ' - quitting.\n' ) 55 | exit( 1 ) 56 | else: 57 | debug( '*** ' + mod + ' already loaded\n' ) 58 | 59 | 60 | def pathCheck( *args, **kwargs ): 61 | "Make sure each program in *args can be found in $PATH." 62 | moduleName = kwargs.get( 'moduleName', 'it' ) 63 | for arg in args: 64 | if not quietRun( 'which ' + arg ): 65 | error( 'Cannot find required executable %s.\n' % arg + 66 | 'Please make sure that %s is installed ' % moduleName + 67 | 'and available in your $PATH:\n(%s)\n' % environ[ 'PATH' ] ) 68 | exit( 1 ) 69 | -------------------------------------------------------------------------------- /mininet/bin/README.md: -------------------------------------------------------------------------------- 1 | # DMN 2 | 3 | ## Deployment in Amazon 4 | 5 | ``` 6 | python3 bin/dmn --provision=aws --controller=lxcremote,ip=192.168.0.1 7 | ``` 8 | 9 | With the possibility to overwrite default parameters: 10 | 11 | ``` 12 | python3 bin/dmn --provision=aws,3,instanceType=t3.2xlarge,volumeSize=10 --controller=lxcremote,ip=192.168.0.1 13 | ``` 14 | 15 | would instantiate a total of 3 t3.2xlarge instances, each one with a volume 16 | size of 10 GiB. 17 | 18 | ## Using running cluster 19 | 20 | Specify the bastion address in the `ssh` section of the `~/.distrinet/conf.yml` 21 | file or using the `--bastion` option: 22 | 23 | ``` 24 | python3 bin/dmn [--bastion ] --workers=",,...," --custom=default_image.py 25 | ``` 26 | 27 | ## Note 28 | 29 | To connect to an already started controller: 30 | 31 | ``` 32 | --controller=lxcremote,ip= 33 | ``` 34 | 35 | where 36 | 37 | * `` is an address reachable on the admin network where an OpenFlow controller listens 38 | 39 | ``` 40 | --controller=onoslxc,ip=,[admin_ip=,target=] 41 | ``` 42 | 43 | where 44 | 45 | 46 | * `` is an address reachable on the admin network where an OpenFlow 47 | controller listens, 48 | * `` is the admin IP address for the container, 49 | * `` is the IP of the node where to deploy the container. 50 | 51 | When `` is not specified the `` address is used as admin IP. 52 | 53 | When `` is not specified, the master node is used to host the 54 | controller. 55 | 56 | # Port forwarding 57 | 58 | To forward ports from bastion to a reachable machine, add an entry as follows 59 | in the `port_forwarding` section of the `~/.distrinet/conf.yml` file. 60 | 61 | ``` 62 | port_forwarding: 63 | - local: 64 | proto: '' 65 | ip: '' 66 | remote: 67 | ``` 68 | 69 | To forward ports from bastion to a container, add an entry as follows in the 70 | `port_forwarding` section of the `~/.distrinet/conf.yml` file. 71 | 72 | ``` 73 | port_forwarding: 74 | - local: 75 | proto: '' 76 | container: '' 77 | ip: '' 78 | remote: 79 | ``` 80 | 81 | 82 | 83 | # Runing Hadoop tests 84 | 85 | ``` 86 | --controller=lxcremote,ip=192.168.0.1 --custom hadoop_test.py --test hadoop 87 | ``` 88 | 89 | ## Examples 90 | 91 | ``` 92 | python3 bin/dmn --workers="10.0.0.200,10.0.1.31,10.0.1.76" --topo=tree,2 --controller=lxcremote,ip=192.168.0.1 --custom=default_image.py 93 | ``` 94 | 95 | ``` 96 | python3 bin/dmn --workers="10.0.0.200,10.0.1.31,10.0.1.76" --topo=tree,2 --controller=onoslxc,ip=192.168.0.250,admin_ip=192.168.0.250,target=10.0.0.200 --custom=default_image.py 97 | ``` 98 | -------------------------------------------------------------------------------- /mininet/examples/multipoll.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | Simple example of sending output to multiple files and 5 | monitoring them 6 | """ 7 | 8 | 9 | from mininet.topo import SingleSwitchTopo 10 | from mininet.net import Mininet 11 | from mininet.log import info, setLogLevel 12 | from mininet.util import decode 13 | 14 | from time import time 15 | from select import poll, POLLIN 16 | from subprocess import Popen, PIPE 17 | 18 | 19 | def monitorFiles( outfiles, seconds, timeoutms ): 20 | "Monitor set of files and return [(host, line)...]" 21 | devnull = open( '/dev/null', 'w' ) 22 | tails, fdToFile, fdToHost = {}, {}, {} 23 | for h, outfile in outfiles.items(): 24 | tail = Popen( [ 'tail', '-f', outfile ], 25 | stdout=PIPE, stderr=devnull ) 26 | fd = tail.stdout.fileno() 27 | tails[ h ] = tail 28 | fdToFile[ fd ] = tail.stdout 29 | fdToHost[ fd ] = h 30 | # Prepare to poll output files 31 | readable = poll() 32 | for t in tails.values(): 33 | readable.register( t.stdout.fileno(), POLLIN ) 34 | # Run until a set number of seconds have elapsed 35 | endTime = time() + seconds 36 | while time() < endTime: 37 | fdlist = readable.poll(timeoutms) 38 | if fdlist: 39 | for fd, _flags in fdlist: 40 | f = fdToFile[ fd ] 41 | host = fdToHost[ fd ] 42 | # Wait for a line of output 43 | line = f.readline().strip() 44 | yield host, decode( line ) 45 | else: 46 | # If we timed out, return nothing 47 | yield None, '' 48 | for t in tails.values(): 49 | t.terminate() 50 | devnull.close() # Not really necessary 51 | 52 | 53 | def monitorTest( N=3, seconds=3 ): 54 | "Run pings and monitor multiple hosts" 55 | topo = SingleSwitchTopo( N ) 56 | net = Mininet( topo ) 57 | net.start() 58 | hosts = net.hosts 59 | info( "Starting test...\n" ) 60 | server = hosts[ 0 ] 61 | outfiles, errfiles = {}, {} 62 | for h in hosts: 63 | # Create and/or erase output files 64 | outfiles[ h ] = '/tmp/%s.out' % h.name 65 | errfiles[ h ] = '/tmp/%s.err' % h.name 66 | h.cmd( 'echo >', outfiles[ h ] ) 67 | h.cmd( 'echo >', errfiles[ h ] ) 68 | # Start pings 69 | h.cmdPrint('ping', server.IP(), 70 | '>', outfiles[ h ], 71 | '2>', errfiles[ h ], 72 | '&' ) 73 | info( "Monitoring output for", seconds, "seconds\n" ) 74 | for h, line in monitorFiles( outfiles, seconds, timeoutms=500 ): 75 | if h: 76 | info( '%s: %s\n' % ( h.name, line ) ) 77 | for h in hosts: 78 | h.cmd('kill %ping') 79 | net.stop() 80 | 81 | 82 | if __name__ == '__main__': 83 | setLogLevel('info') 84 | monitorTest() 85 | -------------------------------------------------------------------------------- /mininet/mininet/term.py: -------------------------------------------------------------------------------- 1 | """ 2 | Terminal creation and cleanup. 3 | Utility functions to run a terminal (connected via socat(1)) on each host. 4 | 5 | Requires socat(1) and xterm(1). 6 | Optionally uses gnome-terminal. 7 | """ 8 | 9 | from os import environ 10 | 11 | from mininet.log import error 12 | from mininet.util import quietRun, errRun 13 | 14 | def tunnelX11( node, display=None): 15 | """Create an X11 tunnel from node:6000 to the root host 16 | display: display on root host (optional) 17 | returns: node $DISPLAY, Popen object for tunnel""" 18 | if display is None and 'DISPLAY' in environ: 19 | display = environ[ 'DISPLAY' ] 20 | if display is None: 21 | error( "Error: Cannot connect to display\n" ) 22 | return None, None 23 | host, screen = display.split( ':' ) 24 | # Unix sockets should work 25 | if not host or host == 'unix': 26 | # GDM3 doesn't put credentials in .Xauthority, 27 | # so allow root to just connect 28 | quietRun( 'xhost +si:localuser:root' ) 29 | return display, None 30 | else: 31 | # Create a tunnel for the TCP connection 32 | port = 6000 + int( float( screen ) ) 33 | connection = r'TCP\:%s\:%s' % ( host, port ) 34 | cmd = [ "socat", "TCP-LISTEN:%d,fork,reuseaddr" % port, 35 | "EXEC:'mnexec -a 1 socat STDIO %s'" % connection ] 36 | return 'localhost:' + screen, node.popen( cmd ) 37 | 38 | def makeTerm( node, title='Node', term='xterm', display=None, cmd='bash'): 39 | """Create an X11 tunnel to the node and start up a terminal. 40 | node: Node object 41 | title: base title 42 | term: 'xterm' or 'gterm' 43 | returns: two Popen objects, tunnel and terminal""" 44 | title = '"%s: %s"' % ( title, node.name ) 45 | if not node.inNamespace: 46 | title += ' (root)' 47 | cmds = { 48 | 'xterm': [ 'xterm', '-title', title, '-display' ], 49 | 'gterm': [ 'gnome-terminal', '--title', title, '--display' ] 50 | } 51 | if term not in cmds: 52 | error( 'invalid terminal type: %s' % term ) 53 | return 54 | display, tunnel = tunnelX11( node, display ) 55 | if display is None: 56 | return [] 57 | term = node.popen( cmds[ term ] + 58 | [ display, '-e', 'env TERM=ansi %s' % cmd ] ) 59 | return [ tunnel, term ] if tunnel else [ term ] 60 | 61 | def runX11( node, cmd ): 62 | "Run an X11 client on a node" 63 | _display, tunnel = tunnelX11( node ) 64 | if _display is None: 65 | return [] 66 | popen = node.popen( cmd ) 67 | return [ tunnel, popen ] 68 | 69 | def cleanUpScreens(): 70 | "Remove moldy socat X11 tunnels." 71 | errRun( "pkill -9 -f mnexec.*socat" ) 72 | 73 | def makeTerms( nodes, title='Node', term='xterm' ): 74 | """Create terminals. 75 | nodes: list of Node objects 76 | title: base title for each 77 | returns: list of created tunnel/terminal processes""" 78 | terms = [] 79 | for node in nodes: 80 | terms += makeTerm( node, title, term ) 81 | return terms 82 | -------------------------------------------------------------------------------- /mininet/examples/linuxrouter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | linuxrouter.py: Example network with Linux IP router 5 | 6 | This example converts a Node into a router using IP forwarding 7 | already built into Linux. 8 | 9 | The example topology creates a router and three IP subnets: 10 | 11 | - 192.168.1.0/24 (r0-eth1, IP: 192.168.1.1) 12 | - 172.16.0.0/12 (r0-eth2, IP: 172.16.0.1) 13 | - 10.0.0.0/8 (r0-eth3, IP: 10.0.0.1) 14 | 15 | Each subnet consists of a single host connected to 16 | a single switch: 17 | 18 | r0-eth1 - s1-eth1 - h1-eth0 (IP: 192.168.1.100) 19 | r0-eth2 - s2-eth1 - h2-eth0 (IP: 172.16.0.100) 20 | r0-eth3 - s3-eth1 - h3-eth0 (IP: 10.0.0.100) 21 | 22 | The example relies on default routing entries that are 23 | automatically created for each router interface, as well 24 | as 'defaultRoute' parameters for the host interfaces. 25 | 26 | Additional routes may be added to the router or hosts by 27 | executing 'ip route' or 'route' commands on the router or hosts. 28 | """ 29 | 30 | 31 | from mininet.topo import Topo 32 | from mininet.net import Mininet 33 | from mininet.node import Node 34 | from mininet.log import setLogLevel, info 35 | from mininet.cli import CLI 36 | 37 | 38 | class LinuxRouter( Node ): 39 | "A Node with IP forwarding enabled." 40 | 41 | def config( self, **params ): 42 | super( LinuxRouter, self).config( **params ) 43 | # Enable forwarding on the router 44 | self.cmd( 'sysctl net.ipv4.ip_forward=1' ) 45 | 46 | def terminate( self ): 47 | self.cmd( 'sysctl net.ipv4.ip_forward=0' ) 48 | super( LinuxRouter, self ).terminate() 49 | 50 | 51 | class NetworkTopo( Topo ): 52 | "A LinuxRouter connecting three IP subnets" 53 | 54 | def build( self, **_opts ): 55 | 56 | defaultIP = '192.168.1.1/24' # IP address for r0-eth1 57 | router = self.addNode( 'r0', cls=LinuxRouter, ip=defaultIP ) 58 | 59 | s1, s2, s3 = [ self.addSwitch( s ) for s in ( 's1', 's2', 's3' ) ] 60 | 61 | self.addLink( s1, router, intfName2='r0-eth1', 62 | params2={ 'ip' : defaultIP } ) # for clarity 63 | self.addLink( s2, router, intfName2='r0-eth2', 64 | params2={ 'ip' : '172.16.0.1/12' } ) 65 | self.addLink( s3, router, intfName2='r0-eth3', 66 | params2={ 'ip' : '10.0.0.1/8' } ) 67 | 68 | h1 = self.addHost( 'h1', ip='192.168.1.100/24', 69 | defaultRoute='via 192.168.1.1' ) 70 | h2 = self.addHost( 'h2', ip='172.16.0.100/12', 71 | defaultRoute='via 172.16.0.1' ) 72 | h3 = self.addHost( 'h3', ip='10.0.0.100/8', 73 | defaultRoute='via 10.0.0.1' ) 74 | 75 | for h, s in [ (h1, s1), (h2, s2), (h3, s3) ]: 76 | self.addLink( h, s ) 77 | 78 | 79 | def run(): 80 | "Test linux router" 81 | topo = NetworkTopo() 82 | net = Mininet( topo=topo ) # controller is used by s1-s3 83 | net.start() 84 | info( '*** Routing Table on Router:\n' ) 85 | info( net[ 'r0' ].cmd( 'route' ) ) 86 | CLI( net ) 87 | net.stop() 88 | 89 | if __name__ == '__main__': 90 | setLogLevel( 'info' ) 91 | run() 92 | -------------------------------------------------------------------------------- /mininet/mininet/topolib.py: -------------------------------------------------------------------------------- 1 | "Library of potentially useful topologies for Mininet" 2 | 3 | from mininet.topo import Topo 4 | from mininet.net import Mininet 5 | 6 | # The build() method is expected to do this: 7 | # pylint: disable=arguments-differ 8 | 9 | class TreeTopo( Topo ): 10 | "Topology for a tree network with a given depth and fanout." 11 | 12 | def build( self, depth=1, fanout=2 ): 13 | # Numbering: h1..N, s1..M 14 | self.hostNum = 1 15 | self.switchNum = 1 16 | # Build topology 17 | self.addTree( depth, fanout ) 18 | 19 | def addTree( self, depth, fanout ): 20 | """Add a subtree starting with node n. 21 | returns: last node added""" 22 | isSwitch = depth > 0 23 | if isSwitch: 24 | node = self.addSwitch( 's%s' % self.switchNum ) 25 | self.switchNum += 1 26 | for _ in range( fanout ): 27 | child = self.addTree( depth - 1, fanout ) 28 | self.addLink( node, child ) 29 | else: 30 | node = self.addHost( 'h%s' % self.hostNum ) 31 | self.hostNum += 1 32 | return node 33 | 34 | 35 | def TreeNet( depth=1, fanout=2, **kwargs ): 36 | "Convenience function for creating tree networks." 37 | topo = TreeTopo( depth, fanout ) 38 | return Mininet( topo, **kwargs ) 39 | 40 | 41 | class TorusTopo( Topo ): 42 | """2-D Torus topology 43 | WARNING: this topology has LOOPS and WILL NOT WORK 44 | with the default controller or any Ethernet bridge 45 | without STP turned on! It can be used with STP, e.g.: 46 | # mn --topo torus,3,3 --switch lxbr,stp=1 --test pingall""" 47 | 48 | def build( self, x, y, n=1 ): 49 | """x: dimension of torus in x-direction 50 | y: dimension of torus in y-direction 51 | n: number of hosts per switch""" 52 | if x < 3 or y < 3: 53 | raise Exception( 'Please use 3x3 or greater for compatibility ' 54 | 'with 2.1' ) 55 | if n == 1: 56 | genHostName = lambda loc, k: 'h%s' % ( loc ) 57 | else: 58 | genHostName = lambda loc, k: 'h%sx%d' % ( loc, k ) 59 | 60 | hosts, switches, dpid = {}, {}, 0 61 | # Create and wire interior 62 | for i in range( 0, x ): 63 | for j in range( 0, y ): 64 | loc = '%dx%d' % ( i + 1, j + 1 ) 65 | # dpid cannot be zero for OVS 66 | dpid = ( i + 1 ) * 256 + ( j + 1 ) 67 | switch = switches[ i, j ] = self.addSwitch( 68 | 's' + loc, dpid='%x' % dpid ) 69 | for k in range( 0, n ): 70 | host = hosts[ i, j, k ] = self.addHost( 71 | genHostName( loc, k + 1 ) ) 72 | self.addLink( host, switch ) 73 | # Connect switches 74 | for i in range( 0, x ): 75 | for j in range( 0, y ): 76 | sw1 = switches[ i, j ] 77 | sw2 = switches[ i, ( j + 1 ) % y ] 78 | sw3 = switches[ ( i + 1 ) % x, j ] 79 | self.addLink( sw1, sw2 ) 80 | self.addLink( sw1, sw3 ) 81 | 82 | # pylint: enable=arguments-differ 83 | -------------------------------------------------------------------------------- /mininet/mininet/provision/playbooks/install-aws-lxd.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: master 4 | tasks: 5 | 6 | - name : Download switch 7 | get_url: 8 | url : https://distrinet.s3.eu-central-1.amazonaws.com/switch.tar.gz 9 | dest: ~/switch.tar.gz 10 | mode: 0666 11 | 12 | - name : Download ubuntu18:04 13 | get_url: 14 | url : https://distrinet.s3.eu-central-1.amazonaws.com/ubuntu.tar.gz 15 | dest: ~/ubuntu.tar.gz 16 | mode: 0666 17 | 18 | - name : Download slave 19 | get_url: 20 | url : https://distrinet.s3.eu-central-1.amazonaws.com/ubuntu-hadoop-slave.tar.gz 21 | dest: ~/ubuntu-hadoop-slave.tar.gz 22 | mode: 0666 23 | 24 | - name : Download master 25 | get_url: 26 | url : https://distrinet.s3.eu-central-1.amazonaws.com/ubuntu-hadoop-master.tar.gz 27 | dest: ~/ubuntu-hadoop-master.tar.gz 28 | mode: 0666 29 | 30 | - name: Download onos-image 31 | get_url: 32 | url: https://distrinet.s3.eu-central-1.amazonaws.com/ubuntu-onos-2.1.0.tar.gz 33 | dest: ~/ubuntu-onos-2.1.0.tar.gz 34 | mode: 0666 35 | 36 | # - name : Download switch 37 | # get_url: 38 | # url : http://18.195.229.56:8000/switch.tar.gz 39 | # dest: ~/switch.tar.gz 40 | # mode: 0666 41 | # 42 | # - name : Download ubuntu18:04 43 | # get_url: 44 | # url : http://18.195.229.56:8000/ubuntu.tar.gz 45 | # dest: ~/ubuntu.tar.gz 46 | # mode: 0666 47 | # 48 | # - name : Download slave 49 | # get_url: 50 | # url : http://18.195.229.56:8000/ubuntu-hadoop-slave.tar.gz 51 | # dest: ~/ubuntu-hadoop-slave.tar.gz 52 | # mode: 0666 53 | # 54 | # - name : Download master 55 | # get_url: 56 | # url : http://18.195.229.56:8000/ubuntu-hadoop-master.tar.gz 57 | # dest: ~/ubuntu-hadoop-master.tar.gz 58 | # mode: 0666 59 | # 60 | # - name: Download onos-image 61 | # get_url: 62 | # url: http://18.195.229.56:8000/ubuntu-onos-2.1.0.tar.gz 63 | # dest: ~/ubuntu-onos-2.1.0.tar.gz 64 | # mode: 0666 65 | 66 | - hosts : all 67 | remote_user: ubuntu 68 | become : true 69 | tasks : 70 | - name: install python3-pip 71 | apt : 72 | update_cache: true 73 | name : python3-pip 74 | 75 | - name: install ethtool 76 | apt : 77 | name: ethtool 78 | 79 | - name: install ryu 80 | apt : 81 | name: python3-ryu 82 | 83 | - name: install bridge-utils 84 | apt : 85 | name: bridge-utils 86 | 87 | - name: install net-tools 88 | apt : 89 | name: net-tools 90 | 91 | - name: install pexpect 92 | pip : 93 | name: pexpect 94 | 95 | - name: install ovs 96 | apt : 97 | name: openvswitch-switch 98 | 99 | 100 | - hosts : workers 101 | remote_user: ubuntu 102 | become : true 103 | tasks : 104 | - name : remove root block 105 | command: sudo rm -f /root/.ssh/authorized_keys 106 | 107 | - name : allow root access 108 | command: sudo cp /home/ubuntu/.ssh/authorized_keys /root/.ssh/authorized_keys 109 | -------------------------------------------------------------------------------- /mininet/util/build-ovs-packages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Attempt to build debian packages for OVS 4 | 5 | set -e # exit on error 6 | set -u # exit on undefined variable 7 | 8 | kvers=`uname -r` 9 | ksrc=/lib/modules/$kvers/build 10 | dist=`lsb_release -is | tr [A-Z] [a-z]` 11 | release=`lsb_release -rs` 12 | arch=`uname -m` 13 | buildsuffix=-2 14 | if [ "$arch" = "i686" ]; then arch=i386; fi 15 | if [ "$arch" = "x86_64" ]; then arch=amd64; fi 16 | 17 | overs=1.4.0 18 | ovs=openvswitch-$overs 19 | ovstgz=$ovs.tar.gz 20 | ovsurl=http://openvswitch.org/releases/$ovstgz 21 | 22 | install='sudo apt-get install -y' 23 | 24 | echo "*** Installing debian/ubuntu build system" 25 | $install build-essential devscripts ubuntu-dev-tools debhelper dh-make 26 | $install diff patch cdbs quilt gnupg fakeroot lintian pbuilder piuparts 27 | $install module-assistant 28 | 29 | echo "*** Installing OVS dependencies" 30 | $install pkg-config gcc make python-dev libssl-dev libtool 31 | $install dkms ipsec-tools 32 | 33 | echo "*** Installing headers for $kvers" 34 | $install linux-headers-$kvers 35 | 36 | echo "*** Retrieving OVS source" 37 | wget -c $ovsurl 38 | tar xzf $ovstgz 39 | cd $ovs 40 | 41 | echo "*** Patching OVS source" 42 | # Not sure why this fails, but off it goes! 43 | sed -i -e 's/dh_strip/# dh_strip/' debian/rules 44 | if [ "$release" = "10.04" ]; then 45 | # Lucid doesn't seem to have all the packages for ovsdbmonitor 46 | echo "*** Patching debian/rules to remove dh_python2" 47 | sed -i -e 's/dh_python2/dh_pysupport/' debian/rules 48 | echo "*** Not building ovsdbmonitor since it's too hard on 10.04" 49 | mv debian/ovsdbmonitor.install debian/ovsdbmonitor.install.backup 50 | sed -i -e 's/ovsdbmonitor.install/ovsdbmonitor.install.backup/' Makefile.in 51 | else 52 | # Install a bag of hurt for ovsdbmonitor 53 | $install python-pyside.qtcore pyqt4-dev-tools python-twisted python-twisted-bin \ 54 | python-twisted-core python-twisted-conch python-anyjson python-zope.interface 55 | fi 56 | # init script was written to assume that commands complete 57 | sed -i -e 's/^set -e/#set -e/' debian/openvswitch-controller.init 58 | 59 | echo "*** Building OVS user packages" 60 | opts=--with-linux=/lib/modules/`uname -r`/build 61 | fakeroot make -f debian/rules DATAPATH_CONFIGURE_OPTS=$opts binary 62 | 63 | echo "*** Building OVS datapath kernel module package" 64 | # Still looking for the "right" way to do this... 65 | sudo mkdir -p /usr/src/linux 66 | ln -sf _debian/openvswitch.tar.gz . 67 | sudo make -f debian/rules.modules KSRC=$ksrc KVERS=$kvers binary-modules 68 | 69 | echo "*** Built the following packages:" 70 | cd ~ 71 | ls -l *deb 72 | 73 | archive=ovs-$overs-core-$dist-$release-$arch$buildsuffix.tar 74 | ovsbase='common pki switch brcompat controller datapath-dkms' 75 | echo "*** Packing up $ovsbase .debs into:" 76 | echo " $archive" 77 | pkgs="" 78 | for component in $ovsbase; do 79 | if echo $component | egrep 'dkms|pki'; then 80 | # Architecture-independent packages 81 | deb=(openvswitch-${component}_$overs*all.deb) 82 | else 83 | deb=(openvswitch-${component}_$overs*$arch.deb) 84 | fi 85 | pkgs="$pkgs $deb" 86 | done 87 | rm -rf $archive 88 | tar cf $archive $pkgs 89 | 90 | echo "*** Contents of archive $archive:" 91 | tar tf $archive 92 | 93 | echo "*** Done (hopefully)" 94 | 95 | -------------------------------------------------------------------------------- /mininet/examples/sshd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | Create a network and start sshd(8) on each host. 5 | 6 | While something like rshd(8) would be lighter and faster, 7 | (and perfectly adequate on an in-machine network) 8 | the advantage of running sshd is that scripts can work 9 | unchanged on mininet and hardware. 10 | 11 | In addition to providing ssh access to hosts, this example 12 | demonstrates: 13 | 14 | - creating a convenience function to construct networks 15 | - connecting the host network to the root namespace 16 | - running server processes (sshd in this case) on hosts 17 | """ 18 | 19 | import sys 20 | 21 | from mininet.net import Mininet 22 | from mininet.cli import CLI 23 | from mininet.log import lg, info 24 | from mininet.node import Node 25 | from mininet.topolib import TreeTopo 26 | from mininet.util import waitListening 27 | 28 | 29 | def TreeNet( depth=1, fanout=2, **kwargs ): 30 | "Convenience function for creating tree networks." 31 | topo = TreeTopo( depth, fanout ) 32 | return Mininet( topo, **kwargs ) 33 | 34 | def connectToRootNS( network, switch, ip, routes ): 35 | """Connect hosts to root namespace via switch. Starts network. 36 | network: Mininet() network object 37 | switch: switch to connect to root namespace 38 | ip: IP address for root namespace node 39 | routes: host networks to route to""" 40 | # Create a node in root namespace and link to switch 0 41 | root = Node( 'root', inNamespace=False ) 42 | intf = network.addLink( root, switch ).intf1 43 | root.setIP( ip, intf=intf ) 44 | # Start network that now includes link to root namespace 45 | network.start() 46 | # Add routes from root ns to hosts 47 | for route in routes: 48 | root.cmd( 'route add -net ' + route + ' dev ' + str( intf ) ) 49 | 50 | def sshd( network, cmd='/usr/sbin/sshd', opts='-D', 51 | ip='10.123.123.1/32', routes=None, switch=None ): 52 | """Start a network, connect it to root ns, and run sshd on all hosts. 53 | ip: root-eth0 IP address in root namespace (10.123.123.1/32) 54 | routes: Mininet host networks to route to (10.0/24) 55 | switch: Mininet switch to connect to root namespace (s1)""" 56 | if not switch: 57 | switch = network[ 's1' ] # switch to use 58 | if not routes: 59 | routes = [ '10.0.0.0/24' ] 60 | connectToRootNS( network, switch, ip, routes ) 61 | for host in network.hosts: 62 | host.cmd( cmd + ' ' + opts + '&' ) 63 | info( "*** Waiting for ssh daemons to start\n" ) 64 | for server in network.hosts: 65 | waitListening( server=server, port=22, timeout=5 ) 66 | 67 | info( "\n*** Hosts are running sshd at the following addresses:\n" ) 68 | for host in network.hosts: 69 | info( host.name, host.IP(), '\n' ) 70 | info( "\n*** Type 'exit' or control-D to shut down network\n" ) 71 | CLI( network ) 72 | for host in network.hosts: 73 | host.cmd( 'kill %' + cmd ) 74 | network.stop() 75 | 76 | if __name__ == '__main__': 77 | lg.setLogLevel( 'info') 78 | net = TreeNet( depth=1, fanout=4 ) 79 | # get sshd args from the command line or use default args 80 | # useDNS=no -u0 to avoid reverse DNS lookup timeout 81 | argvopts = ' '.join( sys.argv[ 1: ] ) if len( sys.argv ) > 1 else ( 82 | '-D -o UseDNS=no -u0' ) 83 | sshd( net, opts=argvopts ) 84 | -------------------------------------------------------------------------------- /mininet/mininet/provision/playbooks/configure-lxd.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts : master 4 | remote_user: root 5 | vars : 6 | master_ip: "{{ master_ip }}" 7 | tasks : 8 | - name : master lxd configuration 9 | expect: 10 | echo : yes 11 | command : lxd init 12 | timeout : 20 13 | responses: 14 | (?i)Would you like to use LXD clustering? : "yes" 15 | (?i)What name should be used to identify this node in the cluster? : "" 16 | (?i)What IP address or DNS name should be used to reach this node? : "" 17 | (?i)Are you joining an existing cluster? : "no" 18 | (?i)Setup password authentication on the cluster? : "yes" 19 | (?i)Trust password for new clients : "s3cr3t" 20 | (?i)Again : "s3cr3t" 21 | (?i)Do you want to configure a new local storage pool? : "yes" 22 | (?i)Do you want to configure a new remote storage pool? : "no" 23 | (?i)Name of the storage backend to use : "dir" 24 | (?i)Would you like to connect to a MAAS server? : "no" 25 | (?i)Would you like to configure LXD to use an existing bridge or host interface?: "no" 26 | (?i)Would you like to create a new Fan overlay network? : "no" 27 | (?i)Would you like stale cached images to be updated automatically? : "yes" 28 | (?i)Would you like a YAML : "no" 29 | 30 | 31 | - hosts : workers 32 | remote_user: root 33 | vars : 34 | master_ip: "{{ master_ip }}" 35 | tasks : 36 | - name : slaves lxd configuration 37 | expect: 38 | echo : yes 39 | command : lxd init 40 | timeout : 20 41 | responses: 42 | (?i)Would you like to use LXD clustering? : "yes" 43 | (?i)What name should be used to identify this node in the cluster?: "" 44 | (?i)What IP address or DNS name should be used to reach this node?: "" 45 | (?i)Are you joining an existing cluster? : "yes" 46 | (?i)IP address or FQDN of an existing cluster node : "{{ master_ip }}" 47 | (?i)Is this the correct fingerprint : "yes" 48 | (?i)Setup password authentication on the cluster? : "yes" 49 | (?i)Cluster trust password : "s3cr3t" 50 | (?i)All existing data is lost when joining a cluster : "yes" 51 | (?i)Choose the local disk or dataset for storage pool : "" 52 | (?i)Would you like a YAML : "no" 53 | 54 | - hosts : master 55 | remote_user: root 56 | vars : 57 | master_ip: "{{ master_ip }}" 58 | tasks : 59 | - name : create switch image 60 | command: lxc image import ~/switch.tar.gz --alias switch --public 61 | # 62 | - name : create ubuntu18.04 image -- alias ubuntu 63 | command: lxc image import ~/ubuntu.tar.gz --alias ubuntu --public 64 | # 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /mininet/mininet/provision/playbooks/configure-lxd-no-clustering.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts : all 4 | remote_user: root 5 | tasks : 6 | - name : lxd configuration 7 | expect: 8 | echo : yes 9 | command : lxd init 10 | timeout : 20 11 | responses: 12 | (?i)Would you like to use LXD clustering? : "no" 13 | (?i)Do you want to configure a new storage pool? : "yes" 14 | (?i)Name of the new storage pool : "default" 15 | (?i)Name of the storage backend to use : "zfs" 16 | (?i)Create a new BTRFS pool? : "yes" 17 | (?i)Create a new ZFS pool : "yes" 18 | (?i)Would you like to use an existing block device? : "no" 19 | (?i)Would you like to use an existing empty block device : "no" 20 | (?i)Would you like to connect to a MAAS server? : "no" 21 | (?i)Size in GB of the new loop device : "15GB" 22 | (?i)Would you like to configure LXD to use an existing bridge or host interface?: "no" 23 | (?i)Would you like to create a new local network bridge? : "no" 24 | (?i)Would you like LXD to be available over the network : "no" 25 | (?i)Would you like the LXD server to be available over the network : "no" 26 | (?i)Would you like stale cached images to be updated automatically? : "no" 27 | (?i)Would you like a YAML : "no" 28 | 29 | 30 | - hosts : all 31 | remote_user: root 32 | tasks : 33 | - name : distribute switch image 34 | copy : 35 | src : ~/switch.tar.gz 36 | dest : ~/switch.tar.gz 37 | 38 | - name : distribute ubuntu image 39 | copy : 40 | src : ~/ubuntu.tar.gz 41 | dest : ~/ubuntu.tar.gz 42 | 43 | # - name : distribute debian image 44 | # copy : 45 | # src : ~/debian.tar.gz 46 | # dest : ~/debian.tar.gz 47 | 48 | # - name : distribute master image 49 | # copy : 50 | # src : ~/ubuntu-hadoop-master.tar.gz 51 | # dest : ~/ubuntu-hadoop-master.tar.gz 52 | 53 | # - name : distribute slave image 54 | # copy : 55 | # src : ~/ubuntu-hadoop-slave.tar.gz 56 | # dest : ~/ubuntu-hadoop-slave.tar.gz 57 | 58 | 59 | # - name : distribute onos image 60 | # copy : 61 | # src : ~/ubuntu-onos-2.1.0.tar.gz 62 | # dest : ~/ubuntu-onos-2.1.0.tar.gz 63 | 64 | - hosts : all 65 | remote_user: root 66 | tasks : 67 | - name : create switch image 68 | command: lxc image import ~/switch.tar.gz --alias switch --public 69 | 70 | - name : create ubuntu18.04 image -- alias ubuntu 71 | command: lxc image import ~/ubuntu.tar.gz --alias ubuntu --public 72 | 73 | # - name : create debian10 image -- alias debian 74 | # command: lxc image import ~/debian.tar.gz --alias debian --public 75 | 76 | # - name : create master image 77 | # command: lxc image import ~/ubuntu-hadoop-master.tar.gz --alias ubuntu-hadoop-master --public 78 | 79 | # - name : create slave image 80 | # command: lxc image import ~/ubuntu-hadoop-slave.tar.gz --alias ubuntu-hadoop-slave --public 81 | 82 | # - name : create onos image 83 | # command: lxc image import ~/ubuntu-onos-2.1.0.tar.gz --alias ubuntu-onos-2.1.0 --public 84 | 85 | 86 | -------------------------------------------------------------------------------- /mininet/mininet/test/test_switchdpidassignment.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Package: mininet 4 | Regression tests for switch dpid assignment.""" 5 | 6 | import unittest 7 | import sys 8 | 9 | from mininet.net import Mininet 10 | from mininet.node import Host, Controller 11 | from mininet.node import ( UserSwitch, OVSSwitch, IVSSwitch ) 12 | from mininet.topo import Topo 13 | from mininet.log import setLogLevel 14 | from mininet.util import quietRun 15 | from mininet.clean import cleanup 16 | 17 | 18 | class TestSwitchDpidAssignmentOVS( unittest.TestCase ): 19 | "Verify Switch dpid assignment." 20 | 21 | switchClass = OVSSwitch # overridden in subclasses 22 | 23 | def tearDown( self ): 24 | "Clean up if necessary" 25 | # satisfy pylint 26 | assert self 27 | if sys.exc_info != ( None, None, None ): 28 | cleanup() 29 | 30 | def testDefaultDpid( self ): 31 | """Verify that the default dpid is assigned using a valid provided 32 | canonical switchname if no dpid is passed in switch creation.""" 33 | net = Mininet( Topo(), self.switchClass, Host, Controller ) 34 | switch = net.addSwitch( 's1' ) 35 | self.assertEqual( switch.defaultDpid(), switch.dpid ) 36 | net.stop() 37 | 38 | def dpidFrom( self, num ): 39 | "Compute default dpid from number" 40 | fmt = ( '%0' + str( self.switchClass.dpidLen ) + 'x' ) 41 | return fmt % num 42 | 43 | def testActualDpidAssignment( self ): 44 | """Verify that Switch dpid is the actual dpid assigned if dpid is 45 | passed in switch creation.""" 46 | dpid = self.dpidFrom( 0xABCD ) 47 | net = Mininet( Topo(), self.switchClass, Host, Controller ) 48 | switch = net.addSwitch( 's1', dpid=dpid ) 49 | self.assertEqual( switch.dpid, dpid ) 50 | net.stop() 51 | 52 | def testDefaultDpidAssignmentFailure( self ): 53 | """Verify that Default dpid assignment raises an Exception if the 54 | name of the switch does not contin a digit. Also verify the 55 | exception message.""" 56 | net = Mininet( Topo(), self.switchClass, Host, Controller ) 57 | with self.assertRaises( Exception ) as raises_cm: 58 | net.addSwitch( 'A' ) 59 | self.assertTrue( 'Unable to derive ' 60 | 'default datapath ID - please either specify a dpid ' 61 | 'or use a canonical switch name such as s23.' 62 | in str( raises_cm.exception ) ) 63 | net.stop() 64 | 65 | def testDefaultDpidLen( self ): 66 | """Verify that Default dpid length is 16 characters consisting of 67 | 16 - len(hex of first string of contiguous digits passed in switch 68 | name) 0's followed by hex of first string of contiguous digits passed 69 | in switch name.""" 70 | net = Mininet( Topo(), self.switchClass, Host, Controller ) 71 | switch = net.addSwitch( 's123' ) 72 | self.assertEqual( switch.dpid, self.dpidFrom( 123 ) ) 73 | net.stop() 74 | 75 | 76 | class OVSUser( OVSSwitch): 77 | "OVS User Switch convenience class" 78 | def __init__( self, *args, **kwargs ): 79 | kwargs.update( datapath='user' ) 80 | OVSSwitch.__init__( self, *args, **kwargs ) 81 | 82 | class testSwitchOVSUser( TestSwitchDpidAssignmentOVS ): 83 | "Test dpid assignnment of OVS User Switch." 84 | switchClass = OVSUser 85 | 86 | @unittest.skipUnless( quietRun( 'which ivs-ctl' ), 87 | 'IVS switch is not installed' ) 88 | class testSwitchIVS( TestSwitchDpidAssignmentOVS ): 89 | "Test dpid assignment of IVS switch." 90 | switchClass = IVSSwitch 91 | 92 | @unittest.skipUnless( quietRun( 'which ofprotocol' ), 93 | 'Reference user switch is not installed' ) 94 | class testSwitchUserspace( TestSwitchDpidAssignmentOVS ): 95 | "Test dpid assignment of Userspace switch." 96 | switchClass = UserSwitch 97 | 98 | if __name__ == '__main__': 99 | setLogLevel( 'warning' ) 100 | unittest.main() 101 | cleanup() 102 | -------------------------------------------------------------------------------- /mininet/mininet/test/test_nets.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Package: mininet 4 | Test creation and all-pairs ping for each included mininet topo type.""" 5 | 6 | import unittest 7 | import sys 8 | from functools import partial 9 | 10 | from mininet.net import Mininet 11 | from mininet.node import Host, Controller 12 | from mininet.node import UserSwitch, OVSSwitch, IVSSwitch 13 | from mininet.topo import SingleSwitchTopo, LinearTopo 14 | from mininet.log import setLogLevel 15 | from mininet.util import quietRun 16 | from mininet.clean import cleanup 17 | 18 | # Tell pylint not to complain about calls to other class 19 | # pylint: disable=E1101 20 | 21 | class testSingleSwitchCommon( object ): 22 | "Test ping with single switch topology (common code)." 23 | 24 | switchClass = None # overridden in subclasses 25 | 26 | @staticmethod 27 | def tearDown(): 28 | "Clean up if necessary" 29 | if sys.exc_info != ( None, None, None ): 30 | cleanup() 31 | 32 | def testMinimal( self ): 33 | "Ping test on minimal topology" 34 | mn = Mininet( SingleSwitchTopo(), self.switchClass, Host, Controller, 35 | waitConnected=True ) 36 | dropped = mn.run( mn.ping ) 37 | self.assertEqual( dropped, 0 ) 38 | 39 | def testSingle5( self ): 40 | "Ping test on 5-host single-switch topology" 41 | mn = Mininet( SingleSwitchTopo( k=5 ), self.switchClass, Host, 42 | Controller, waitConnected=True ) 43 | dropped = mn.run( mn.ping ) 44 | self.assertEqual( dropped, 0 ) 45 | 46 | # pylint: enable=E1101 47 | 48 | class testSingleSwitchOVSKernel( testSingleSwitchCommon, unittest.TestCase ): 49 | "Test ping with single switch topology (OVS kernel switch)." 50 | switchClass = OVSSwitch 51 | 52 | class testSingleSwitchOVSUser( testSingleSwitchCommon, unittest.TestCase ): 53 | "Test ping with single switch topology (OVS user switch)." 54 | switchClass = partial( OVSSwitch, datapath='user' ) 55 | 56 | @unittest.skipUnless( quietRun( 'which ivs-ctl' ), 'IVS is not installed' ) 57 | class testSingleSwitchIVS( testSingleSwitchCommon, unittest.TestCase ): 58 | "Test ping with single switch topology (IVS switch)." 59 | switchClass = IVSSwitch 60 | 61 | @unittest.skipUnless( quietRun( 'which ofprotocol' ), 62 | 'Reference user switch is not installed' ) 63 | class testSingleSwitchUserspace( testSingleSwitchCommon, unittest.TestCase ): 64 | "Test ping with single switch topology (Userspace switch)." 65 | switchClass = UserSwitch 66 | 67 | 68 | # Tell pylint not to complain about calls to other class 69 | # pylint: disable=E1101 70 | 71 | class testLinearCommon( object ): 72 | "Test all-pairs ping with LinearNet (common code)." 73 | 74 | switchClass = None # overridden in subclasses 75 | 76 | def testLinear5( self ): 77 | "Ping test on a 5-switch topology" 78 | mn = Mininet( LinearTopo( k=5 ), self.switchClass, Host, 79 | Controller, waitConnected=True ) 80 | dropped = mn.run( mn.ping ) 81 | self.assertEqual( dropped, 0 ) 82 | 83 | # pylint: enable=E1101 84 | 85 | 86 | class testLinearOVSKernel( testLinearCommon, unittest.TestCase ): 87 | "Test all-pairs ping with LinearNet (OVS kernel switch)." 88 | switchClass = OVSSwitch 89 | 90 | class testLinearOVSUser( testLinearCommon, unittest.TestCase ): 91 | "Test all-pairs ping with LinearNet (OVS user switch)." 92 | switchClass = partial( OVSSwitch, datapath='user' ) 93 | 94 | @unittest.skipUnless( quietRun( 'which ivs-ctl' ), 'IVS is not installed' ) 95 | class testLinearIVS( testLinearCommon, unittest.TestCase ): 96 | "Test all-pairs ping with LinearNet (IVS switch)." 97 | switchClass = IVSSwitch 98 | 99 | @unittest.skipUnless( quietRun( 'which ofprotocol' ), 100 | 'Reference user switch is not installed' ) 101 | class testLinearUserspace( testLinearCommon, unittest.TestCase ): 102 | "Test all-pairs ping with LinearNet (Userspace switch)." 103 | switchClass = UserSwitch 104 | 105 | 106 | if __name__ == '__main__': 107 | setLogLevel( 'warning' ) 108 | unittest.main() 109 | -------------------------------------------------------------------------------- /mininet/examples/vlanhost.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | vlanhost.py: Host subclass that uses a VLAN tag for the default interface. 4 | 5 | Dependencies: 6 | This class depends on the "vlan" package 7 | $ sudo apt-get install vlan 8 | 9 | Usage (example uses VLAN ID=1000): 10 | From the command line: 11 | sudo mn --custom vlanhost.py --host vlan,vlan=1000 12 | 13 | From a script (see exampleUsage function below): 14 | from functools import partial 15 | from vlanhost import VLANHost 16 | 17 | .... 18 | 19 | host = partial( VLANHost, vlan=1000 ) 20 | net = Mininet( host=host, ... ) 21 | 22 | Directly running this script: 23 | sudo python vlanhost.py 1000 24 | 25 | """ 26 | 27 | from mininet.node import Host 28 | from mininet.topo import Topo 29 | from mininet.util import quietRun 30 | from mininet.log import error 31 | 32 | class VLANHost( Host ): 33 | "Host connected to VLAN interface" 34 | 35 | def config( self, vlan=100, **params ): 36 | """Configure VLANHost according to (optional) parameters: 37 | vlan: VLAN ID for default interface""" 38 | 39 | r = super( VLANHost, self ).config( **params ) 40 | 41 | intf = self.defaultIntf() 42 | # remove IP from default, "physical" interface 43 | self.cmd( 'ifconfig %s inet 0' % intf ) 44 | # create VLAN interface 45 | self.cmd( 'vconfig add %s %d' % ( intf, vlan ) ) 46 | # assign the host's IP to the VLAN interface 47 | self.cmd( 'ifconfig %s.%d inet %s' % ( intf, vlan, params['ip'] ) ) 48 | # update the intf name and host's intf map 49 | newName = '%s.%d' % ( intf, vlan ) 50 | # update the (Mininet) interface to refer to VLAN interface name 51 | intf.name = newName 52 | # add VLAN interface to host's name to intf map 53 | self.nameToIntf[ newName ] = intf 54 | 55 | return r 56 | 57 | hosts = { 'vlan': VLANHost } 58 | 59 | 60 | def exampleAllHosts( vlan ): 61 | """Simple example of how VLANHost can be used in a script""" 62 | # This is where the magic happens... 63 | host = partial( VLANHost, vlan=vlan ) 64 | # vlan (type: int): VLAN ID to be used by all hosts 65 | 66 | # Start a basic network using our VLANHost 67 | topo = SingleSwitchTopo( k=2 ) 68 | net = Mininet( host=host, topo=topo ) 69 | net.start() 70 | CLI( net ) 71 | net.stop() 72 | 73 | # pylint: disable=arguments-differ 74 | 75 | class VLANStarTopo( Topo ): 76 | """Example topology that uses host in multiple VLANs 77 | 78 | The topology has a single switch. There are k VLANs with 79 | n hosts in each, all connected to the single switch. There 80 | are also n hosts that are not in any VLAN, also connected to 81 | the switch.""" 82 | 83 | def build( self, k=2, n=2, vlanBase=100 ): 84 | s1 = self.addSwitch( 's1' ) 85 | for i in range( k ): 86 | vlan = vlanBase + i 87 | for j in range(n): 88 | name = 'h%d-%d' % ( j+1, vlan ) 89 | h = self.addHost( name, cls=VLANHost, vlan=vlan ) 90 | self.addLink( h, s1 ) 91 | for j in range( n ): 92 | h = self.addHost( 'h%d' % (j+1) ) 93 | self.addLink( h, s1 ) 94 | 95 | 96 | def exampleCustomTags(): 97 | """Simple example that exercises VLANStarTopo""" 98 | 99 | net = Mininet( topo=VLANStarTopo() ) 100 | net.start() 101 | CLI( net ) 102 | net.stop() 103 | 104 | if __name__ == '__main__': 105 | import sys 106 | from functools import partial 107 | 108 | from mininet.net import Mininet 109 | from mininet.cli import CLI 110 | from mininet.topo import SingleSwitchTopo 111 | from mininet.log import setLogLevel 112 | 113 | setLogLevel( 'info' ) 114 | 115 | if not quietRun( 'which vconfig' ): 116 | error( "Cannot find command 'vconfig'\nThe package", 117 | "'vlan' is required in Ubuntu or Debian,", 118 | "or 'vconfig' in Fedora\n" ) 119 | exit() 120 | 121 | if len( sys.argv ) >= 2: 122 | exampleAllHosts( vlan=int( sys.argv[ 1 ] ) ) 123 | else: 124 | exampleCustomTags() 125 | -------------------------------------------------------------------------------- /mininet/examples/cpu.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | cpu.py: test iperf bandwidth for varying cpu limits 5 | 6 | Since we are limiting the hosts (only), we should expect the iperf 7 | processes to be affected, as well as any system processing which is 8 | billed to the hosts. 9 | 10 | We reserve >50% of cycles for system processing; we assume that 11 | this is enough for it not to affect results. Hosts are limited to 12 | 40% of total cycles, which we assume is enough to make them CPU 13 | bound. 14 | 15 | As CPU performance increases over time, we may have to reduce the 16 | overall CPU allocation so that the host processing is still CPU bound. 17 | This is perhaps an argument for specifying performance in a more 18 | system-independent manner. 19 | 20 | It would also be nice to have a better handle on limiting packet 21 | processing cycles. It's not entirely clear to me how those are 22 | billed to user or system processes if we are using OVS with a kernel 23 | datapath. With a user datapath, they are easier to account for, but 24 | overall performance is usually lower. 25 | 26 | Although the iperf client uses more CPU and should be CPU bound (?), 27 | we measure the received data at the server since the client transmit 28 | rate includes buffering. 29 | """ 30 | 31 | from mininet.net import Mininet 32 | from mininet.node import CPULimitedHost 33 | from mininet.topolib import TreeTopo 34 | from mininet.util import custom, waitListening, decode 35 | from mininet.log import setLogLevel, info 36 | from mininet.clean import cleanup 37 | 38 | def bwtest( cpuLimits, period_us=100000, seconds=10 ): 39 | """Example/test of link and CPU bandwidth limits 40 | cpu: cpu limit as fraction of overall CPU time""" 41 | 42 | topo = TreeTopo( depth=1, fanout=2 ) 43 | 44 | results = {} 45 | 46 | for sched in 'rt', 'cfs': 47 | info( '*** Testing with', sched, 'bandwidth limiting\n' ) 48 | for cpu in cpuLimits: 49 | # cpu is the cpu fraction for all hosts, so we divide 50 | # it across two hosts 51 | host = custom( CPULimitedHost, sched=sched, 52 | period_us=period_us, 53 | cpu=.5*cpu ) 54 | try: 55 | net = Mininet( topo=topo, host=host ) 56 | # pylint: disable=bare-except 57 | except: 58 | info( '*** Skipping scheduler %s and cleaning up\n' % sched ) 59 | cleanup() 60 | break 61 | net.start() 62 | net.pingAll() 63 | hosts = [ net.getNodeByName( h ) for h in topo.hosts() ] 64 | client, server = hosts[ 0 ], hosts[ -1 ] 65 | info( '*** Starting iperf with %d%% of CPU allocated to hosts\n' % 66 | ( 100.0 * cpu ) ) 67 | # We measure at the server because it doesn't include 68 | # the client's buffer fill rate 69 | popen = server.popen( 'iperf -yc -s -p 5001' ) 70 | waitListening( client, server, 5001 ) 71 | # ignore empty result from waitListening/telnet 72 | popen.stdout.readline() 73 | client.cmd( 'iperf -yc -t %s -c %s' % ( seconds, server.IP() ) ) 74 | result = decode( popen.stdout.readline() ).split( ',' ) 75 | bps = float( result[ -1 ] ) 76 | popen.terminate() 77 | net.stop() 78 | updated = results.get( sched, [] ) 79 | updated += [ ( cpu, bps ) ] 80 | results[ sched ] = updated 81 | 82 | return results 83 | 84 | 85 | def dump( results ): 86 | "Dump results" 87 | 88 | fmt = '%s\t%s\t%s\n' 89 | 90 | info( '\n' ) 91 | info( fmt % ( 'sched', 'cpu', 'received bits/sec' ) ) 92 | 93 | for sched in sorted( results.keys() ): 94 | entries = results[ sched ] 95 | for cpu, bps in entries: 96 | pct = '%d%%' % ( cpu * 100 ) 97 | mbps = '%.2e' % bps 98 | info( fmt % ( sched, pct, mbps ) ) 99 | 100 | 101 | if __name__ == '__main__': 102 | setLogLevel( 'info' ) 103 | # These are the limits for the hosts/iperfs - the 104 | # rest is for system processes 105 | limits = [ .5, .4, .3, .2, .1 ] 106 | out = bwtest( limits ) 107 | dump( out ) 108 | -------------------------------------------------------------------------------- /mininet/examples/linearbandwidth.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | Test bandwidth (using iperf) on linear networks of varying size, 5 | using both kernel and user datapaths. 6 | 7 | We construct a network of N hosts and N-1 switches, connected as follows: 8 | 9 | h1 <-> s1 <-> s2 .. sN-1 10 | | | | 11 | h2 h3 hN 12 | 13 | WARNING: by default, the reference controller only supports 16 14 | switches, so this test WILL NOT WORK unless you have recompiled 15 | your controller to support 100 switches (or more.) 16 | 17 | In addition to testing the bandwidth across varying numbers 18 | of switches, this example demonstrates: 19 | 20 | - creating a custom topology, LinearTestTopo 21 | - using the ping() and iperf() tests from Mininet() 22 | - testing both the kernel and user switches 23 | 24 | """ 25 | 26 | 27 | from mininet.net import Mininet 28 | from mininet.node import UserSwitch, OVSKernelSwitch, Controller 29 | from mininet.topo import Topo 30 | from mininet.log import lg, info 31 | from mininet.util import irange, quietRun 32 | from mininet.link import TCLink 33 | from functools import partial 34 | 35 | import sys 36 | flush = sys.stdout.flush 37 | 38 | class LinearTestTopo( Topo ): 39 | "Topology for a string of N hosts and N-1 switches." 40 | 41 | def build( self, N, **params ): 42 | # Create switches and hosts 43 | hosts = [ self.addHost( 'h%s' % h ) 44 | for h in irange( 1, N ) ] 45 | switches = [ self.addSwitch( 's%s' % s ) 46 | for s in irange( 1, N - 1 ) ] 47 | 48 | # Wire up switches 49 | last = None 50 | for switch in switches: 51 | if last: 52 | self.addLink( last, switch ) 53 | last = switch 54 | 55 | # Wire up hosts 56 | self.addLink( hosts[ 0 ], switches[ 0 ] ) 57 | for host, switch in zip( hosts[ 1: ], switches ): 58 | self.addLink( host, switch ) 59 | 60 | 61 | def linearBandwidthTest( lengths ): 62 | 63 | "Check bandwidth at various lengths along a switch chain." 64 | 65 | results = {} 66 | switchCount = max( lengths ) 67 | hostCount = switchCount + 1 68 | 69 | switches = { 'reference user': UserSwitch, 70 | 'Open vSwitch kernel': OVSKernelSwitch } 71 | 72 | # UserSwitch is horribly slow with recent kernels. 73 | # We can reinstate it once its performance is fixed 74 | del switches[ 'reference user' ] 75 | 76 | topo = LinearTestTopo( hostCount ) 77 | 78 | # Select TCP Reno 79 | output = quietRun( 'sysctl -w net.ipv4.tcp_congestion_control=reno' ) 80 | assert 'reno' in output 81 | 82 | for datapath in switches.keys(): 83 | info( "*** testing", datapath, "datapath\n" ) 84 | Switch = switches[ datapath ] 85 | results[ datapath ] = [] 86 | link = partial( TCLink, delay='2ms', bw=10 ) 87 | net = Mininet( topo=topo, switch=Switch, 88 | controller=Controller, waitConnected=True, 89 | link=link ) 90 | net.start() 91 | info( "*** testing basic connectivity\n" ) 92 | for n in lengths: 93 | net.ping( [ net.hosts[ 0 ], net.hosts[ n ] ] ) 94 | info( "*** testing bandwidth\n" ) 95 | for n in lengths: 96 | src, dst = net.hosts[ 0 ], net.hosts[ n ] 97 | # Try to prime the pump to reduce PACKET_INs during test 98 | # since the reference controller is reactive 99 | src.cmd( 'telnet', dst.IP(), '5001' ) 100 | info( "testing", src.name, "<->", dst.name, '\n' ) 101 | # serverbw = received; _clientbw = buffered 102 | serverbw, _clientbw = net.iperf( [ src, dst ], seconds=10 ) 103 | info( serverbw, '\n' ) 104 | flush() 105 | results[ datapath ] += [ ( n, serverbw ) ] 106 | net.stop() 107 | 108 | for datapath in switches.keys(): 109 | info( "\n*** Linear network results for", datapath, "datapath:\n" ) 110 | result = results[ datapath ] 111 | info( "SwitchCount\tiperf Results\n" ) 112 | for switchCount, serverbw in result: 113 | info( switchCount, '\t\t' ) 114 | info( serverbw, '\n' ) 115 | info( '\n') 116 | info( '\n' ) 117 | 118 | if __name__ == '__main__': 119 | lg.setLogLevel( 'info' ) 120 | sizes = [ 1, 10, 20, 40, 60, 80 ] 121 | info( "*** Running linearBandwidthTest", sizes, '\n' ) 122 | linearBandwidthTest( sizes ) 123 | -------------------------------------------------------------------------------- /mininet/examples/clustercli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | "CLI for Mininet Cluster Edition prototype demo" 4 | 5 | from mininet.cli import CLI 6 | from mininet.log import output, error 7 | 8 | # pylint: disable=global-statement 9 | nx, graphviz_layout, plt = None, None, None # Will be imported on demand 10 | 11 | 12 | class ClusterCLI( CLI ): 13 | "CLI with additional commands for Cluster Edition demo" 14 | 15 | @staticmethod 16 | def colorsFor( seq ): 17 | "Return a list of background colors for a sequence" 18 | colors = [ 'red', 'lightgreen', 'cyan', 'yellow', 'orange', 19 | 'magenta', 'pink', 'grey', 'brown', 20 | 'white' ] 21 | slen, clen = len( seq ), len( colors ) 22 | reps = max( 1, slen / clen ) 23 | colors = colors * reps 24 | colors = colors[ 0 : slen ] 25 | return colors 26 | 27 | def do_plot( self, _line ): 28 | "Plot topology colored by node placement" 29 | # Import networkx if needed 30 | global nx, plt, graphviz_layout 31 | if not nx: 32 | try: 33 | # pylint: disable=import-error,no-member 34 | import networkx 35 | nx = networkx # satisfy pylint 36 | from matplotlib import pyplot 37 | plt = pyplot # satisfy pylint 38 | import pygraphviz 39 | assert pygraphviz # silence pyflakes 40 | # Networkx moved this around 41 | if hasattr( nx, 'graphviz_layout' ): 42 | graphviz_layout = nx.graphviz_layout 43 | else: 44 | graphviz_layout = nx.drawing.nx_agraph.graphviz_layout 45 | # pylint: enable=import-error,no-member 46 | except ImportError: 47 | error( 'plot requires networkx, matplotlib and pygraphviz - ' 48 | 'please install them and try again\n' ) 49 | return 50 | # Make a networkx Graph 51 | g = nx.Graph() 52 | mn = self.mn 53 | servers = getattr( mn, 'servers', [ 'localhost' ] ) 54 | hosts, switches = mn.hosts, mn.switches 55 | nodes = hosts + switches 56 | g.add_nodes_from( nodes ) 57 | links = [ ( link.intf1.node, link.intf2.node ) 58 | for link in self.mn.links ] 59 | g.add_edges_from( links ) 60 | # Pick some shapes and colors 61 | # shapes = hlen * [ 's' ] + slen * [ 'o' ] 62 | color = dict( zip( servers, self.colorsFor( servers ) ) ) 63 | # Plot it! 64 | pos = graphviz_layout( g ) 65 | opts = { 'ax': None, 'font_weight': 'bold', 66 | 'width': 2, 'edge_color': 'darkblue' } 67 | hcolors = [ color[ getattr( h, 'server', 'localhost' ) ] 68 | for h in hosts ] 69 | scolors = [ color[ getattr( s, 'server', 'localhost' ) ] 70 | for s in switches ] 71 | nx.draw_networkx( g, pos=pos, nodelist=hosts, node_size=800, 72 | label='host', node_color=hcolors, node_shape='s', 73 | **opts ) 74 | nx.draw_networkx( g, pos=pos, nodelist=switches, node_size=1000, 75 | node_color=scolors, node_shape='o', **opts ) 76 | # Get rid of axes, add title, and show 77 | fig = plt.gcf() 78 | ax = plt.gca() 79 | ax.get_xaxis().set_visible( False ) 80 | ax.get_yaxis().set_visible( False ) 81 | fig.canvas.set_window_title( 'Mininet') 82 | plt.title( 'Node Placement', fontweight='bold' ) 83 | plt.show() 84 | 85 | def do_status( self, _line ): 86 | "Report on node shell status" 87 | nodes = self.mn.hosts + self.mn.switches 88 | for node in nodes: 89 | node.shell.poll() 90 | exited = [ node for node in nodes 91 | if node.shell.returncode is not None ] 92 | if exited: 93 | for node in exited: 94 | output( '%s has exited with code %d\n' 95 | % ( node, node.shell.returncode ) ) 96 | else: 97 | output( 'All nodes are still running.\n' ) 98 | 99 | def do_placement( self, _line ): 100 | "Describe node placement" 101 | mn = self.mn 102 | nodes = mn.hosts + mn.switches + mn.controllers 103 | for server in mn.servers: 104 | names = [ n.name for n in nodes if hasattr( n, 'server' ) 105 | and n.server == server ] 106 | output( '%s: %s\n' % ( server, ' '.join( names ) ) ) 107 | -------------------------------------------------------------------------------- /mininet/custom/hadoop_test.py: -------------------------------------------------------------------------------- 1 | from mininet.topodc import (toHadoop, getHadoopMaster) 2 | import time 3 | from mininet.dutil import makeFile, makeHosts, default_images 4 | from mininet.log import info, debug, warn, error, output 5 | 6 | def aliasMaster(topo, net): 7 | master = getHadoopMaster(topo) 8 | output ("The Hadoop master is {}\n".format(master)) 9 | 10 | lines = [] 11 | line = "{} {}".format(net.nameToNode[master].IP(), "master") 12 | lines.append(line) 13 | for host in topo.hosts(): 14 | lines.append("{} {}".format(net.nameToNode[host].IP(), host)) 15 | # output (" >>> {}\n".format(lines)) 16 | for host in topo.hosts(): 17 | # output ("\t Adding to host {}".format(lines)) 18 | makeFile(net=net, host=host, lines=lines, filename="/etc/hosts", overwrite=False) 19 | 20 | def makeMasters(topo, net): 21 | """Generate the etc/hadoop/masters file on all the masters 22 | """ 23 | masters = list() 24 | 25 | for host in topo.hosts(): 26 | if "role" in topo.nodeInfo(host).keys() and topo.nodeInfo(host)["role"] == "master": 27 | masters.append(host) 28 | 29 | # Execute the command to build etc/hadoop/masters on each master 30 | for master in masters: 31 | makeFile(net, master, masters, "/root/hadoop-2.7.6/etc/hadoop/masters", overwrite=False) 32 | 33 | def makeSlaves(topo, net): 34 | """ Generate the etc/hadoop/slaves file on all hosts 35 | """ 36 | cluster = list() 37 | slaves = list() 38 | 39 | hosts = topo.hosts() 40 | for host in hosts: 41 | if "role" in topo.nodeInfo(host).keys(): 42 | if topo.nodeInfo(host)["role"] == "slave": 43 | slaves.append(host) 44 | cluster.append(host) 45 | elif topo.nodeInfo(host)["role"] == "master": 46 | cluster.append(host) 47 | 48 | # Execute the command to build etc/hadoop/slaves on each host 49 | for host in cluster: 50 | makeFile(net, host, slaves, "/root/hadoop-2.7.6/etc/hadoop/slaves", overwrite=False) 51 | 52 | def hadoop_test(mn): 53 | topo = mn.topo 54 | aliasMaster(topo=topo, net=mn) 55 | output ("# populate etc/hadoop/masters\n") 56 | makeMasters(topo=topo, net=mn) 57 | 58 | output 59 | output ("# populate etc/hadoop/slaves\n") 60 | makeSlaves(topo=topo, net=mn) 61 | 62 | hm = getHadoopMaster(topo) 63 | hadoopMasterNode = mn.nameToNode[hm] 64 | 65 | output ("# Start Hadoop in the cluster\n") 66 | output ("# Format HDFS\n") 67 | output (hadoopMasterNode.cmd('bash -c "/root/hadoop-2.7.6/bin/hdfs namenode -format -force"')) 68 | 69 | output ("# Launch HDFS\n") 70 | output (hadoopMasterNode.cmd('bash -c "/root/hadoop-2.7.6/sbin/start-dfs.sh"')) 71 | 72 | output ("# Launch YARN\n") 73 | output (hadoopMasterNode.cmd('bash -c "/root/hadoop-2.7.6/sbin/start-yarn.sh"')) 74 | 75 | output ("# Create a directory for the user\n") 76 | output (hadoopMasterNode.cmd('bash -c "/root/hadoop-2.7.6/bin/hdfs dfs -mkdir -p /user/root"')) 77 | time.sleep(2) 78 | 79 | output ("\n") 80 | output ("# Compute PI\n") 81 | output (hadoopMasterNode.cmd('bash -c "/root/hadoop-2.7.6/bin/hadoop jar /root/hadoop-2.7.6/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.6.jar pi 20 100"')) 82 | 83 | output ("\n") 84 | output ("# Teragen\n") 85 | output (hadoopMasterNode.cmd('bash -c "/root/hadoop-2.7.6/bin/hadoop jar /root/hadoop-2.7.6/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.6.jar teragen 1000000 bench.tera"')) 86 | output ("# Terasort\n") 87 | output (hadoopMasterNode.cmd('bash -c "/root/hadoop-2.7.6/bin/hadoop jar /root/hadoop-2.7.6/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.6.jar terasort bench.tera bench.tera.out"')) 88 | output ("# Teravalidate\n") 89 | output (hadoopMasterNode.cmd('bash -c "/root/hadoop-2.7.6/bin/hadoop jar /root/hadoop-2.7.6/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.6.jar teravalidate bench.tera.out bench.tera.validate"')) 90 | 91 | 92 | output ("\n") 93 | output ("# Wordcount\n") 94 | output (hadoopMasterNode.cmd('bash -c "/root/hadoop-2.7.6/bin/hadoop dfs -mkdir bench.wordcount"')) 95 | output (hadoopMasterNode.cmd('bash -c "/root/hadoop-2.7.6/bin/hadoop dfs -copyFromLocal /etc/hosts bench.wordcount/hosts"')) 96 | output (hadoopMasterNode.cmd('bash -c "/root/hadoop-2.7.6/bin/hadoop jar /root/hadoop-2.7.6/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.6.jar wordcount bench.wordcount/hosts bench.wordcount bench.wordcount.out"')) 97 | output ("\n") 98 | 99 | # we need the right images to run hadoop 100 | PREBUILD = [default_images, toHadoop] 101 | 102 | # adding the test in the suite 103 | TESTS = {'hadoop':hadoop_test} 104 | -------------------------------------------------------------------------------- /mininet/examples/mobility.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | Simple example of Mobility with Mininet 5 | (aka enough rope to hang yourself.) 6 | 7 | We move a host from s1 to s2, s2 to s3, and then back to s1. 8 | 9 | Gotchas: 10 | 11 | The reference controller doesn't support mobility, so we need to 12 | manually flush the switch flow tables! 13 | 14 | Good luck! 15 | 16 | to-do: 17 | 18 | - think about wifi/hub behavior 19 | - think about clearing last hop - why doesn't that work? 20 | """ 21 | 22 | 23 | from mininet.net import Mininet 24 | from mininet.node import OVSSwitch 25 | from mininet.topo import LinearTopo 26 | from mininet.log import info, output, warn, setLogLevel 27 | 28 | from random import randint 29 | 30 | 31 | class MobilitySwitch( OVSSwitch ): 32 | "Switch that can reattach and rename interfaces" 33 | 34 | def delIntf( self, intf ): 35 | "Remove (and detach) an interface" 36 | port = self.ports[ intf ] 37 | del self.ports[ intf ] 38 | del self.intfs[ port ] 39 | del self.nameToIntf[ intf.name ] 40 | 41 | def addIntf( self, intf, rename=False, **kwargs ): 42 | "Add (and reparent) an interface" 43 | OVSSwitch.addIntf( self, intf, **kwargs ) 44 | intf.node = self 45 | if rename: 46 | self.renameIntf( intf ) 47 | 48 | def attach( self, intf ): 49 | "Attach an interface and set its port" 50 | port = self.ports[ intf ] 51 | if port: 52 | if self.isOldOVS(): 53 | self.cmd( 'ovs-vsctl add-port', self, intf ) 54 | else: 55 | self.cmd( 'ovs-vsctl add-port', self, intf, 56 | '-- set Interface', intf, 57 | 'ofport_request=%s' % port ) 58 | self.validatePort( intf ) 59 | 60 | def validatePort( self, intf ): 61 | "Validate intf's OF port number" 62 | ofport = int( self.cmd( 'ovs-vsctl get Interface', intf, 63 | 'ofport' ) ) 64 | if ofport != self.ports[ intf ]: 65 | warn( 'WARNING: ofport for', intf, 'is actually', ofport, 66 | '\n' ) 67 | 68 | def renameIntf( self, intf, newname='' ): 69 | "Rename an interface (to its canonical name)" 70 | intf.ifconfig( 'down' ) 71 | if not newname: 72 | newname = '%s-eth%d' % ( self.name, self.ports[ intf ] ) 73 | intf.cmd( 'ip link set', intf, 'name', newname ) 74 | del self.nameToIntf[ intf.name ] 75 | intf.name = newname 76 | self.nameToIntf[ intf.name ] = intf 77 | intf.ifconfig( 'up' ) 78 | 79 | def moveIntf( self, intf, switch, port=None, rename=True ): 80 | "Move one of our interfaces to another switch" 81 | self.detach( intf ) 82 | self.delIntf( intf ) 83 | switch.addIntf( intf, port=port, rename=rename ) 84 | switch.attach( intf ) 85 | 86 | 87 | def printConnections( switches ): 88 | "Compactly print connected nodes to each switch" 89 | for sw in switches: 90 | output( '%s: ' % sw ) 91 | for intf in sw.intfList(): 92 | link = intf.link 93 | if link: 94 | intf1, intf2 = link.intf1, link.intf2 95 | remote = intf1 if intf1.node != sw else intf2 96 | output( '%s(%s) ' % ( remote.node, sw.ports[ intf ] ) ) 97 | output( '\n' ) 98 | 99 | 100 | def moveHost( host, oldSwitch, newSwitch, newPort=None ): 101 | "Move a host from old switch to new switch" 102 | hintf, sintf = host.connectionsTo( oldSwitch )[ 0 ] 103 | oldSwitch.moveIntf( sintf, newSwitch, port=newPort ) 104 | return hintf, sintf 105 | 106 | 107 | def mobilityTest(): 108 | "A simple test of mobility" 109 | info( '* Simple mobility test\n' ) 110 | net = Mininet( topo=LinearTopo( 3 ), switch=MobilitySwitch ) 111 | info( '* Starting network:\n' ) 112 | net.start() 113 | printConnections( net.switches ) 114 | info( '* Testing network\n' ) 115 | net.pingAll() 116 | info( '* Identifying switch interface for h1\n' ) 117 | h1, old = net.get( 'h1', 's1' ) 118 | for s in 2, 3, 1: 119 | new = net[ 's%d' % s ] 120 | port = randint( 10, 20 ) 121 | info( '* Moving', h1, 'from', old, 'to', new, 'port', port, '\n' ) 122 | hintf, sintf = moveHost( h1, old, new, newPort=port ) 123 | info( '*', hintf, 'is now connected to', sintf, '\n' ) 124 | info( '* Clearing out old flows\n' ) 125 | for sw in net.switches: 126 | sw.dpctl( 'del-flows' ) 127 | info( '* New network:\n' ) 128 | printConnections( net.switches ) 129 | info( '* Testing connectivity:\n' ) 130 | net.pingAll() 131 | old = new 132 | net.stop() 133 | 134 | if __name__ == '__main__': 135 | setLogLevel( 'info' ) 136 | mobilityTest() 137 | --------------------------------------------------------------------------------