├── .dockerignore ├── .gitattributes ├── .gitignore ├── .pylint ├── CONTRIBUTORS ├── Dockerfile ├── Dockerfile.centos ├── INSTALL ├── LICENSE ├── Makefile ├── P4_examples ├── P4-XDP_example │ ├── README.md │ ├── ebpf_example_topology.py │ ├── p4src │ │ ├── Makefile │ │ ├── ebpf_xdp.h │ │ └── program.p4 │ └── program.o ├── README.md ├── eINT │ ├── README.md │ ├── commands_INT_s1.txt │ ├── commands_INT_s2.txt │ ├── commands_INT_s3.txt │ ├── commands_INT_s4.txt │ ├── doc │ │ ├── UC3_1.png │ │ ├── UC3_1.xml │ │ ├── UC3_2.png │ │ └── UC_2.xml │ ├── eint_topology.py │ ├── int-vnf │ │ ├── Dockerfile │ │ ├── Readme │ │ ├── build.sh │ │ ├── gen_packet_test_int.py │ │ ├── int_header.py │ │ ├── sniff.py │ │ └── start.sh │ ├── int.json │ └── p4src │ │ ├── Makefile │ │ ├── include │ │ ├── actions.p4 │ │ ├── checksums.p4 │ │ ├── defines.p4 │ │ ├── headers.p4 │ │ ├── int_definitions.p4 │ │ ├── int_headers.p4 │ │ ├── int_parser.p4 │ │ ├── int_report.p4 │ │ ├── int_sink.p4 │ │ ├── int_source.p4 │ │ ├── int_transit.p4 │ │ ├── packet_io.p4 │ │ ├── port_counters.p4 │ │ ├── table0.p4 │ │ └── telemetry_report_headers.p4 │ │ ├── int.p4 │ │ └── p4c-out │ │ └── bmv2 │ │ ├── int.json │ │ └── int_p4info.txt ├── load_balancer_RR │ ├── Makefile │ ├── command.txt │ ├── load_balancer_RR.p4 │ └── load_balancer_RR_p4.py └── load_balancer_hash │ ├── Makefile │ ├── command.txt │ ├── load_balancer_hash.p4 │ └── load_balancer_hash_p4.py ├── README.md ├── StandaloneVagrantfile ├── Vagrantfile ├── ansible ├── install.yml ├── install_centos.yml └── install_vagrant.yml ├── bin ├── clear_crash.sh └── mn ├── doc └── doxygen.cfg ├── examples ├── README.md ├── __init__.py ├── baresshd.py ├── bind.py ├── cluster.py ├── clusterSanity.py ├── clustercli.py ├── clusterdemo.py ├── clusterperf.py ├── consoles.py ├── containernet_container_test.py ├── containernet_example.py ├── containernet_example_cmd_field.py ├── containernet_example_ipc.py ├── containernet_example_server_curl.py ├── containernet_topology_example.py ├── containernet_volume_example.py ├── controllers.py ├── controllers2.py ├── controlnet.py ├── cpu.py ├── docker_cpuset.py ├── dockerhosts.py ├── emptynet.py ├── example-containers │ ├── Dockerfile.HAProxy │ ├── Dockerfile.alpine3 │ ├── Dockerfile.centos6 │ ├── Dockerfile.centos7 │ ├── Dockerfile.curl │ ├── Dockerfile.iperf │ ├── Dockerfile.lamp │ ├── Dockerfile.p4bmv2 │ ├── Dockerfile.ubuntu1404 │ ├── Dockerfile.ubuntu1604 │ ├── Dockerfile.ubuntu1804 │ ├── Dockerfile.ubuntu_p4 │ ├── build.sh │ ├── haproxy.cfg │ ├── haproxy.sh │ ├── index.php │ ├── installP4BMv2.sh │ ├── lamp.sh │ ├── runBMv2.sh │ └── webserver_curl │ │ ├── Dockerfile.server │ │ ├── app.py │ │ └── requirements.txt ├── hwintf.py ├── intfoptions.py ├── limit.py ├── linearbandwidth.py ├── linuxrouter.py ├── miniedit.py ├── mobility.py ├── multilink.py ├── multiping.py ├── multipoll.py ├── multitest.py ├── nat.py ├── natnet.py ├── numberedports.py ├── popen.py ├── popenpoll.py ├── scratchnet.py ├── scratchnetuser.py ├── simpleperf.py ├── sshd.py ├── test │ ├── runner.py │ ├── test_baresshd.py │ ├── test_bind.py │ ├── test_clusterSanity.py │ ├── test_controllers.py │ ├── test_controlnet.py │ ├── test_cpu.py │ ├── test_emptynet.py │ ├── test_hwintf.py │ ├── test_intfoptions.py │ ├── test_limit.py │ ├── test_linearbandwidth.py │ ├── test_linuxrouter.py │ ├── test_mobility.py │ ├── test_multilink.py │ ├── test_multiping.py │ ├── test_multipoll.py │ ├── test_multitest.py │ ├── test_nat.py │ ├── test_natnet.py │ ├── test_numberedports.py │ ├── test_popen.py │ ├── test_scratchnet.py │ ├── test_simpleperf.py │ ├── test_sshd.py │ ├── test_tree1024.py │ ├── test_treeping64.py │ └── test_vlanhost.py ├── tree1024.py ├── treeping64.py └── vlanhost.py ├── mininet ├── __init__.py ├── bmv2.py ├── clean.py ├── cli.py ├── ebpf.py ├── examples ├── link.py ├── log.py ├── moduledeps.py ├── net.py ├── node.py ├── nodelib.py ├── term.py ├── test │ └── test_containernet.py ├── topo.py ├── topolib.py └── util.py ├── mnexec.c ├── setup.py └── util ├── build-ovs-packages.sh ├── clustersetup.sh ├── colorfilters ├── docker ├── entrypoint.sh └── entrypoint_centos.sh ├── doxify.py ├── install-p4-dependencies.sh ├── install-p4c-xdp.sh ├── install.sh ├── kbuild ├── kbuild ├── tun.patch └── version_vars.patch ├── m ├── motd ├── nox-patches ├── 0001-OpenFlow-tutorial-port-nox-destiny.patch ├── 0002-nox-ubuntu12-hacks.patch └── README ├── openflow-patches ├── README ├── controller.patch └── datapath.patch ├── sch_htb-ofbuf ├── Makefile ├── README └── sch_htb.c ├── sysctl_addon ├── unpep8 ├── versioncheck.py └── vm ├── .bash_profile ├── build.py └── install-mininet-vm.sh /.dockerignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | **/*.pyc 3 | **/__pycache__ 4 | 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.py diff=python 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | venv/ 2 | venv3/ 3 | mnexec 4 | .cache/ 5 | *.log 6 | *.pyc 7 | *~ 8 | *.1 9 | *.xcodeproj 10 | *.xcworkspace 11 | \#*\# 12 | mininet.egg-info 13 | build 14 | dist 15 | doc/html 16 | doc/latex 17 | trunk 18 | .vagrant/ 19 | .idea 20 | -------------------------------------------------------------------------------- /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 | 54 | 55 | 56 | Containernet Contributors 57 | 58 | Containernet is a fork of Mininet that allows to use Docker containers 59 | as Mininet hosts. We thank all Mininet contributors for providing this great 60 | open source platform! 61 | 62 | Containernet contributors include: 63 | 64 | Manuel Peuster 65 | Steven Van Rossem 66 | Malte Splietker 67 | Dennis Sehring 68 | Johannes Kampmeyer 69 | Marco De Benedictis 70 | Erik Schilling 71 | Zohar Lorberbaum 72 | Ramon Fontes 73 | Rafael Schellenberg 74 | Dimitrios (@digiou) 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:bionic 2 | LABEL maintainer="manuel@peuster.de" 3 | 4 | # install required packages 5 | RUN apt-get clean 6 | RUN apt-get update \ 7 | && apt-get install -y git \ 8 | net-tools \ 9 | aptitude \ 10 | build-essential \ 11 | python3-setuptools \ 12 | python3-dev \ 13 | python3-pip \ 14 | software-properties-common \ 15 | ansible \ 16 | curl \ 17 | iptables \ 18 | iputils-ping \ 19 | sudo 20 | 21 | # install containernet (using its Ansible playbook) 22 | COPY . /containernet 23 | WORKDIR /containernet/ansible 24 | RUN ansible-playbook -i "localhost," -c local --skip-tags "notindocker" install.yml 25 | WORKDIR /containernet 26 | RUN make develop 27 | 28 | # Hotfix: https://github.com/pytest-dev/pytest/issues/4770 29 | RUN pip3 install "more-itertools<=5.0.0" 30 | 31 | # tell containernet that it runs in a container 32 | ENV CONTAINERNET_NESTED 1 33 | 34 | # Important: This entrypoint is required to start the OVS service 35 | ENTRYPOINT ["util/docker/entrypoint.sh"] 36 | CMD ["python3", "examples/containernet_example.py"] 37 | 38 | -------------------------------------------------------------------------------- /Dockerfile.centos: -------------------------------------------------------------------------------- 1 | FROM centos:7 2 | 3 | # install required packages 4 | RUN yum install -y epel-release \ 5 | && yum update -y \ 6 | && yum install -y ansible 7 | 8 | # install containernet (using its Ansible playbook) 9 | COPY . /containernet 10 | WORKDIR /containernet/ansible 11 | RUN ansible-playbook -i "localhost," -c local --skip-tags "notindocker" install_centos.yml 12 | WORKDIR /containernet 13 | RUN python3 setup.py develop 14 | 15 | # Hotfix: https://github.com/pytest-dev/pytest/issues/4770 16 | RUN pip3 install "more-itertools<=5.0.0" 17 | 18 | # tell containernet that it runs in a container 19 | ENV CONTAINERNET_NESTED 1 20 | 21 | # Important: This entrypoint is required to start the Docker and OVS service 22 | ENTRYPOINT ["util/docker/entrypoint_centos.sh"] 23 | CMD ["python3", "examples/containernet_example.py"] 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mininet 2.3.0d1 License 2 | 3 | Copyright (c) 2013-2016 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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MININET = mininet/*.py 2 | TEST = mininet/test/*.py 3 | EXAMPLES = mininet/examples/*.py 4 | MN = bin/mn 5 | PYTHON ?= python3 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: test 21 | 22 | clean: 23 | rm -rf build dist *.egg-info *.pyc $(MNEXEC) $(MANPAGES) $(DOCDIRS) 24 | 25 | test: $(MININET) $(TEST) 26 | -echo "Running tests" 27 | py.test -v mininet/test/test_containernet.py 28 | 29 | mnexec: mnexec.c $(MN) mininet/net.py 30 | cc $(CFLAGS) $(LDFLAGS) -DVERSION=\"`PYTHONPATH=. $(PYMN) --version`\" $< -o $@ 31 | 32 | install-mnexec: $(MNEXEC) 33 | install -D $(MNEXEC) $(BINDIR)/$(MNEXEC) 34 | 35 | install-manpages: $(MANPAGES) 36 | install -D -t $(MANDIR) $(MANPAGES) 37 | 38 | install: install-mnexec install-manpages 39 | $(PYTHON) setup.py install 40 | 41 | develop: $(MNEXEC) $(MANPAGES) 42 | # Perhaps we should link these as well 43 | install $(MNEXEC) $(BINDIR) 44 | install $(MANPAGES) $(MANDIR) 45 | $(PYTHON) setup.py develop 46 | 47 | man: $(MANPAGES) 48 | 49 | mn.1: $(MN) 50 | PYTHONPATH=. help2man -N -n "create a Mininet network." \ 51 | --no-discard-stderr "$(PYMN)" -o $@ 52 | 53 | mnexec.1: mnexec 54 | help2man -N -n "execution utility for Mininet." \ 55 | -h "-h" -v "-v" --no-discard-stderr ./$< -o $@ 56 | 57 | .PHONY: doc 58 | 59 | doc: man 60 | doxygen doc/doxygen.cfg 61 | make -C doc/latex 62 | -------------------------------------------------------------------------------- /P4_examples/P4-XDP_example/README.md: -------------------------------------------------------------------------------- 1 | # P4-XDP on P4-Containernet 2 | 3 | ## Installation 4 | ### Manual installation 5 | Follow instruction from [here](https://github.com/vmware/p4c-xdp) to install the P4_16-XDP compiler. 6 | Then set the environment variable `$P4C` to the path of the P4 compiler folder (usually `~/p4c/`). 7 | 8 | ### Automatic installation 9 | Alternatively, you can install the compiler by executing the script `FOP4/util/install-p4c-xdp.sh`. 10 | The script will add necessary environment variables to your bash profile file. 11 | To load them without rebooting, run `source ~/.profile` 12 | 13 | ## Compile P4 program for eBPF-XDP target (p4c-xdp) 14 | You can compile the P4 program to the eBPF-XDP target running the following commands. First copy the `ebpf_xdp.h` 15 | ```bash 16 | cp ${P4C}/extensions/p4c-xdp/tests/ebpf_xdp.h . 17 | p4c-xdp --target xdp -o PROGRAM_NAME.c PROGRAM_NAME.p4 18 | clang -I ${P4C}/extensions/p4c-xdp/p4include -I${P4C}/backends/ebpf/runtime/ -I${P4C}/backends/ebpf/runtime/usr/include/bpf \ 19 | -Wno-unused-value -Wno-pointer-sign \ 20 | -Wno-compare-distinct-pointer-types \ 21 | -Wno-gnu-variable-sized-type-not-at-end \ 22 | -Wno-tautological-compare \ 23 | -O2 -emit-llvm -g -c PROGRAM_NAME.c -o -| llc -march=bpf -filetype=obj -o PROGRAM_NAME.o 24 | ``` 25 | ## How to use a compiled eBPF-XDP program in P4-Containernet 26 | 27 | To use the previously compiled program you should add an eBFP enabled host to your topology (`EbpfXdpNode`). Then, when you create a link from that host, you can specify which compiled eBFP-XDP program has to be loaded to the interface. 28 | 29 | 30 | Here is an example: 31 | ```python 32 | net = Containernet() 33 | h = net.addEbpfHost('h1') 34 | s = net.addSwitch('s1') 35 | net.addLink(h, s, ebpfProgram1="./PROGRAM_NAME.o") 36 | # or net.addLink(s, h, ebpfProgram2="./PROGRAM_NAME.o") 37 | 38 | ``` 39 | The interface accept any eBPF-XDP program, not only the ones obtained with the **p4c-xdp** compiler. -------------------------------------------------------------------------------- /P4_examples/P4-XDP_example/ebpf_example_topology.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from mininet.net import Containernet 3 | from mininet.cli import CLI 4 | from mininet.log import info, setLogLevel 5 | setLogLevel('info') 6 | 7 | net = Containernet() 8 | 9 | info('*** Adding Controller\n') 10 | c = net.addController() 11 | 12 | info('*** Adding Hosts\n') 13 | 14 | # HOST 15 | h1 = net.addHost('h1') 16 | h2 = net.addEbpfHost('h2') 17 | 18 | info('*** Adding switches\n') 19 | 20 | s1 = net.addSwitch('s1') 21 | 22 | info('*** Creating links\n') 23 | net.addLink(h1, s1) 24 | net.addLink(h2, s1, ebpfProgram1="./program.o") 25 | info('*** Starting network\n') 26 | 27 | net.start() 28 | net.staticArp() 29 | 30 | info('*** Running CLI\n') 31 | CLI(net) 32 | info('*** Stopping network') 33 | net.stop() 34 | -------------------------------------------------------------------------------- /P4_examples/P4-XDP_example/p4src/Makefile: -------------------------------------------------------------------------------- 1 | all: program 2 | 3 | program: program.p4 4 | p4c-xdp --target xdp -o program.c program.p4 5 | clang -I ${P4C}/extensions/p4c-xdp/p4include -I${P4C}/backends/ebpf/runtime/ -I${P4C}/backends/ebpf/runtime/usr/include/bpf \ 6 | -Wno-unused-value -Wno-pointer-sign \ 7 | -Wno-compare-distinct-pointer-types \ 8 | -Wno-gnu-variable-sized-type-not-at-end \ 9 | -Wno-tautological-compare \ 10 | -O2 -emit-llvm -g -c program.c -o -| llc -march=bpf -filetype=obj -o program.o 11 | -------------------------------------------------------------------------------- /P4_examples/P4-XDP_example/p4src/ebpf_xdp.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 VMware, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | * This file contains all functions and definitions necessary for the xdp target C code to compile. It must be included with any file generated by the p4c-xdp compiler. 19 | */ 20 | 21 | #ifndef __BPF_HELPERS_H 22 | #define __BPF_HELPERS_H 23 | 24 | #include "ebpf_kernel.h" 25 | 26 | /* xdp descriptor similar to sk_buff */ 27 | #ifdef SK_BUFF 28 | #undef SK_BUFF 29 | #endif 30 | #define SK_BUFF struct xdp_md 31 | 32 | #ifdef load_dword 33 | #undef load_dword 34 | #endif 35 | 36 | #define load_dword(data, b) (*(u64 *)((u8*)(data) + (b))) << 16 37 | 38 | 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /P4_examples/P4-XDP_example/p4src/program.p4: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 VMWare, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include "xdp_model.p4" 18 | 19 | header Ethernet { 20 | bit<48> destination; 21 | bit<48> source; 22 | bit<16> protocol; 23 | } 24 | 25 | header IPv4 { 26 | bit<4> version; 27 | bit<4> ihl; 28 | bit<8> diffserv; 29 | bit<16> totalLen; 30 | bit<16> identification; 31 | bit<3> flags; 32 | bit<13> fragOffset; 33 | bit<8> ttl; 34 | bit<8> protocol; 35 | bit<16> hdrChecksum; 36 | bit<32> srcAddr; 37 | bit<32> dstAddr; 38 | } 39 | 40 | struct Headers { 41 | Ethernet ethernet; 42 | IPv4 ipv4; 43 | } 44 | 45 | parser Parser(packet_in packet, out Headers hd) { 46 | state start { 47 | packet.extract(hd.ethernet); 48 | transition select(hd.ethernet.protocol) { 49 | 16w0x800: parse_ipv4; 50 | default: accept; 51 | } 52 | } 53 | 54 | state parse_ipv4 { 55 | packet.extract(hd.ipv4); 56 | transition accept; 57 | } 58 | } 59 | 60 | control Ingress(inout Headers hdr, in xdp_input xin, out xdp_output xout) { 61 | apply { 62 | xout.output_port = 0; 63 | xout.output_action = (hdr.ethernet.protocol != 0x800) ? xdp_action.XDP_DROP : xdp_action.XDP_PASS; 64 | } 65 | } 66 | 67 | control Deparser(in Headers hdrs, packet_out packet) { 68 | apply { 69 | packet.emit(hdrs.ethernet); 70 | packet.emit(hdrs.ipv4); 71 | } 72 | } 73 | 74 | xdp(Parser(), Ingress(), Deparser()) main; 75 | -------------------------------------------------------------------------------- /P4_examples/P4-XDP_example/program.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ANTLab-polimi/FOP4/6edf95398f8fd93b0d8f52ebf666a8dc6c0b27ab/P4_examples/P4-XDP_example/program.o -------------------------------------------------------------------------------- /P4_examples/README.md: -------------------------------------------------------------------------------- 1 | # P4 examples on FOP4 2 | 3 | ## Pre-requisites 4 | 5 | To run these examples you need to have installed both `p4c` and `behavioural-model` with **P4Runtime** support. 6 | 7 | You can follow the guide provided by *p4.org*. 8 | 9 | * `p4c`: you need to install the P4 compiler following [this guide](https://github.com/p4lang/p4c) 10 | * `behavioural-model`: you need to install `simple_switch_grpc` following [this guide](https://github.com/p4lang/behavioral-model/tree/master/targets/simple_switch_grpc) (remember to install also **P4Runtime**) 11 | 12 | Alternatively, you can use the [ONF script](https://github.com/opennetworkinglab/onos/blob/master/tools/dev/p4vm/install-p4-tools.sh) that should install both `p4c` and `behavioural-model` with support to P4Runtime. 13 | 14 | See [here](https://github.com/jafingerhut/p4-guide/blob/master/bin/README-install-troubleshooting.md) for troubleshooting. 15 | 16 | ## Topology 17 | 18 | 2 Hosts: 19 | 20 | * h1) IP: 192.168.1.104, MAC: 00:00:00:00:00:04 21 | * h2) IP: 192.168.1.105, MAC: 00:00:00:00:00:05 22 | 23 | 1 *"Fake"* Host (Docker Image: containernet_example:ubuntup4) 24 | 25 | * d1) IP: 192.168.1.100, MAC: 00:00:00:00:00:01 26 | 27 | 2 LAMP SERVER (Docker image: containernet_example:lamp) 28 | 29 | * d2) IP: 192.168.1.200, MAC: 00:00:00:00:00:A0 30 | * d3) IP: 192.168.1.201, MAC: 00:00:00:00:00:A1 31 | 32 | 1 Switch P4: 33 | 34 | * It will be loaded with the pipeline load_balancer_RR or load_balancer_hash 35 | 36 | ## Instructions 37 | 38 | ### Prerequisites 39 | 40 | To be able to run the following examples, the needed Docker containers have to be already built. 41 | To build them, run `FOP4/examples/example-containers/build.sh` 42 | 43 | ### Running 44 | 45 | First you need to compile the P4 pipeline using the `make` command on the folders `load_balancer_hash` and `load_balancer_RR`. 46 | 47 | Then you can run the script `load_balancer_hash_p4.py` or the script `load_balancer_RR_p4.py` to run the previously described topology. 48 | 49 | Finally, you need to populate the tables of the switch using the command `simple_switch_CLI --thrift-port $(cat /tmp/bmv2-s1-thrift-port) < command.txt`. 50 | 51 | ```bash 52 | containernet> sh simple_switch_CLI --thrift-port $(cat /tmp/bmv2-s1-thrift-port) < command.txt 53 | ``` 54 | 55 | If you try to contact the LAMP webserver at the address 192.168.1.100 you will be served alternatively from the host with IP 192.168.1.200 or the host with IP 192.168.1.201. 56 | To check it you can try to open the page `index.php` and you can check the address of the server that served the page (search for **SERVER_ADDR** field). 57 | 58 | ```bash 59 | containernet> h1 curl -s 192.168.1.100/index.php | grep SERVER_ADDR 60 | ``` 61 | 62 | ## Miniedit.py 63 | 64 | You can use a GUI using `miniedit.py` script on the `example` folder of this repository, this script has support for P4 BMv2 switches. 65 | -------------------------------------------------------------------------------- /P4_examples/eINT/README.md: -------------------------------------------------------------------------------- 1 | # extended INT (eINT) with VNFs support 2 | 3 | ## Demo architecture 4 | 5 | ![Scenario3](https://github.com/ANTLab-polimi/FOP4/raw/master/P4_examples/eINT/doc/UC3_2.png) 6 | 7 | ## Example of functionality 8 | ![Scenario3Example](https://github.com/ANTLab-polimi/FOP4/raw/master/P4_examples/eINT/doc/UC3_1.png) 9 | 10 | 11 | ## Demo walkthrough 12 | 13 | ### Step 1: Add int-vnf 14 | 15 | ```sh 16 | cd int-vnf/ 17 | ./build.sh 18 | cd .. 19 | ``` 20 | 21 | ### Step 2: Start FOP4 topology 22 | 23 | 24 | ```sh 25 | sudo python3 eint_topology.py 26 | 27 | # check if things run in FOP4: 28 | containernet> dump 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | # check Docker status 40 | containernet> sh docker ps 41 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 42 | 2f3585b0c837 fop4_example:eINT "/bin/bash" 53 seconds ago Up 52 seconds mn.v2 43 | ac083b30a046 fop4_example:eINT "/bin/bash" 54 seconds ago Up 54 seconds mn.v1 44 | 45 | ``` 46 | 47 | ### Step 3: Test connectivity 48 | 49 | #### Terminal 50 | Test iperf UDP connectivity between the 2 hosts. `h1` is the Traffic Source, `h2` is the traffic sink 51 | 52 | ```sh 53 | h2 iperf -u -s & 54 | h1 iperf -u -l 1200 -c 10.0.0.2 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /P4_examples/eINT/commands_INT_s1.txt: -------------------------------------------------------------------------------- 1 | table_add ingress.table0_control.table0 set_egress_port 0x0001&&&0xFFFF 0&&&0 0&&&0 0x0800&&&0xFFFF 0&&&0 0&&&0 0x11&&&0xFF 0&&&0 0&&&0 => 2 1 2 | table_add ingress.table0_control.table0 set_egress_port 0x0002&&&0xFFFF 0&&&0 0&&&0 0x0800&&&0xFFFF 0&&&0 0&&&0 0x11&&&0xFF 0&&&0 0&&&0 => 1 2 3 | table_add ingress.process_int_source_sink.tb_set_source int_set_source 0x0001 => 4 | table_add ingress.process_int_source.tb_int_source int_source_dscp 0&&&0 0&&&0 0&&&0 0&&&0 => 3 10 0b1110 0 0b0000 0 10 5 | table_add egress.process_int_transit.tb_int_insert init_metadata 1 => 0x01 -------------------------------------------------------------------------------- /P4_examples/eINT/commands_INT_s2.txt: -------------------------------------------------------------------------------- 1 | table_add ingress.table0_control.table0 set_egress_port 0x0001&&&0xFFFF 0&&&0 0&&&0 0x0800&&&0xFFFF 0&&&0 0&&&0 0x11&&&0xFF 0&&&0 0&&&0 => 3 1 2 | table_add ingress.table0_control.table0 set_egress_port 0x0002&&&0xFFFF 0&&&0 0&&&0 0x0800&&&0xFFFF 0&&&0 0&&&0 0x11&&&0xFF 0&&&0 0&&&0 => 1 2 3 | table_add ingress.table0_control.table0 set_egress_port 0x0004&&&0xFFFF 0&&&0 0&&&0 0x0800&&&0xFFFF 0&&&0 0&&&0 0x11&&&0xFF 0&&&0 0&&&0 => 2 3 4 | table_add egress.process_int_transit.tb_int_insert init_metadata 1 => 0x02 5 | -------------------------------------------------------------------------------- /P4_examples/eINT/commands_INT_s3.txt: -------------------------------------------------------------------------------- 1 | table_add ingress.table0_control.table0 set_egress_port 0x0001&&&0xFFFF 0&&&0 0&&&0 0x0800&&&0xFFFF 0&&&0 0&&&0 0x11&&&0xFF 0&&&0 0&&&0 => 3 1 2 | table_add ingress.table0_control.table0 set_egress_port 0x0002&&&0xFFFF 0&&&0 0&&&0 0x0800&&&0xFFFF 0&&&0 0&&&0 0x11&&&0xFF 0&&&0 0&&&0 => 1 2 3 | table_add ingress.table0_control.table0 set_egress_port 0x0004&&&0xFFFF 0&&&0 0&&&0 0x0800&&&0xFFFF 0&&&0 0&&&0 0x11&&&0xFF 0&&&0 0&&&0 => 2 3 4 | table_add egress.process_int_transit.tb_int_insert init_metadata 1 => 0x03 -------------------------------------------------------------------------------- /P4_examples/eINT/commands_INT_s4.txt: -------------------------------------------------------------------------------- 1 | table_add ingress.table0_control.table0 set_egress_port 0x0001&&&0xFFFF 0&&&0 0&&&0 0x0800&&&0xFFFF 0&&&0 0&&&0 0x11&&&0xFF 0&&&0 0&&&0 => 2 1 2 | table_add ingress.table0_control.table0 set_egress_port 0x0002&&&0xFFFF 0&&&0 0&&&0 0x0800&&&0xFFFF 0&&&0 0&&&0 0x11&&&0xFF 0&&&0 0&&&0 => 1 2 3 | table_add egress.process_int_transit.tb_int_insert init_metadata 1 => 0x04 4 | table_add egress. 5 | table_add ingress.process_int_source_sink.tb_set_sink int_set_sink 0x0002 => 6 | mirroring_add 500 3 -------------------------------------------------------------------------------- /P4_examples/eINT/doc/UC3_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ANTLab-polimi/FOP4/6edf95398f8fd93b0d8f52ebf666a8dc6c0b27ab/P4_examples/eINT/doc/UC3_1.png -------------------------------------------------------------------------------- /P4_examples/eINT/doc/UC3_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ANTLab-polimi/FOP4/6edf95398f8fd93b0d8f52ebf666a8dc6c0b27ab/P4_examples/eINT/doc/UC3_2.png -------------------------------------------------------------------------------- /P4_examples/eINT/eint_topology.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from mininet.net import Containernet 3 | from mininet.cli import CLI 4 | from mininet.log import info, setLogLevel 5 | from mininet.bmv2 import ONOSBmv2Switch, P4DockerHost, P4Host, Bmv2Switch 6 | setLogLevel('info') 7 | 8 | net = Containernet(switch=Bmv2Switch) 9 | 10 | info('*** Adding docker containers\n') 11 | 12 | # HOSTS 13 | h1 = net.addHost('h1', cls=P4Host, ip='10.0.0.1', mac="00:00:00:00:00:01") 14 | h2 = net.addHost('h2', cls=P4Host, ip='10.0.0.2', mac="00:00:00:00:00:02") 15 | 16 | # INT COLLECTOR 17 | h3 = net.addHost('h3', cls=P4Host, ip='10.0.0.254', mac="00:00:00:00:00:FF") 18 | 19 | 20 | v1 = net.addDocker('v1', cls=P4DockerHost, ip='10.0.0.100', mac="00:00:00:00:00:F1", dimage='fop4_example:eINT') 21 | v2 = net.addDocker('v2', cls=P4DockerHost, ip='10.0.0.101', mac="00:00:00:00:00:F2", dimage='fop4_example:eINT') 22 | 23 | info('*** Adding switches\n') 24 | # SWITCHES 25 | s1 = net.addP4Switch(name='s1', json="./int.json", loglevel='debug', pktdump=False, 26 | switch_config='./commands_INT_s1.txt') 27 | s2 = net.addP4Switch(name='s2', json="./int.json", loglevel='debug', pktdump=False, 28 | switch_config='./commands_INT_s2.txt') 29 | s3 = net.addP4Switch(name='s3', json="./int.json", loglevel='debug', pktdump=False, 30 | switch_config='./commands_INT_s3.txt') 31 | s4 = net.addP4Switch(name='s4', json="./int.json", loglevel='debug', pktdump=False, 32 | switch_config='./commands_INT_s4.txt') 33 | 34 | # LINKS 35 | info('*** Creating links\n') 36 | net.addLink(h1, s1) 37 | net.addLink(s1, s2) 38 | 39 | net.addLink(s2, s3) 40 | net.addLink(s2, v1) 41 | net.addLink(s2, v1) 42 | 43 | net.addLink(s3, s4) 44 | net.addLink(s3, v2) 45 | net.addLink(s3, v2) 46 | 47 | net.addLink(h2, s4) 48 | net.addLink(s4, h3) 49 | 50 | info('*** Starting network\n') 51 | 52 | net.start() 53 | net.staticArp() 54 | 55 | # Start containers 56 | v1.start() 57 | v2.start() 58 | 59 | info('*** Running CLI\n') 60 | CLI(net) 61 | info('*** Stopping network') 62 | net.stop() 63 | -------------------------------------------------------------------------------- /P4_examples/eINT/int-vnf/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:xenial 2 | MAINTAINER daniele.moro@polimi.it 3 | 4 | RUN export DEBIAN_FRONTEND=noninteractive && apt-get update && apt-get install -y -q \ 5 | net-tools \ 6 | iproute \ 7 | inetutils-ping \ 8 | iptables \ 9 | arptables \ 10 | ebtables \ 11 | bridge-utils \ 12 | ethtool \ 13 | vim \ 14 | tcpdump \ 15 | python \ 16 | python-pip \ 17 | python-psutil 18 | 19 | RUN pip install scapy 20 | 21 | ADD sniff.py sniff.py 22 | ADD int_header.py int_header.py 23 | ADD start.sh start.sh 24 | RUN chmod +x start.sh 25 | 26 | # normal entry point 27 | CMD ./start.sh 28 | -------------------------------------------------------------------------------- /P4_examples/eINT/int-vnf/Readme: -------------------------------------------------------------------------------- 1 | Copy files `sniff.py` and `int_header.py` from `uc3_int/vnf_int_injector` folder. -------------------------------------------------------------------------------- /P4_examples/eINT/int-vnf/build.sh: -------------------------------------------------------------------------------- 1 | docker build -t fop4_example:eINT -f Dockerfile . 2 | -------------------------------------------------------------------------------- /P4_examples/eINT/int-vnf/gen_packet_test_int.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from scapy.all import * 3 | import time 4 | import argparse 5 | 6 | from int_header import INT_v10 7 | 8 | if __name__ == "__main__": 9 | p1 = Ether() / \ 10 | IP(src="10.0.0.1", dst="10.0.0.2") / \ 11 | UDP(sport=5000, dport=5000) / \ 12 | INT_v10(length=6, hopMLen=4, remainHopCnt=3, 13 | # ver=1, 14 | ins=0b11110000, 15 | vnf_ins=0b11100000, 16 | # reserved=0, 17 | INTMetadata=[100,100,100], 18 | ) / \ 19 | Raw(load="0"*40) 20 | 21 | iface = "veth1" 22 | 23 | try: 24 | while 1: 25 | # sendp(p0, iface=iface) 26 | # time.sleep(2) 27 | sendp(p1, iface=iface) 28 | time.sleep(2) 29 | 30 | except KeyboardInterrupt: 31 | pass 32 | -------------------------------------------------------------------------------- /P4_examples/eINT/int-vnf/int_header.py: -------------------------------------------------------------------------------- 1 | from scapy.all import * 2 | 3 | 4 | class INT_v10(Packet): 5 | name = "INT v1.0" 6 | 7 | fields_desc = [ 8 | # ----- Shim header ------ (4 Bytes) 9 | XByteField("type", 1), 10 | XByteField("shimRsvd1", None), 11 | XByteField("length", None), # --> lunghezza totale della parte di int (INT header+metadata+shim) in numero di 4-byte words 12 | BitField("dscp", None, 6), 13 | BitField("shimRsvd2", None, 2), 14 | # ------------------------ 15 | 16 | # ----- Header INT ------- (4 Bytes) 17 | BitField("ver", 0, 4), 18 | BitField("rep", 0, 2), 19 | BitField("c", 0, 1), 20 | BitField("e", 0, 1), 21 | BitField("m", 0, 1), 22 | BitField("rsvd1", 0, 7), 23 | BitField("rsvd2", 0, 3), 24 | BitField("hopMLen", None, 5), 25 | XByteField("remainHopCnt", None), 26 | 27 | XByteField("ins", None), 28 | XByteField("vnf_ins", None), 29 | XShortField("reserved", None), 30 | # ------------------------- 31 | 32 | # ----- INT METADATA ------ 33 | # (Multiple of 4 bytes, length is length in the shim header - 3 (the 2*4bytes of shim and INT header) 34 | FieldListField("INTMetadata", [], XIntField("", None), count_from=lambda p: p.length - 3) 35 | # ------------------------ 36 | ] 37 | -------------------------------------------------------------------------------- /P4_examples/eINT/int-vnf/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | python ./sniff.py --in_intf $(hostname)'-eth0' --out_intf $(hostname)'-eth1' --vnf_id 1 4 | -------------------------------------------------------------------------------- /P4_examples/eINT/p4src/Makefile: -------------------------------------------------------------------------------- 1 | all: int 2 | 3 | int: int.p4 4 | p4c-bm2-ss --arch v1model -o p4c-out/bmv2/int.json "-DTARGET_BMV2" \ 5 | --p4runtime-files p4c-out/bmv2/int_p4info.txt \ 6 | int.p4 7 | 8 | clean: 9 | rm -rf p4c-out/bmv2/* 10 | -------------------------------------------------------------------------------- /P4_examples/eINT/p4src/include/actions.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-present Open Networking Foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __ACTIONS__ 18 | #define __ACTIONS__ 19 | 20 | #include "headers.p4" 21 | #include "defines.p4" 22 | 23 | action _drop() { 24 | mark_to_drop(); 25 | } 26 | 27 | action nop() { 28 | NoAction(); 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /P4_examples/eINT/p4src/include/checksums.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-present Open Networking Foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __CHECKSUMS__ 18 | #define __CHECKSUMS__ 19 | 20 | #include "headers.p4" 21 | 22 | control verify_checksum_control(inout headers_t hdr, 23 | inout local_metadata_t local_metadata) { 24 | apply { 25 | // Assume checksum is always correct. 26 | } 27 | } 28 | 29 | control compute_checksum_control(inout headers_t hdr, 30 | inout local_metadata_t local_metadata) { 31 | apply { 32 | update_checksum(hdr.ipv4.isValid(), 33 | { 34 | hdr.ipv4.version, 35 | hdr.ipv4.ihl, 36 | hdr.ipv4.dscp, 37 | hdr.ipv4.ecn, 38 | hdr.ipv4.len, 39 | hdr.ipv4.identification, 40 | hdr.ipv4.flags, 41 | hdr.ipv4.frag_offset, 42 | hdr.ipv4.ttl, 43 | hdr.ipv4.protocol, 44 | hdr.ipv4.src_addr, 45 | hdr.ipv4.dst_addr 46 | }, 47 | hdr.ipv4.hdr_checksum, 48 | HashAlgorithm.csum16 49 | ); 50 | 51 | 52 | // Need to recompute for the cloned packet. 53 | //TODO: https://github.com/p4lang/p4app/issues/43#issuecomment-378061934 54 | #ifdef __INT_HEADERS__ 55 | update_checksum(hdr.report_ipv4.isValid(), 56 | { 57 | hdr.report_ipv4.version, 58 | hdr.report_ipv4.ihl, 59 | hdr.report_ipv4.dscp, 60 | hdr.report_ipv4.ecn, 61 | hdr.report_ipv4.len, 62 | hdr.report_ipv4.identification, 63 | hdr.report_ipv4.flags, 64 | hdr.report_ipv4.frag_offset, 65 | hdr.report_ipv4.ttl, 66 | hdr.report_ipv4.protocol, 67 | hdr.report_ipv4.src_addr, 68 | hdr.report_ipv4.dst_addr 69 | }, 70 | hdr.report_ipv4.hdr_checksum, 71 | HashAlgorithm.csum16 72 | ); 73 | #endif // __INT_HEADERS__ 74 | update_checksum_with_payload(hdr.udp.isValid(), 75 | { hdr.ipv4.src_addr, 76 | hdr.ipv4.dst_addr, 77 | 8w0, 78 | hdr.ipv4.protocol, 79 | hdr.udp.length_, 80 | hdr.udp.src_port, 81 | hdr.udp.dst_port, 82 | hdr.udp.length_ 83 | }, 84 | hdr.udp.checksum, 85 | HashAlgorithm.csum16); 86 | } 87 | } 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /P4_examples/eINT/p4src/include/defines.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-present Open Networking Foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __DEFINES__ 18 | #define __DEFINES__ 19 | 20 | #define ETH_TYPE_IPV4 0x0800 21 | #define IP_PROTO_TCP 8w6 22 | #define IP_PROTO_UDP 8w17 23 | #define IP_VERSION_4 4w4 24 | #define IPV4_IHL_MIN 4w5 25 | #define MAX_PORTS 511 26 | 27 | #ifndef _BOOL 28 | #define _BOOL bool 29 | #endif 30 | #ifndef _TRUE 31 | #define _TRUE true 32 | #endif 33 | #ifndef _FALSE 34 | #define _FALSE false 35 | #endif 36 | 37 | typedef bit<48> mac_t; 38 | typedef bit<32> ip_address_t; 39 | typedef bit<16> l4_port_t; 40 | typedef bit<9> port_t; 41 | typedef bit<16> next_hop_id_t; 42 | 43 | const port_t CPU_PORT = 255; 44 | 45 | typedef bit<8> MeterColor; 46 | const MeterColor MeterColor_GREEN = 8w0; 47 | const MeterColor MeterColor_YELLOW = 8w1; 48 | const MeterColor MeterColor_RED = 8w2; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /P4_examples/eINT/p4src/include/headers.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-present Open Networking Foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __HEADERS__ 18 | #define __HEADERS__ 19 | 20 | #include "defines.p4" 21 | 22 | @controller_header("packet_in") 23 | header packet_in_header_t { 24 | bit<9> ingress_port; 25 | bit<7> _padding; 26 | } 27 | 28 | @controller_header("packet_out") 29 | header packet_out_header_t { 30 | bit<9> egress_port; 31 | bit<7> _padding; 32 | } 33 | 34 | header ethernet_t { 35 | bit<48> dst_addr; 36 | bit<48> src_addr; 37 | bit<16> ether_type; 38 | } 39 | const bit<8> ETH_HEADER_LEN = 14; 40 | 41 | header ipv4_t { 42 | bit<4> version; 43 | bit<4> ihl; 44 | bit<6> dscp; 45 | bit<2> ecn; 46 | bit<16> len; 47 | bit<16> identification; 48 | bit<3> flags; 49 | bit<13> frag_offset; 50 | bit<8> ttl; 51 | bit<8> protocol; 52 | bit<16> hdr_checksum; 53 | bit<32> src_addr; 54 | bit<32> dst_addr; 55 | } 56 | const bit<8> IPV4_MIN_HEAD_LEN = 20; 57 | 58 | header tcp_t { 59 | bit<16> src_port; 60 | bit<16> dst_port; 61 | bit<32> seq_no; 62 | bit<32> ack_no; 63 | bit<4> data_offset; 64 | bit<3> res; 65 | bit<3> ecn; 66 | bit<6> ctrl; 67 | bit<16> window; 68 | bit<16> checksum; 69 | bit<16> urgent_ptr; 70 | } 71 | 72 | header udp_t { 73 | bit<16> src_port; 74 | bit<16> dst_port; 75 | bit<16> length_; 76 | bit<16> checksum; 77 | } 78 | const bit<8> UDP_HEADER_LEN = 8; 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /P4_examples/eINT/p4src/include/int_definitions.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-present Open Networking Foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* -*- P4_16 -*- */ 18 | #ifndef __INT_DEFINE__ 19 | #define __INT_DEFINE__ 20 | 21 | #include "defines.p4" 22 | 23 | /* indicate INT by DSCP value */ 24 | const bit<6> DSCP_INT = 0x17; 25 | const bit<6> DSCP_MASK = 0x3F; 26 | 27 | typedef bit<48> timestamp_t; 28 | typedef bit<32> switch_id_t; 29 | 30 | const bit<8> INT_HEADER_LEN_WORD = 3; 31 | const bit<16> INT_HEADER_SIZE = 8; 32 | const bit<16> INT_SHIM_HEADER_SIZE = 4; 33 | 34 | const bit<8> CPU_MIRROR_SESSION_ID = 250; 35 | const bit<32> REPORT_MIRROR_SESSION_ID = 500; 36 | const bit<6> HW_ID = 1; 37 | const bit<8> REPORT_HDR_TTL = 64; 38 | 39 | #ifdef TARGET_BMV2 40 | // These definitions are from: 41 | // https://github.com/jafingerhut/p4-guide/blob/master/v1model-special-ops/v1model-special-ops.p4 42 | 43 | // These definitions are derived from the numerical values of the enum 44 | // named "PktInstanceType" in the p4lang/behavioral-model source file 45 | // targets/simple_switch/simple_switch.h 46 | // https://github.com/p4lang/behavioral-model/blob/master/targets/simple_switch/simple_switch.h#L126-L134 47 | 48 | const bit<32> BMV2_V1MODEL_INSTANCE_TYPE_NORMAL = 0; 49 | const bit<32> BMV2_V1MODEL_INSTANCE_TYPE_INGRESS_CLONE = 1; 50 | const bit<32> BMV2_V1MODEL_INSTANCE_TYPE_EGRESS_CLONE = 2; 51 | const bit<32> BMV2_V1MODEL_INSTANCE_TYPE_COALESCED = 3; 52 | const bit<32> BMV2_V1MODEL_INSTANCE_TYPE_RECIRC = 4; 53 | const bit<32> BMV2_V1MODEL_INSTANCE_TYPE_REPLICATION = 5; 54 | const bit<32> BMV2_V1MODEL_INSTANCE_TYPE_RESUBMIT = 6; 55 | 56 | #define IS_RESUBMITTED(smeta) (smeta.instance_type == BMV2_V1MODEL_INSTANCE_TYPE_RESUBMIT) 57 | #define IS_RECIRCULATED(smeta) (smeta.instance_type == BMV2_V1MODEL_INSTANCE_TYPE_RECIRC) 58 | #define IS_I2E_CLONE(smeta) (smeta.instance_type == BMV2_V1MODEL_INSTANCE_TYPE_INGRESS_CLONE) 59 | #define IS_E2E_CLONE(smeta) (smeta.instance_type == BMV2_V1MODEL_INSTANCE_TYPE_EGRESS_CLONE) 60 | #define IS_REPLICATED(smeta) (smeta.instance_type == BMV2_V1MODEL_INSTANCE_TYPE_REPLICATION) 61 | #endif // TARGET__BMV2 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /P4_examples/eINT/p4src/include/int_sink.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-present Open Networking Foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* -*- P4_16 -*- */ 18 | #ifndef __INT_SINK__ 19 | #define __INT_SINK__ 20 | 21 | control process_int_sink ( 22 | inout headers_t hdr, 23 | inout local_metadata_t local_metadata, 24 | inout standard_metadata_t standard_metadata) { 25 | @hidden 26 | action restore_header () { 27 | hdr.ipv4.dscp = hdr.intl4_shim.dscp; 28 | // restore length fields of IPv4 header and UDP header 29 | bit<16> len_bytes = ((bit<16>)hdr.intl4_shim.len) << 2; 30 | hdr.ipv4.len = hdr.ipv4.len - len_bytes; 31 | hdr.udp.length_ = hdr.udp.length_ - len_bytes; 32 | } 33 | 34 | @hidden 35 | action int_sink() { 36 | // remove all the INT information from the packet 37 | hdr.int_header.setInvalid(); 38 | hdr.int_data.setInvalid(); 39 | hdr.intl4_shim.setInvalid(); 40 | hdr.int_switch_id.setInvalid(); 41 | hdr.int_level1_port_ids.setInvalid(); 42 | hdr.int_hop_latency.setInvalid(); 43 | hdr.int_q_occupancy.setInvalid(); 44 | hdr.int_ingress_tstamp.setInvalid(); 45 | hdr.int_egress_tstamp.setInvalid(); 46 | hdr.int_level2_port_ids.setInvalid(); 47 | hdr.int_egress_tx_util.setInvalid(); 48 | hdr.extra_data[0].setInvalid(); 49 | hdr.extra_data[1].setInvalid(); 50 | hdr.extra_data[2].setInvalid(); 51 | hdr.extra_data[3].setInvalid(); 52 | hdr.extra_data[4].setInvalid(); 53 | hdr.extra_data[5].setInvalid(); 54 | hdr.extra_data[6].setInvalid(); 55 | hdr.extra_data[7].setInvalid(); 56 | hdr.extra_data[8].setInvalid(); 57 | hdr.extra_data[9].setInvalid(); 58 | hdr.extra_data[10].setInvalid(); 59 | hdr.extra_data[11].setInvalid(); 60 | hdr.extra_data[12].setInvalid(); 61 | hdr.extra_data[13].setInvalid(); 62 | hdr.extra_data[14].setInvalid(); 63 | hdr.extra_data[15].setInvalid(); 64 | } 65 | 66 | apply { 67 | restore_header(); 68 | int_sink(); 69 | } 70 | } 71 | #endif 72 | -------------------------------------------------------------------------------- /P4_examples/eINT/p4src/include/packet_io.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-present Open Networking Foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __PACKET_IO__ 18 | #define __PACKET_IO__ 19 | 20 | #include "headers.p4" 21 | #include "defines.p4" 22 | 23 | control packetio_ingress(inout headers_t hdr, 24 | inout standard_metadata_t standard_metadata) { 25 | apply { 26 | if (standard_metadata.ingress_port == CPU_PORT) { 27 | standard_metadata.egress_spec = hdr.packet_out.egress_port; 28 | hdr.packet_out.setInvalid(); 29 | exit; 30 | } 31 | } 32 | } 33 | 34 | control packetio_egress(inout headers_t hdr, 35 | inout standard_metadata_t standard_metadata) { 36 | apply { 37 | if (standard_metadata.egress_port == CPU_PORT) { 38 | hdr.packet_in.setValid(); 39 | hdr.packet_in.ingress_port = standard_metadata.ingress_port; 40 | } 41 | } 42 | } 43 | 44 | #endif -------------------------------------------------------------------------------- /P4_examples/eINT/p4src/include/port_counters.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-present Open Networking Foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __PORT_COUNTERS__ 18 | #define __PORT_COUNTERS__ 19 | 20 | #include "headers.p4" 21 | #include "defines.p4" 22 | 23 | control port_counters_ingress(inout headers_t hdr, 24 | inout standard_metadata_t standard_metadata) { 25 | 26 | counter(MAX_PORTS, CounterType.packets) ingress_port_counter; 27 | 28 | apply { 29 | ingress_port_counter.count((bit<32>) standard_metadata.ingress_port); 30 | } 31 | } 32 | 33 | control port_counters_egress(inout headers_t hdr, 34 | inout standard_metadata_t standard_metadata) { 35 | 36 | counter(MAX_PORTS, CounterType.packets) egress_port_counter; 37 | 38 | apply { 39 | egress_port_counter.count((bit<32>) standard_metadata.egress_port); 40 | } 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /P4_examples/eINT/p4src/include/table0.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-present Open Networking Foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __TABLE0__ 18 | #define __TABLE0__ 19 | 20 | #include "headers.p4" 21 | #include "defines.p4" 22 | 23 | control table0_control(inout headers_t hdr, 24 | inout local_metadata_t local_metadata, 25 | inout standard_metadata_t standard_metadata) { 26 | 27 | direct_counter(CounterType.packets_and_bytes) table0_counter; 28 | 29 | action set_next_hop_id(next_hop_id_t next_hop_id) { 30 | local_metadata.next_hop_id = next_hop_id; 31 | } 32 | 33 | action send_to_cpu() { 34 | standard_metadata.egress_spec = CPU_PORT; 35 | } 36 | 37 | action set_egress_port(port_t port) { 38 | standard_metadata.egress_spec = port; 39 | } 40 | 41 | table table0 { 42 | key = { 43 | standard_metadata.ingress_port : ternary; 44 | hdr.ethernet.src_addr : ternary; 45 | hdr.ethernet.dst_addr : ternary; 46 | hdr.ethernet.ether_type : ternary; 47 | hdr.ipv4.src_addr : ternary; 48 | hdr.ipv4.dst_addr : ternary; 49 | hdr.ipv4.protocol : ternary; 50 | local_metadata.l4_src_port : ternary; 51 | local_metadata.l4_dst_port : ternary; 52 | } 53 | actions = { 54 | set_egress_port; 55 | send_to_cpu; 56 | set_next_hop_id; 57 | _drop; 58 | } 59 | const default_action = _drop(); 60 | counters = table0_counter; 61 | } 62 | 63 | apply { 64 | table0.apply(); 65 | } 66 | } 67 | 68 | #endif -------------------------------------------------------------------------------- /P4_examples/eINT/p4src/include/telemetry_report_headers.p4: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-present Open Networking Foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* -*- P4_16 -*- */ 18 | #ifndef __TELEMETRY_REPORT_HEADERS__ 19 | #define __TELEMETRY_REPORT_HEADERS__ 20 | 21 | const bit<3> NPROTO_ETHERNET = 0; 22 | const bit<3> NPROTO_TELEMETRY_DROP_HEADER = 1; 23 | const bit<3> NPROTO_TELEMETRY_SWITCH_LOCAL_HEADER = 2; 24 | 25 | 26 | // Report Telemetry Headers 27 | header report_fixed_header_t { 28 | bit<4> ver; 29 | bit<4> len; 30 | bit<3> nproto; 31 | bit<6> rep_md_bits; 32 | bit<1> d; 33 | bit<1> q; 34 | bit<1> f; 35 | bit<6> rsvd; 36 | bit<6> hw_id; 37 | bit<32> sw_id; 38 | bit<32> seq_no; 39 | bit<32> ingress_tstamp; 40 | } 41 | const bit<8> REPORT_FIXED_HEADER_LEN = 16; 42 | 43 | // Telemetry drop report header 44 | header drop_report_header_t { 45 | bit<32> switch_id; 46 | bit<16> ingress_port_id; 47 | bit<16> egress_port_id; 48 | bit<8> queue_id; 49 | bit<8> drop_reason; 50 | bit<16> pad; 51 | } 52 | const bit<8> DROP_REPORT_HEADER_LEN = 12; 53 | 54 | // Switch Local Report Header 55 | header local_report_header_t { 56 | bit<32> switch_id; 57 | bit<16> ingress_port_id; 58 | bit<16> egress_port_id; 59 | bit<8> queue_id; 60 | bit<24> queue_occupancy; 61 | bit<32> egress_tstamp; 62 | } 63 | const bit<8> LOCAL_REPORT_HEADER_LEN = 16; 64 | 65 | header_union local_report_t { 66 | drop_report_header_t drop_report_header; 67 | local_report_header_t local_report_header; 68 | } 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /P4_examples/load_balancer_RR/Makefile: -------------------------------------------------------------------------------- 1 | all: loadbalancer 2 | 3 | loadbalancer: load_balancer_RR.p4 4 | p4c-bm2-ss --arch v1model -o load_balancer_RR.json \ 5 | --p4runtime-file load_balancer_RRnel.p4info --p4runtime-format text \ 6 | load_balancer_RR.p4 7 | -------------------------------------------------------------------------------- /P4_examples/load_balancer_RR/command.txt: -------------------------------------------------------------------------------- 1 | table_add http_load_balancer set_nhop 192.168.1.100 0x0001&&&0x0001 => 00:00:00:00:00:A0 192.168.1.200 2 200 2 | table_add http_load_balancer set_nhop 192.168.1.100 0x0000&&&0x0001 => 00:00:00:00:00:A1 192.168.1.201 3 201 3 | 4 | table_add other_direction substitute_src 192.168.1.200 => 00:00:00:00:00:01 192.168.1.100 1 5 | table_add other_direction substitute_src 192.168.1.201 => 00:00:00:00:00:01 192.168.1.100 1 6 | 7 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:A0&&&0xFFFFFFFFFFFF 00:00:00:00:00:04&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 2 1 8 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:A0&&&0xFFFFFFFFFFFF 00:00:00:00:00:05&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 2 1 9 | 10 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:A1&&&0xFFFFFFFFFFFF 00:00:00:00:00:04&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 3 1 11 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:A1&&&0xFFFFFFFFFFFF 00:00:00:00:00:05&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 3 1 12 | 13 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:04&&&0xFFFFFFFFFFFF 00:00:00:00:00:A1&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 4 1 14 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:05&&&0xFFFFFFFFFFFF 00:00:00:00:00:A1&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 5 1 15 | 16 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:04&&&0xFFFFFFFFFFFF 00:00:00:00:00:A0&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 4 1 17 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:05&&&0xFFFFFFFFFFFF 00:00:00:00:00:A0&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 5 1 18 | 19 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:04&&&0xFFFFFFFFFFFF 00:00:00:00:00:01&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 4 1 20 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:05&&&0xFFFFFFFFFFFF 00:00:00:00:00:01&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 5 1 21 | 22 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:01&&&0xFFFFFFFFFFFF 00:00:00:00:00:04&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 1 1 23 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:01&&&0xFFFFFFFFFFFF 00:00:00:00:00:05&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 1 1 24 | -------------------------------------------------------------------------------- /P4_examples/load_balancer_RR/load_balancer_RR_p4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from mininet.net import Containernet 3 | from mininet.node import Controller 4 | from mininet.cli import CLI 5 | from mininet.log import info, setLogLevel 6 | from mininet.bmv2 import ONOSBmv2Switch, P4DockerHost 7 | setLogLevel('info') 8 | 9 | 10 | class NormalP4Switch(ONOSBmv2Switch): 11 | def __init__(self, name, **kwargs): 12 | ONOSBmv2Switch.__init__(self, name, **kwargs) 13 | self.netcfg = False 14 | 15 | 16 | net = Containernet(controller=Controller, switch=NormalP4Switch) 17 | 18 | info('*** Adding controller\n') 19 | net.addController('c0') 20 | 21 | info('*** Adding docker containers\n') 22 | 23 | # Fake HOST 24 | d1 = net.addDocker('d1', cls=P4DockerHost, ip='192.168.1.100', 25 | dimage="containernet_example:ubuntup4", mac="00:00:00:00:00:01") 26 | d1.start() 27 | # HOST 28 | h1 = net.addHost('h1', ip='192.168.1.104', mac="00:00:00:00:00:04") 29 | h2 = net.addHost('h2', ip='192.168.1.105', mac="00:00:00:00:00:05") 30 | 31 | # h4 = net.addDocker('h4', cls=P4DockerHost, ip='192.168.1.104', 32 | # dimage="containernet_ubuntup4:latest", mac="00:00:00:00:00:04") 33 | # h5 = net.addDocker('h5', cls=P4DockerHost, ip='192.168.1.105', 34 | # dimage="containernet_ubuntup4:latest", mac="00:00:00:00:00:05") 35 | 36 | 37 | # LAMP servers 38 | d2 = net.addDocker('d2', cls=P4DockerHost, ip='192.168.1.200', 39 | dimage="containernet_example:lamp", mac="00:00:00:00:00:A0") 40 | d2.start() 41 | d3 = net.addDocker('d3', cls=P4DockerHost, ip='192.168.1.201', 42 | dimage="containernet_example:lamp", mac="00:00:00:00:00:A1") 43 | d3.start() 44 | 45 | info('*** Adding switches\n') 46 | 47 | s1 = net.addSwitch('s1', json="./load_balancer_RR.json", loglevel="debug", pktdump=True) 48 | 49 | info('*** Creating links\n') 50 | net.addLink(d1, s1) 51 | net.addLink(d2, s1) 52 | net.addLink(d3, s1) 53 | net.addLink(h1, s1) 54 | net.addLink(h2, s1) 55 | info('*** Starting network\n') 56 | 57 | net.start() 58 | net.staticArp() 59 | 60 | info('*** Running CLI\n') 61 | CLI(net) 62 | info('*** Stopping network') 63 | net.stop() 64 | -------------------------------------------------------------------------------- /P4_examples/load_balancer_hash/Makefile: -------------------------------------------------------------------------------- 1 | all: loadbalancer 2 | 3 | loadbalancer: load_balancer_hash.p4 4 | p4c-bm2-ss --arch v1model -o load_balancer_hash.json \ 5 | --p4runtime-file load_balancer_hash.p4info --p4runtime-format text \ 6 | load_balancer_hash.p4 7 | -------------------------------------------------------------------------------- /P4_examples/load_balancer_hash/command.txt: -------------------------------------------------------------------------------- 1 | table_add ecmp_nhop set_nhop 0x0001&&&0x0001 => 00:00:00:00:00:A0 192.168.1.200 2 200 2 | table_add ecmp_nhop set_nhop 0x0000&&&0x0001 => 00:00:00:00:00:A1 192.168.1.201 3 201 3 | 4 | table_add ecmp_group set_ecmp_select 192.168.1.100 => 10 100 5 | 6 | table_add ecmp_other_direction substitute_src 192.168.1.200 => 00:00:00:00:00:01 192.168.1.100 1 7 | table_add ecmp_other_direction substitute_src 192.168.1.201 => 00:00:00:00:00:01 192.168.1.100 1 8 | 9 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:A0&&&0xFFFFFFFFFFFF 00:00:00:00:00:04&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 2 1 10 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:A0&&&0xFFFFFFFFFFFF 00:00:00:00:00:05&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 2 1 11 | 12 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:A1&&&0xFFFFFFFFFFFF 00:00:00:00:00:04&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 3 1 13 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:A1&&&0xFFFFFFFFFFFF 00:00:00:00:00:05&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 3 1 14 | 15 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:04&&&0xFFFFFFFFFFFF 00:00:00:00:00:A1&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 4 1 16 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:05&&&0xFFFFFFFFFFFF 00:00:00:00:00:A1&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 5 1 17 | 18 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:04&&&0xFFFFFFFFFFFF 00:00:00:00:00:A0&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 4 1 19 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:05&&&0xFFFFFFFFFFFF 00:00:00:00:00:A0&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 5 1 20 | 21 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:04&&&0xFFFFFFFFFFFF 00:00:00:00:00:01&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 4 1 22 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:05&&&0xFFFFFFFFFFFF 00:00:00:00:00:01&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 5 1 23 | 24 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:01&&&0xFFFFFFFFFFFF 00:00:00:00:00:04&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 1 1 25 | table_add t_l2_fwd set_out_port 0x0&&&0x0 00:00:00:00:00:01&&&0xFFFFFFFFFFFF 00:00:00:00:00:05&&&0xFFFFFFFFFFFF 0x0&&&0x0 => 1 1 -------------------------------------------------------------------------------- /P4_examples/load_balancer_hash/load_balancer_hash_p4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from mininet.net import Containernet 3 | from mininet.node import Controller 4 | from mininet.cli import CLI 5 | from mininet.log import info, setLogLevel 6 | from mininet.bmv2 import ONOSBmv2Switch, P4DockerHost 7 | setLogLevel('info') 8 | 9 | 10 | class NormalP4Switch(ONOSBmv2Switch): 11 | def __init__(self, name, **kwargs): 12 | ONOSBmv2Switch.__init__(self, name, **kwargs) 13 | self.netcfg = False 14 | 15 | 16 | net = Containernet(controller=Controller, switch=NormalP4Switch) 17 | 18 | info('*** Adding controller\n') 19 | net.addController('c0') 20 | 21 | info('*** Adding docker containers\n') 22 | 23 | # Fake HOST 24 | d1 = net.addDocker('d1', cls=P4DockerHost, ip='192.168.1.100', 25 | dimage="containernet_example:ubuntup4", mac="00:00:00:00:00:01") 26 | d1.start() 27 | # HOST 28 | h1 = net.addHost('h1', ip='192.168.1.104', mac="00:00:00:00:00:04") 29 | h2 = net.addHost('h2', ip='192.168.1.105', mac="00:00:00:00:00:05") 30 | 31 | # h4 = net.addDocker('h4', cls=P4DockerHost, ip='192.168.1.104', 32 | # dimage="containernet_ubuntup4:latest", mac="00:00:00:00:00:04") 33 | # h5 = net.addDocker('h5', cls=P4DockerHost, ip='192.168.1.105', 34 | # dimage="containernet_ubuntup4:latest", mac="00:00:00:00:00:05") 35 | 36 | 37 | # LAMP servers 38 | d2 = net.addDocker('d2', cls=P4DockerHost, ip='192.168.1.200', 39 | dimage="containernet_example:lamp", mac="00:00:00:00:00:A0") 40 | d2.start() 41 | d3 = net.addDocker('d3', cls=P4DockerHost, ip='192.168.1.201', 42 | dimage="containernet_example:lamp", mac="00:00:00:00:00:A1") 43 | d3.start() 44 | 45 | info('*** Adding switches\n') 46 | 47 | s1 = net.addSwitch('s1', json="./load_balancer_hash.json", loglevel="debug", pktdump=True) 48 | 49 | info('*** Creating links\n') 50 | net.addLink(d1, s1) 51 | net.addLink(d2, s1) 52 | net.addLink(d3, s1) 53 | net.addLink(h1, s1) 54 | net.addLink(h2, s1) 55 | info('*** Starting network\n') 56 | 57 | net.start() 58 | net.staticArp() 59 | 60 | info('*** Running CLI\n') 61 | CLI(net) 62 | info('*** Stopping network') 63 | net.stop() 64 | -------------------------------------------------------------------------------- /StandaloneVagrantfile: -------------------------------------------------------------------------------- 1 | VAGRANT_COMMAND = ARGV[0] 2 | downloaded = false 3 | Vagrant.configure(2) do |config| 4 | config.vm.box = "ubuntu/xenial64" 5 | config.ssh.username = 'root' 6 | if VAGRANT_COMMAND == "provision" || VAGRANT_COMMAND == "up" 7 | config.ssh.username = 'vagrant' 8 | end 9 | config.ssh.insert_key = 'false' 10 | config.vm.provider "virtualbox" do |vb| 11 | vb.customize [ "modifyvm", :id, "--uartmode1", "disconnected" ] 12 | vb.memory = "1024" 13 | end 14 | config.trigger.before :provision, :up, :reload do |trigger| 15 | if !Dir.exists?('ansible') and !File.exists?('install_vagrant.yml') 16 | trigger.run = {inline: "curl https://raw.githubusercontent.com/containernet/containernet/master/ansible/install_vagrant.yml -o install_vagrant.yml -s"} 17 | end 18 | end 19 | config.trigger.after :provision, :up, :reload do |trigger| 20 | trigger.run = {inline: "rm -f install_vagrant.yml"} 21 | end 22 | config.vm.provision "ansible_local" do |a| 23 | if !Dir.exists?('ansible') 24 | a.playbook = "install_vagrant.yml" 25 | else 26 | a.playbook = "ansible/install_vagrant.yml" 27 | end 28 | end 29 | end -------------------------------------------------------------------------------- /ansible/install.yml: -------------------------------------------------------------------------------- 1 | - hosts: localhost 2 | tasks: 3 | - name: updates apt 4 | apt: 5 | update_cache: yes 6 | 7 | - name: install basic packages 8 | apt: name={{item}} state=present 9 | with_items: 10 | - aptitude 11 | - apt-transport-https 12 | - ca-certificates 13 | - curl 14 | - python3-setuptools 15 | - python3-dev 16 | - build-essential 17 | - python3-pip 18 | - iptables 19 | - software-properties-common 20 | 21 | - name: install Docker CE repos (1/3) 22 | apt_key: 23 | url: https://download.docker.com/linux/ubuntu/gpg 24 | state: present 25 | 26 | - name: install Docker CE repos (2/3) 27 | shell: add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" 28 | 29 | - name: install Docker CE repos (3/3) 30 | apt: 31 | update_cache: yes 32 | 33 | - name: install Docker CE 34 | apt: name=docker-ce state=present 35 | 36 | - name: find pip executable 37 | shell: "which pip3" 38 | register: pip_path 39 | 40 | - name: install python-backports.ssl-match-hostname 41 | pip: name=backports.ssl-match-hostname executable={{pip_path.stdout}} 42 | 43 | - name: install pytest 44 | pip: name=pytest version=4.6.4 executable={{pip_path.stdout}} 45 | 46 | - name: install docker py 47 | pip: name=docker version=4.4.1 executable={{pip_path.stdout}} 48 | 49 | - name: install python-iptables 50 | pip: name=python-iptables state=latest executable={{pip_path.stdout}} 51 | 52 | - name: install pexpect 53 | pip: name=pexpect executable={{pip_path.stdout}} 54 | 55 | - name: built and install Containernet (using Mininet installer) 56 | shell: FOP4/util/install.sh -fnv 57 | args: 58 | chdir: ../../ 59 | 60 | - name: install Containernet Python egg etc. 61 | shell: make -f Makefile develop 62 | args: 63 | chdir: ../ 64 | 65 | - name: download 'ubuntu' docker image for Containernet example 66 | shell: docker pull ubuntu:trusty 67 | tags: 68 | - notindocker 69 | - nopull 70 | -------------------------------------------------------------------------------- /ansible/install_centos.yml: -------------------------------------------------------------------------------- 1 | - hosts: localhost 2 | tasks: 3 | - name: epel release 4 | yum: 5 | name: epel-release 6 | state: latest 7 | 8 | - name: openstack repo (for OVS) 9 | yum: 10 | name: centos-release-openstack-rocky 11 | state: latest 12 | 13 | - name: updates yum 14 | yum: 15 | name: '*' 16 | state: latest 17 | 18 | - name: install basic packages 19 | yum: 20 | state: latest 21 | name: 22 | - net-tools 23 | - python3-setuptools 24 | - python3-devel 25 | - python3-pip 26 | - curl 27 | - iptables 28 | - initscripts 29 | - yum-utils 30 | - device-mapper-persistent-data 31 | - lvm2 32 | - ca-certificates 33 | - gcc 34 | - sudo 35 | - which 36 | 37 | - name: install Docker CE (1/3) 38 | shell: yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 39 | 40 | - name: install Docker CE (2/3) 41 | yum: 42 | name: docker-ce 43 | state: latest 44 | 45 | - name: install Docker CE (3/3) 46 | systemd: name=docker state=started 47 | tags: 48 | - notindocker 49 | 50 | - name: find pip executable 51 | shell: "which pip3" 52 | register: pip_path 53 | 54 | - name: install pytest 55 | pip: name=pytest version=4.6.4 executable={{pip_path.stdout}} 56 | 57 | - name: install docker-py 58 | pip: name=docker version=4.1.0 executable={{pip_path.stdout}} 59 | 60 | - name: install python-iptables 61 | pip: name=python-iptables state=latest executable={{pip_path.stdout}} 62 | 63 | - name: build and install Containernet (using Mininet installer) 64 | shell: containernet/util/install.sh 65 | args: 66 | chdir: ../../ 67 | 68 | - name: install Containernet Python egg etc. 69 | shell: make develop 70 | args: 71 | chdir: ../ 72 | 73 | - name: download 'ubuntu' docker image for Containernet example 74 | shell: docker pull ubuntu:trusty 75 | tags: 76 | - notindocker 77 | -------------------------------------------------------------------------------- /ansible/install_vagrant.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | become: yes 3 | tasks: 4 | - name: Ansible copy file to remote server 5 | copy: 6 | src: /home/vagrant/.ssh/authorized_keys 7 | dest: /root/.ssh/authorized_keys 8 | 9 | - name: Replace username in key file 10 | replace: 11 | dest: /etc/hosts 12 | regexp: '^vagrant' 13 | replace: 'root' 14 | 15 | - name: Clone repo 16 | git: 17 | repo: https://github.com/containernet/containernet.git 18 | dest: /var/containernet 19 | version: master 20 | when: 21 | 22 | - name: updates apt 23 | shell: apt-get -qq update 24 | 25 | - name: install basic packages 26 | apt: name={{item}} state=installed 27 | with_items: 28 | - aptitude 29 | - apt-transport-https 30 | - ca-certificates 31 | - curl 32 | - python-setuptools 33 | - python-dev 34 | - build-essential 35 | - python-pip 36 | - iptables 37 | - software-properties-common 38 | 39 | - name: install Docker CE repos (1/3) 40 | shell: curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 41 | 42 | - name: install Docker CE repos (2/3) 43 | shell: add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" 44 | 45 | - name: install Docker CE repos (3/3) 46 | shell: apt-get -qq update 47 | 48 | - name: install Docker CE 49 | apt: name=docker-ce state=installed 50 | 51 | - name: install pytest 52 | pip: name=pytest version=4.6.4 53 | 54 | - name: install docker-py 55 | pip: name=docker version=4.1.0 56 | 57 | - name: install python-iptables 58 | pip: name=python-iptables state=latest 59 | 60 | - name: build and install Containernet (using Mininet installer) 61 | shell: containernet/util/install.sh 62 | args: 63 | chdir: /var 64 | 65 | - name: install Containernet Python egg etc. 66 | shell: make develop 67 | args: 68 | chdir: /var/containernet 69 | 70 | - name: download 'ubuntu' docker image for Containernet example 71 | shell: docker pull ubuntu:trusty 72 | tags: 73 | - notindocker 74 | 75 | -------------------------------------------------------------------------------- /bin/clear_crash.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo docker rm -f $(sudo docker ps --filter 'label=com.containernet' -a -q) 4 | sudo ./mn -c -------------------------------------------------------------------------------- /examples/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Mininet Examples 3 | See README for details 4 | """ 5 | -------------------------------------------------------------------------------- /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 | from mininet.node import Host 7 | from mininet.util import ensureRoot, waitListening 8 | 9 | ensureRoot() 10 | timeout = 5 11 | 12 | print("*** Creating nodes") 13 | h1 = Host( 'h1' ) 14 | 15 | root = Host( 'root', inNamespace=False ) 16 | 17 | print("*** Creating links") 18 | h1.linkTo( root ) 19 | 20 | print(h1) 21 | 22 | print("*** Configuring nodes") 23 | h1.setIP( '10.0.0.1', 8 ) 24 | root.setIP( '10.0.0.2', 8 ) 25 | 26 | print("*** Creating banner file") 27 | f = open( '/tmp/%s.banner' % h1.name, 'w' ) 28 | f.write( 'Welcome to %s at %s\n' % ( h1.name, h1.IP() ) ) 29 | f.close() 30 | 31 | print("*** Running sshd") 32 | cmd = '/usr/sbin/sshd -o UseDNS=no -u0 -o "Banner /tmp/%s.banner"' % h1.name 33 | # add arguments from the command line 34 | if len( sys.argv ) > 1: 35 | cmd += ' ' + ' '.join( sys.argv[ 1: ] ) 36 | h1.cmd( cmd ) 37 | listening = waitListening( server=h1, port=22, timeout=timeout ) 38 | 39 | if listening: 40 | print(("*** You may now ssh into", h1.name, "at", h1.IP())) 41 | else: 42 | print(( "*** Warning: after %s seconds, %s is not listening on port 22" 43 | % ( timeout, h1.name ) )) 44 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | from mininet.topolib import TreeTopo 7 | from mininet.log import setLogLevel 8 | from mininet.examples.clustercli import ClusterCLI as CLI 9 | 10 | def demo(): 11 | "Simple Demo of Cluster Mode" 12 | servers = [ 'localhost', 'ubuntu2', 'ubuntu3' ] 13 | topo = TreeTopo( depth=3, fanout=3 ) 14 | net = MininetCluster( topo=topo, servers=servers, 15 | placement=SwitchBinPlacer ) 16 | net.start() 17 | CLI( net ) 18 | net.stop() 19 | 20 | if __name__ == '__main__': 21 | setLogLevel( 'info' ) 22 | demo() 23 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /examples/containernet_container_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | """ 3 | This topology is used to test the compatibility of different Docker images. 4 | The images to be tested can be found in 'examples/example-containers'. 5 | They are build with './build.sh' 6 | """ 7 | from mininet.net import Containernet 8 | from mininet.node import Controller 9 | from mininet.cli import CLI 10 | from mininet.link import TCLink 11 | from mininet.log import info, setLogLevel 12 | setLogLevel('info') 13 | 14 | net = Containernet(controller=Controller) 15 | info('*** Adding controller\n') 16 | net.addController('c0') 17 | 18 | info('*** Adding docker containers\n') 19 | d1 = net.addDocker('d1', dimage="ubuntu:trusty") 20 | d2 = net.addDocker('d2', dimage="containernet_example:ubuntu1404") 21 | d3 = net.addDocker('d3', dimage="containernet_example:ubuntu1604") 22 | d4 = net.addDocker('d4', dimage="containernet_example:ubuntu1804") 23 | d5 = net.addDocker('d5', dimage="containernet_example:centos6") 24 | d6 = net.addDocker('d6', dimage="containernet_example:centos7") 25 | d7 = net.addDocker('d7', dimage="containernet_example:alpine3") 26 | d8 = net.addDocker('d8', dimage="containernet_example:lamp") 27 | d9 = net.addDocker('d9', dimage="containernet_example:haproxy") 28 | d10 = net.addDocker('d10', dimage="containernet_example:ubuntup4") 29 | 30 | info('*** Adding switches\n') 31 | s1 = net.addSwitch('s1') 32 | 33 | info('*** Creating links\n') 34 | net.addLink(d1, s1) 35 | net.addLink(d2, s1) 36 | net.addLink(d3, s1) 37 | net.addLink(d4, s1) 38 | net.addLink(d5, s1) 39 | net.addLink(d6, s1) 40 | net.addLink(d7, s1) 41 | net.addLink(d8, s1) 42 | net.addLink(d9, s1) 43 | net.addLink(d10, s1) 44 | 45 | info('*** Starting network\n') 46 | net.start() 47 | 48 | info('*** Testing connectivity\n') 49 | net.ping([d2, d1]) 50 | net.ping([d3, d1]) 51 | net.ping([d4, d1]) 52 | net.ping([d5, d1]) 53 | net.ping([d6, d1]) 54 | net.ping([d7, d1]) 55 | net.ping([d8, d1]) 56 | net.ping([d9, d1]) 57 | net.ping([d9, d1]) 58 | 59 | info('*** Running CLI\n') 60 | CLI(net) 61 | 62 | info('*** Stopping network') 63 | net.stop() 64 | 65 | -------------------------------------------------------------------------------- /examples/containernet_example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | """ 3 | This is the most simple example to showcase Containernet. 4 | """ 5 | from mininet.net import Containernet 6 | from mininet.node import Controller 7 | from mininet.cli import CLI 8 | from mininet.link import TCLink 9 | from mininet.log import info, setLogLevel 10 | setLogLevel('info') 11 | 12 | net = Containernet(controller=Controller) 13 | info('*** Adding controller\n') 14 | net.addController('c0') 15 | info('*** Adding docker containers\n') 16 | d1 = net.addDocker('d1', ip='10.0.0.251', dimage="ubuntu:trusty") 17 | d2 = net.addDocker('d2', ip='10.0.0.252', dimage="ubuntu:trusty") 18 | info('*** Adding switches\n') 19 | s1 = net.addSwitch('s1') 20 | s2 = net.addSwitch('s2') 21 | info('*** Creating links\n') 22 | net.addLink(d1, s1) 23 | net.addLink(s1, s2, cls=TCLink, delay='100ms', bw=1) 24 | net.addLink(s2, d2) 25 | info('*** Starting network\n') 26 | net.start() 27 | info('*** Testing connectivity\n') 28 | net.ping([d1, d2]) 29 | info('*** Running CLI\n') 30 | CLI(net) 31 | info('*** Stopping network') 32 | net.stop() 33 | 34 | -------------------------------------------------------------------------------- /examples/containernet_example_cmd_field.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | """ 3 | Example to test the automated CMD field execution feature. 4 | """ 5 | from mininet.net import Containernet 6 | from mininet.node import Controller 7 | from mininet.cli import CLI 8 | from mininet.link import TCLink 9 | from mininet.log import info, setLogLevel 10 | setLogLevel('info') 11 | 12 | net = Containernet(controller=Controller) 13 | info('*** Adding controller\n') 14 | net.addController('c0') 15 | info('*** Adding docker containers\n') 16 | # normal container without CMD 17 | d1 = net.addDocker('d1', ip='10.0.0.251', dimage="ubuntu:trusty") 18 | # HTTPD container with CMD that starts httpd in foreground 19 | d2 = net.addDocker('d2', ip='10.0.0.252', dimage="httpd:latest") 20 | info('*** Adding switches\n') 21 | s1 = net.addSwitch('s1') 22 | s2 = net.addSwitch('s2') 23 | info('*** Creating links\n') 24 | net.addLink(d1, s1) 25 | net.addLink(s1, s2, cls=TCLink, delay='100ms', bw=1) 26 | net.addLink(s2, d2) 27 | info('*** Starting network\n') 28 | net.start() 29 | d2.start() 30 | info('*** Running CLI\n') 31 | CLI(net) 32 | info('*** Stopping network') 33 | net.stop() 34 | 35 | # Check if things are working: 36 | # 1. Containernet CLI containernet> works after startup 37 | # 2. docker container top mn.d2 shows the running httpd 38 | 39 | -------------------------------------------------------------------------------- /examples/containernet_example_ipc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | """ 3 | This is the most simple example to showcase Containernet. 4 | """ 5 | from mininet.net import Containernet 6 | from mininet.node import Controller 7 | from mininet.cli import CLI 8 | from mininet.link import TCLink 9 | from mininet.log import info, setLogLevel 10 | setLogLevel('info') 11 | 12 | net = Containernet(controller=Controller) 13 | info('*** Adding controller\n') 14 | net.addController('c0') 15 | info('*** Adding docker containers\n') 16 | # IPC see: https://docs.docker.com/engine/reference/run/#ipc-settings---ipc 17 | d1 = net.addDocker('d1', ip='10.0.0.251', dimage="ubuntu:trusty", ipc_mode="shareable", devices=["/dev/net/tun"]) # share IPC 18 | d2 = net.addDocker('d2', ip='10.0.0.252', dimage="ubuntu:trusty", ipc_mode="container:mn.d1", devices=["/dev/net/tun"]) # container: 19 | info('*** Adding switches\n') 20 | s1 = net.addSwitch('s1') 21 | s2 = net.addSwitch('s2') 22 | info('*** Creating links\n') 23 | net.addLink(d1, s1) 24 | net.addLink(s1, s2, cls=TCLink, delay='100ms', bw=1) 25 | net.addLink(s2, d2) 26 | info('*** Starting network\n') 27 | net.start() 28 | info('*** Testing connectivity\n') 29 | net.ping([d1, d2]) 30 | info('*** Running CLI\n') 31 | CLI(net) 32 | info('*** Stopping network') 33 | net.stop() 34 | 35 | -------------------------------------------------------------------------------- /examples/containernet_example_server_curl.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | """ 3 | This is the most simple example to showcase Containernet. 4 | """ 5 | from mininet.net import Containernet 6 | from mininet.node import Controller 7 | from mininet.cli import CLI 8 | from mininet.link import TCLink 9 | from mininet.log import info, setLogLevel 10 | setLogLevel('info') 11 | 12 | net = Containernet(controller=Controller) 13 | info('*** Adding controller\n') 14 | net.addController('c0') 15 | info('*** Adding docker containers\n') 16 | server = net.addDocker('server', ip='10.0.0.251', dcmd="python app.py", 17 | dimage="server_example:latest") 18 | client = net.addDocker('client', ip='10.0.0.252', dimage="curl_example:latest") 19 | info('*** Adding switches\n') 20 | s1 = net.addSwitch('s1') 21 | s2 = net.addSwitch('s2') 22 | info('*** Creating links\n') 23 | net.addLink(server, s1) 24 | net.addLink(s1, s2, cls=TCLink, delay='100ms', bw=1) 25 | net.addLink(s2, client) 26 | info('*** Starting network\n') 27 | net.start() 28 | info('\nclient.cmd("time curl 10.0.0.251/9999"):\n') 29 | info(client.cmd("time curl 10.0.0.251/9999") + "\n") 30 | info('*** Running CLI\n') 31 | CLI(net) 32 | info('*** Stopping network') 33 | net.stop() 34 | -------------------------------------------------------------------------------- /examples/containernet_topology_example.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 | This is a copy of tree1024.py that is using the Containernet 9 | constructor. Containernet overrides the buildFromTopo 10 | functionality and adds Docker hosts instead. 11 | """ 12 | 13 | from mininet.cli import CLI 14 | from mininet.log import setLogLevel 15 | from mininet.node import OVSSwitch 16 | from mininet.topolib import TreeContainerNet 17 | 18 | if __name__ == '__main__': 19 | setLogLevel( 'info' ) 20 | network = TreeContainerNet( depth=2, fanout=100, switch=OVSSwitch ) 21 | network.run( CLI, network ) 22 | -------------------------------------------------------------------------------- /examples/containernet_volume_example.py: -------------------------------------------------------------------------------- 1 | from mininet.net import Containernet 2 | from mininet.node import Controller 3 | from mininet.cli import CLI 4 | from mininet.link import TCLink 5 | from mininet.log import info, setLogLevel 6 | setLogLevel('info') 7 | 8 | net = Containernet(controller=Controller) 9 | info('*** Adding controller\n') 10 | net.addController('c0') 11 | info('*** Adding docker containers\n') 12 | d1 = net.addDocker('d1', volumes=["/home/user/vol1:/vol1"], ip='10.0.0.251', dimage="ubuntu:trusty") 13 | d2 = net.addDocker('d2', volumes=["/home/user/vol1:/vol1"], ip='10.0.0.252', dimage="ubuntu:trusty") 14 | info('*** Adding switches\n') 15 | s1 = net.addSwitch('s1') 16 | s2 = net.addSwitch('s2') 17 | info('*** Creating links\n') 18 | net.addLink(d1, d2) 19 | net.addLink(s1, s2, cls=TCLink, delay='100ms', bw=1) 20 | net.addLink(s2, d2) 21 | info('*** Starting network\n') 22 | net.start() 23 | info('*** Testing connectivity\n') 24 | net.ping([d1, d2]) 25 | info('*** Running CLI\n') 26 | CLI(net) 27 | info('*** Stopping network') 28 | net.stop() 29 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | from mininet.net import Mininet 15 | from mininet.node import Controller, OVSSwitch 16 | from mininet.cli import CLI 17 | from mininet.log import setLogLevel 18 | 19 | def multiControllerNet(): 20 | "Create a network from semi-scratch with multiple controllers." 21 | 22 | net = Mininet( controller=Controller, switch=OVSSwitch ) 23 | 24 | print("*** Creating (reference) controllers") 25 | c1 = net.addController( 'c1', port=6633 ) 26 | c2 = net.addController( 'c2', port=6634 ) 27 | 28 | print("*** Creating switches") 29 | s1 = net.addSwitch( 's1' ) 30 | s2 = net.addSwitch( 's2' ) 31 | 32 | print("*** Creating hosts") 33 | hosts1 = [ net.addHost( 'h%d' % n ) for n in (3, 4) ] 34 | hosts2 = [ net.addHost( 'h%d' % n ) for n in (5, 6) ] 35 | 36 | print("*** Creating links") 37 | for h in hosts1: 38 | net.addLink( s1, h ) 39 | for h in hosts2: 40 | net.addLink( s2, h ) 41 | net.addLink( s1, s2 ) 42 | 43 | print("*** Starting network") 44 | net.build() 45 | c1.start() 46 | c2.start() 47 | s1.start( [ c1 ] ) 48 | s2.start( [ c2 ] ) 49 | 50 | print("*** Testing network") 51 | net.pingAll() 52 | 53 | print("*** Running CLI") 54 | CLI( net ) 55 | 56 | print("*** Stopping network") 57 | net.stop() 58 | 59 | if __name__ == '__main__': 60 | setLogLevel( 'info' ) # for CLI output 61 | multiControllerNet() 62 | -------------------------------------------------------------------------------- /examples/cpu.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | cpu.py: test iperf bandwidth for varying cpu limits 5 | """ 6 | 7 | from mininet.net import Mininet 8 | from mininet.node import CPULimitedHost 9 | from mininet.topolib import TreeTopo 10 | from mininet.util import custom, waitListening 11 | from mininet.log import setLogLevel, info 12 | 13 | 14 | def bwtest( cpuLimits, period_us=100000, seconds=5 ): 15 | """Example/test of link and CPU bandwidth limits 16 | cpu: cpu limit as fraction of overall CPU time""" 17 | 18 | topo = TreeTopo( depth=1, fanout=2 ) 19 | 20 | results = {} 21 | 22 | for sched in 'rt', 'cfs': 23 | print(('*** Testing with', sched, 'bandwidth limiting')) 24 | for cpu in cpuLimits: 25 | host = custom( CPULimitedHost, sched=sched, 26 | period_us=period_us, 27 | cpu=cpu ) 28 | try: 29 | net = Mininet( topo=topo, host=host ) 30 | # pylint: disable=bare-except 31 | except: 32 | info( '*** Skipping host %s\n' % sched ) 33 | break 34 | net.start() 35 | net.pingAll() 36 | hosts = [ net.getNodeByName( h ) for h in topo.hosts() ] 37 | client, server = hosts[ 0 ], hosts[ -1 ] 38 | server.cmd( 'iperf -s -p 5001 &' ) 39 | waitListening( client, server, 5001 ) 40 | result = client.cmd( 'iperf -yc -t %s -c %s' % ( 41 | seconds, server.IP() ) ).split( ',' ) 42 | bps = float( result[ -1 ] ) 43 | server.cmdPrint( 'kill %iperf' ) 44 | net.stop() 45 | updated = results.get( sched, [] ) 46 | updated += [ ( cpu, bps ) ] 47 | results[ sched ] = updated 48 | 49 | return results 50 | 51 | 52 | def dump( results ): 53 | "Dump results" 54 | 55 | fmt = '%s\t%s\t%s' 56 | 57 | print() 58 | print((fmt % ( 'sched', 'cpu', 'client MB/s' ))) 59 | print() 60 | 61 | for sched in sorted( results.keys() ): 62 | entries = results[ sched ] 63 | for cpu, bps in entries: 64 | pct = '%.2f%%' % ( cpu * 100 ) 65 | mbps = bps / 1e6 66 | print((fmt % ( sched, pct, mbps ))) 67 | 68 | 69 | if __name__ == '__main__': 70 | setLogLevel( 'info' ) 71 | limits = [ .45, .4, .3, .2, .1 ] 72 | out = bwtest( limits ) 73 | dump( out ) 74 | -------------------------------------------------------------------------------- /examples/docker_cpuset.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | This example shows how to create a simple network and 5 | how to create docker containers (based on existing images) 6 | to it. 7 | """ 8 | 9 | from mininet.net import Containernet 10 | from mininet.node import Controller, Docker, OVSSwitch 11 | from mininet.cli import CLI 12 | from mininet.log import setLogLevel, info 13 | from mininet.link import TCLink, Link 14 | 15 | 16 | def topology(): 17 | 18 | "Create a network with some docker containers acting as hosts." 19 | 20 | net = Containernet(controller=Controller) 21 | 22 | info('*** Adding controller\n') 23 | net.addController('c0') 24 | 25 | info('*** Adding docker containers\n') 26 | d1 = net.addDocker('d1', ip='10.0.0.251', dimage="mpeuster/stress", cpuset_cpus="0,1") 27 | d1.sendCmd("./start.sh") 28 | 29 | info('*** Starting network\n') 30 | net.start() 31 | 32 | info('*** Running CLI\n') 33 | CLI(net) 34 | 35 | info('*** Stopping network') 36 | net.stop() 37 | 38 | if __name__ == '__main__': 39 | setLogLevel('info') 40 | topology() 41 | -------------------------------------------------------------------------------- /examples/dockerhosts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | This example shows how to create a simple network and 5 | how to create docker containers (based on existing images) 6 | to it. 7 | """ 8 | 9 | from mininet.net import Containernet 10 | from mininet.node import Controller, Docker, OVSSwitch 11 | from mininet.cli import CLI 12 | from mininet.log import setLogLevel, info 13 | from mininet.link import TCLink, Link 14 | 15 | 16 | def topology(): 17 | 18 | "Create a network with some docker containers acting as hosts." 19 | 20 | net = Containernet(controller=Controller) 21 | 22 | info('*** Adding controller\n') 23 | net.addController('c0') 24 | 25 | info('*** Adding hosts\n') 26 | h1 = net.addHost('h1') 27 | h2 = net.addHost('h2') 28 | 29 | info('*** Adding docker containers\n') 30 | d1 = net.addDocker('d1', ip='10.0.0.251', dimage="ubuntu:trusty") 31 | d2 = net.addDocker('d2', ip='10.0.0.252', dimage="ubuntu:trusty", cpu_period=50000, cpu_quota=25000) 32 | d3 = net.addHost( 33 | 'd3', ip='11.0.0.253', cls=Docker, dimage="ubuntu:trusty", cpu_shares=20) 34 | # using advanced features like volumes and exposed ports 35 | d5 = net.addDocker('d5', dimage="ubuntu:trusty", volumes=["/:/mnt/vol1:rw"], ports=[9999], port_bindings={9999:9999}, publish_all_ports=True) 36 | 37 | info('*** Adding switch\n') 38 | s1 = net.addSwitch('s1') 39 | s2 = net.addSwitch('s2', cls=OVSSwitch) 40 | s3 = net.addSwitch('s3') 41 | 42 | info('*** Creating links\n') 43 | net.addLink(h1, s1) 44 | net.addLink(s1, d1) 45 | net.addLink(h2, s2) 46 | net.addLink(d2, s2) 47 | net.addLink(s1, s2) 48 | #net.addLink(s1, s2, cls=TCLink, delay="100ms", bw=1, loss=10) 49 | # try to add a second interface to a docker container 50 | net.addLink(d2, s3, params1={"ip": "11.0.0.254/8"}) 51 | net.addLink(d3, s3) 52 | 53 | info('*** Starting network\n') 54 | net.start() 55 | 56 | net.ping([d1, d2]) 57 | 58 | # our extended ping functionality 59 | net.ping([d1], manualdestip="10.0.0.252") 60 | net.ping([d2, d3], manualdestip="11.0.0.254") 61 | 62 | info('*** Dynamically add a container at runtime\n') 63 | d4 = net.addDocker('d4', dimage="ubuntu:trusty") 64 | # we have to specify a manual ip when we add a link at runtime 65 | net.addLink(d4, s1, params1={"ip": "10.0.0.254/8"}) 66 | # other options to do this 67 | #d4.defaultIntf().ifconfig("10.0.0.254 up") 68 | #d4.setIP("10.0.0.254") 69 | 70 | # if this ping keeps failing, use some waiting 71 | # time.sleep(2) 72 | 73 | net.ping([d1], manualdestip="10.0.0.254") 74 | 75 | info('*** Running CLI\n') 76 | CLI(net) 77 | 78 | info('*** Stopping network') 79 | net.stop() 80 | 81 | if __name__ == '__main__': 82 | setLogLevel('info') 83 | topology() 84 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /examples/example-containers/Dockerfile.HAProxy: -------------------------------------------------------------------------------- 1 | FROM haproxy:1.7 2 | RUN apt-get update && apt-get install -y \ 3 | net-tools \ 4 | iputils-ping \ 5 | iproute \ 6 | htop \ 7 | ethtool \ 8 | wget \ 9 | tcpdump 10 | COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg 11 | COPY haproxy.sh ./ 12 | RUN chmod +x ./haproxy.sh 13 | 14 | ENTRYPOINT ./haproxy.sh 15 | -------------------------------------------------------------------------------- /examples/example-containers/Dockerfile.alpine3: -------------------------------------------------------------------------------- 1 | FROM alpine:latest 2 | 3 | RUN apk add --update --no-cache \ 4 | bash \ 5 | tcpdump \ 6 | iperf \ 7 | busybox-extras \ 8 | iproute2 \ 9 | iputils 10 | 11 | CMD /bin/bash 12 | -------------------------------------------------------------------------------- /examples/example-containers/Dockerfile.centos6: -------------------------------------------------------------------------------- 1 | FROM centos:6 2 | MAINTAINER manuel.peuster@uni-paderborn.de 3 | 4 | RUN yum update -y 5 | RUN yum install -y \ 6 | net-tools \ 7 | iputils 8 | 9 | CMD /bin/bash 10 | -------------------------------------------------------------------------------- /examples/example-containers/Dockerfile.centos7: -------------------------------------------------------------------------------- 1 | FROM centos:7 2 | MAINTAINER manuel.peuster@uni-paderborn.de 3 | 4 | RUN yum update -y 5 | RUN yum install -y \ 6 | net-tools \ 7 | iproute \ 8 | iputils-ping 9 | 10 | CMD /bin/bash 11 | -------------------------------------------------------------------------------- /examples/example-containers/Dockerfile.curl: -------------------------------------------------------------------------------- 1 | FROM ubuntu:trusty 2 | 3 | RUN apt-get update && apt-get install -y \ 4 | net-tools \ 5 | iputils-ping \ 6 | iproute2 \ 7 | curl 8 | 9 | CMD /bin/bash 10 | -------------------------------------------------------------------------------- /examples/example-containers/Dockerfile.iperf: -------------------------------------------------------------------------------- 1 | FROM ubuntu:trusty 2 | 3 | RUN apt-get update && apt-get install -y \ 4 | net-tools \ 5 | iputils-ping \ 6 | iproute2 \ 7 | telnet telnetd \ 8 | iperf 9 | 10 | CMD /bin/bash 11 | -------------------------------------------------------------------------------- /examples/example-containers/Dockerfile.lamp: -------------------------------------------------------------------------------- 1 | FROM fauria/lamp 2 | RUN apt-get update && apt-get install -y \ 3 | net-tools \ 4 | iputils-ping \ 5 | iproute \ 6 | ethtool \ 7 | wget \ 8 | tcpdump 9 | COPY ./lamp.sh ./ 10 | RUN chmod +x ./lamp.sh 11 | 12 | ENTRYPOINT ./lamp.sh 13 | -------------------------------------------------------------------------------- /examples/example-containers/Dockerfile.p4bmv2: -------------------------------------------------------------------------------- 1 | FROM ubuntu:bionic 2 | 3 | LABEL maintainer="Daniele Moro " 4 | 5 | RUN apt-get update && apt-get install -y \ 6 | net-tools \ 7 | iputils-ping \ 8 | iproute2 \ 9 | ethtool \ 10 | wget \ 11 | tcpdump \ 12 | curl \ 13 | python \ 14 | automake \ 15 | build-essential \ 16 | clang \ 17 | curl \ 18 | g++-6 \ 19 | git \ 20 | pkg-config \ 21 | python-setuptools \ 22 | python-pip \ 23 | libpython2.7-dev \ 24 | libevent-dev \ 25 | sudo 26 | 27 | COPY ./installP4.sh . 28 | COPY ./startP4.sh . 29 | RUN ./installP4.sh 30 | 31 | EXPOSE 9090/tcp 32 | 33 | ENTRYPOINT ./runBMv2.sh 34 | -------------------------------------------------------------------------------- /examples/example-containers/Dockerfile.ubuntu1404: -------------------------------------------------------------------------------- 1 | FROM ubuntu:trusty 2 | MAINTAINER manuel.peuster@uni-paderborn.de 3 | 4 | CMD /bin/bash 5 | -------------------------------------------------------------------------------- /examples/example-containers/Dockerfile.ubuntu1604: -------------------------------------------------------------------------------- 1 | FROM ubuntu:xenial 2 | MAINTAINER manuel.peuster@uni-paderborn.de 3 | 4 | RUN apt-get update && apt-get install -y \ 5 | net-tools \ 6 | iputils-ping \ 7 | iproute 8 | 9 | CMD /bin/bash 10 | -------------------------------------------------------------------------------- /examples/example-containers/Dockerfile.ubuntu1804: -------------------------------------------------------------------------------- 1 | FROM ubuntu:bionic 2 | MAINTAINER manuel.peuster@uni-paderborn.de 3 | 4 | RUN apt-get update && apt-get install -y \ 5 | net-tools \ 6 | iputils-ping \ 7 | iproute2 8 | 9 | CMD /bin/bash 10 | -------------------------------------------------------------------------------- /examples/example-containers/Dockerfile.ubuntu_p4: -------------------------------------------------------------------------------- 1 | FROM ubuntu:xenial 2 | RUN apt-get update && apt-get install -y \ 3 | net-tools \ 4 | iputils-ping \ 5 | iproute \ 6 | htop \ 7 | haproxy \ 8 | ethtool \ 9 | wget \ 10 | tcpdump 11 | -------------------------------------------------------------------------------- /examples/example-containers/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker build -t containernet_example:ubuntu1404 -f Dockerfile.ubuntu1404 . 4 | docker build -t containernet_example:ubuntu1604 -f Dockerfile.ubuntu1604 . 5 | docker build -t containernet_example:ubuntu1804 -f Dockerfile.ubuntu1804 . 6 | 7 | docker build -t containernet_example:centos6 -f Dockerfile.centos6 . 8 | docker build -t containernet_example:centos7 -f Dockerfile.centos7 . 9 | 10 | 11 | docker build -t containernet_example:lamp -f Dockerfile.lamp . 12 | docker build -t containernet_example:haproxy -f Dockerfile.HAProxy . 13 | docker build -t containernet_example:ubuntup4 -f Dockerfile.ubuntu_p4 . 14 | 15 | docker build -t containernet_example:nDPI -f Dockerfile.nDPI . 16 | docker build -t containernet_example:P4BMv2 -f Dockerfile.p4bmv2 . 17 | docker build -t containernet_example:alpine3 -f Dockerfile.alpine3 . 18 | -------------------------------------------------------------------------------- /examples/example-containers/haproxy.cfg: -------------------------------------------------------------------------------- 1 | global 2 | log 127.0.0.1 local0 notice 3 | maxconn 2000 4 | user root 5 | group root 6 | 7 | defaults 8 | log global 9 | mode http 10 | option httplog 11 | option dontlognull 12 | retries 3 13 | option redispatch 14 | timeout connect 5000 15 | timeout client 10000 16 | timeout server 10000 17 | 18 | frontend localnodes 19 | bind 0.0.0.0:80 20 | mode http 21 | default_backend nodes 22 | 23 | 24 | backend nodes 25 | mode http 26 | stats enable 27 | stats uri /haproxy?stats 28 | stats realm Strictly\ Private 29 | stats auth A_Username:YourPassword 30 | stats auth Another_User:passwd 31 | balance roundrobin 32 | option httpclose 33 | option forwardfor 34 | server lamp1 10.0.0.2:80 check 35 | server lamp2 10.0.0.3:80 check -------------------------------------------------------------------------------- /examples/example-containers/haproxy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Starting server...." 4 | haproxy -f /usr/local/etc/haproxy/haproxy.cfg 5 | echo ".... done." -------------------------------------------------------------------------------- /examples/example-containers/index.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/example-containers/lamp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Starting server...." 4 | /usr/sbin/run-lamp.sh 5 | echo ".... done." -------------------------------------------------------------------------------- /examples/example-containers/runBMv2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #INTF_LIST=`ls -l /sys/class/net | grep nw | awk '{print $9}'` 4 | INTF_LIST=`ls -l /sys/class/net | grep nw | awk '{print $9}'` 5 | n=1 6 | INTF_SW="" 7 | for i in $INTF_LIST 8 | do 9 | INTF_SW="$INTF_SW -i $n@$i" 10 | n=$(($n+1)) 11 | done 12 | echo $INTF_SW 13 | simple_switch_grpc --log-console --no-p4 $INTF_SW 14 | #echo $INTF_SW -------------------------------------------------------------------------------- /examples/example-containers/webserver_curl/Dockerfile.server: -------------------------------------------------------------------------------- 1 | # Use an official Python runtime as a parent image 2 | FROM python:2.7-slim 3 | 4 | # Set the working directory to /app 5 | WORKDIR /app 6 | 7 | # Copy the current directory contents into the container at /app 8 | COPY . /app 9 | 10 | # Install any needed packages specified in requirements.txt 11 | RUN apt-get update && apt-get install -y \ 12 | net-tools \ 13 | iputils-ping \ 14 | iproute2 \ 15 | curl 16 | RUN pip install -r requirements.txt 17 | 18 | CMD ["python", "app.py"] 19 | 20 | -------------------------------------------------------------------------------- /examples/example-containers/webserver_curl/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | app = Flask(__name__) 4 | 5 | 6 | @app.route("/") 7 | def hello1(): 8 | # returns 0 9 | return "0\n" 10 | 11 | @app.route("/") 12 | def hello(arg=0): 13 | # returns arg+1 14 | try: 15 | arg = int(arg) 16 | arg += 1 17 | except ValueError: 18 | pass 19 | return str(arg) + "\n" 20 | 21 | if __name__ == "__main__": 22 | app.run(host='0.0.0.0', port=80) 23 | 24 | -------------------------------------------------------------------------------- /examples/example-containers/webserver_curl/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | from mininet.topo import Topo 31 | from mininet.net import Mininet 32 | from mininet.node import Node 33 | from mininet.log import setLogLevel, info 34 | from mininet.cli import CLI 35 | 36 | class LinuxRouter( Node ): 37 | "A Node with IP forwarding enabled." 38 | 39 | def config( self, **params ): 40 | super( LinuxRouter, self).config( **params ) 41 | # Enable forwarding on the router 42 | self.cmd( 'sysctl net.ipv4.ip_forward=1' ) 43 | 44 | def terminate( self ): 45 | self.cmd( 'sysctl net.ipv4.ip_forward=0' ) 46 | super( LinuxRouter, self ).terminate() 47 | 48 | 49 | class NetworkTopo( Topo ): 50 | "A LinuxRouter connecting three IP subnets" 51 | 52 | def build( self, **_opts ): 53 | 54 | defaultIP = '192.168.1.1/24' # IP address for r0-eth1 55 | router = self.addNode( 'r0', cls=LinuxRouter, ip=defaultIP ) 56 | 57 | s1, s2, s3 = [ self.addSwitch( s ) for s in ('s1', 's2', 's3') ] 58 | 59 | self.addLink( s1, router, intfName2='r0-eth1', 60 | params2={ 'ip' : defaultIP } ) # for clarity 61 | self.addLink( s2, router, intfName2='r0-eth2', 62 | params2={ 'ip' : '172.16.0.1/12' } ) 63 | self.addLink( s3, router, intfName2='r0-eth3', 64 | params2={ 'ip' : '10.0.0.1/8' } ) 65 | 66 | h1 = self.addHost( 'h1', ip='192.168.1.100/24', 67 | defaultRoute='via 192.168.1.1' ) 68 | h2 = self.addHost( 'h2', ip='172.16.0.100/12', 69 | defaultRoute='via 172.16.0.1' ) 70 | h3 = self.addHost( 'h3', ip='10.0.0.100/8', 71 | defaultRoute='via 10.0.0.1' ) 72 | 73 | for h, s in [ (h1, s1), (h2, s2), (h3, s3) ]: 74 | self.addLink( h, s ) 75 | 76 | 77 | def run(): 78 | "Test linux router" 79 | topo = NetworkTopo() 80 | net = Mininet( topo=topo ) # controller is used by s1-s3 81 | net.start() 82 | info( '*** Routing Table on Router:\n' ) 83 | print((net[ 'r0' ].cmd( 'route' ))) 84 | CLI( net ) 85 | net.stop() 86 | 87 | if __name__ == '__main__': 88 | setLogLevel( 'info' ) 89 | run() 90 | -------------------------------------------------------------------------------- /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 __init__( self, n, **kwargs ): 25 | Topo.__init__( self, **kwargs ) 26 | 27 | h1, h2 = self.addHost( 'h1' ), self.addHost( 'h2' ) 28 | s1 = self.addSwitch( 's1' ) 29 | 30 | for _ in range( n ): 31 | self.addLink( s1, h1 ) 32 | self.addLink( s1, h2 ) 33 | 34 | if __name__ == '__main__': 35 | setLogLevel( 'info' ) 36 | runMultiLink() 37 | -------------------------------------------------------------------------------- /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 | from mininet.net import Mininet 12 | from mininet.node import Node 13 | from mininet.topo import SingleSwitchTopo 14 | from mininet.log import setLogLevel 15 | 16 | from select import poll, POLLIN 17 | from time import time 18 | 19 | def chunks( l, n ): 20 | "Divide list l into chunks of size n - thanks Stackoverflow" 21 | return [ l[ i: i + n ] for i in range( 0, len( l ), n ) ] 22 | 23 | def startpings( host, targetips ): 24 | "Tell host to repeatedly ping targets" 25 | 26 | targetips = ' '.join( targetips ) 27 | 28 | # Simple ping loop 29 | cmd = ( 'while true; do ' 30 | ' for ip in %s; do ' % targetips + 31 | ' echo -n %s "->" $ip ' % host.IP() + 32 | ' `ping -c1 -w 1 $ip | grep packets` ;' 33 | ' sleep 1;' 34 | ' done; ' 35 | 'done &' ) 36 | 37 | print(( '*** Host %s (%s) will be pinging ips: %s' % 38 | ( host.name, host.IP(), targetips ) )) 39 | 40 | host.cmd( cmd ) 41 | 42 | def multiping( netsize, chunksize, seconds): 43 | "Ping subsets of size chunksize in net of size netsize" 44 | 45 | # Create network and identify subnets 46 | topo = SingleSwitchTopo( netsize ) 47 | net = Mininet( topo=topo ) 48 | net.start() 49 | hosts = net.hosts 50 | subnets = chunks( hosts, chunksize ) 51 | 52 | # Create polling object 53 | fds = [ host.stdout.fileno() for host in hosts ] 54 | poller = poll() 55 | for fd in fds: 56 | poller.register( fd, POLLIN ) 57 | 58 | # Start pings 59 | for subnet in subnets: 60 | ips = [ host.IP() for host in subnet ] 61 | #adding bogus to generate packet loss 62 | ips.append( '10.0.0.200' ) 63 | for host in subnet: 64 | startpings( host, ips ) 65 | 66 | # Monitor output 67 | endTime = time() + seconds 68 | while time() < endTime: 69 | readable = poller.poll(1000) 70 | for fd, _mask in readable: 71 | node = Node.outToNode[ fd ] 72 | print(('%s:' % node.name, node.monitor().strip())) 73 | 74 | # Stop pings 75 | for host in hosts: 76 | host.cmd( 'kill %while' ) 77 | 78 | net.stop() 79 | 80 | 81 | if __name__ == '__main__': 82 | setLogLevel( 'info' ) 83 | multiping( netsize=20, chunksize=4, seconds=10 ) 84 | -------------------------------------------------------------------------------- /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 | from mininet.topo import SingleSwitchTopo 9 | from mininet.net import Mininet 10 | from mininet.log import setLogLevel 11 | 12 | from time import time 13 | from select import poll, POLLIN 14 | from subprocess import Popen, PIPE 15 | 16 | def monitorFiles( outfiles, seconds, timeoutms ): 17 | "Monitor set of files and return [(host, line)...]" 18 | devnull = open( '/dev/null', 'w' ) 19 | tails, fdToFile, fdToHost = {}, {}, {} 20 | for h, outfile in list(outfiles.items()): 21 | tail = Popen( [ 'tail', '-f', outfile ], 22 | stdout=PIPE, stderr=devnull ) 23 | fd = tail.stdout.fileno() 24 | tails[ h ] = tail 25 | fdToFile[ fd ] = tail.stdout 26 | fdToHost[ fd ] = h 27 | # Prepare to poll output files 28 | readable = poll() 29 | for t in list(tails.values()): 30 | readable.register( t.stdout.fileno(), POLLIN ) 31 | # Run until a set number of seconds have elapsed 32 | endTime = time() + seconds 33 | while time() < endTime: 34 | fdlist = readable.poll(timeoutms) 35 | if fdlist: 36 | for fd, _flags in fdlist: 37 | f = fdToFile[ fd ] 38 | host = fdToHost[ fd ] 39 | # Wait for a line of output 40 | line = f.readline().strip() 41 | yield host, line 42 | else: 43 | # If we timed out, return nothing 44 | yield None, '' 45 | for t in list(tails.values()): 46 | t.terminate() 47 | devnull.close() # Not really necessary 48 | 49 | 50 | def monitorTest( N=3, seconds=3 ): 51 | "Run pings and monitor multiple hosts" 52 | topo = SingleSwitchTopo( N ) 53 | net = Mininet( topo ) 54 | net.start() 55 | hosts = net.hosts 56 | print("Starting test...") 57 | server = hosts[ 0 ] 58 | outfiles, errfiles = {}, {} 59 | for h in hosts: 60 | # Create and/or erase output files 61 | outfiles[ h ] = '/tmp/%s.out' % h.name 62 | errfiles[ h ] = '/tmp/%s.err' % h.name 63 | h.cmd( 'echo >', outfiles[ h ] ) 64 | h.cmd( 'echo >', errfiles[ h ] ) 65 | # Start pings 66 | h.cmdPrint('ping', server.IP(), 67 | '>', outfiles[ h ], 68 | '2>', errfiles[ h ], 69 | '&' ) 70 | print(("Monitoring output for", seconds, "seconds")) 71 | for h, line in monitorFiles( outfiles, seconds, timeoutms=500 ): 72 | if h: 73 | print(('%s: %s' % ( h.name, line ))) 74 | for h in hosts: 75 | h.cmd('kill %ping') 76 | net.stop() 77 | 78 | 79 | if __name__ == '__main__': 80 | setLogLevel('info') 81 | monitorTest() 82 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | from mininet.cli import CLI 8 | from mininet.log import lg 9 | from mininet.topolib import TreeNet 10 | 11 | if __name__ == '__main__': 12 | lg.setLogLevel( 'info') 13 | net = TreeNet( depth=1, fanout=4 ) 14 | # Add NAT connectivity 15 | net.addNAT().configDefault() 16 | net.start() 17 | print("*** Hosts are running and should have internet connectivity") 18 | print("*** Type 'exit' or control-D to shut down network") 19 | CLI( net ) 20 | # Shut down NAT 21 | net.stop() 22 | -------------------------------------------------------------------------------- /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 __init__(self, n=2, **opts): 31 | Topo.__init__(self, **opts) 32 | 33 | # set up inet switch 34 | inetSwitch = self.addSwitch('s0') 35 | # add inet host 36 | inetHost = self.addHost('h0') 37 | self.addLink(inetSwitch, inetHost) 38 | 39 | # add local nets 40 | for i in irange(1, n): 41 | inetIntf = 'nat%d-eth0' % i 42 | localIntf = 'nat%d-eth1' % i 43 | localIP = '192.168.%d.1' % i 44 | localSubnet = '192.168.%d.0/24' % i 45 | natParams = { 'ip' : '%s/24' % localIP } 46 | # add NAT to topology 47 | nat = self.addNode('nat%d' % i, cls=NAT, subnet=localSubnet, 48 | inetIntf=inetIntf, localIntf=localIntf) 49 | switch = self.addSwitch('s%d' % i) 50 | # connect NAT to inet and local switches 51 | self.addLink(nat, inetSwitch, intfName1=inetIntf) 52 | self.addLink(nat, switch, intfName1=localIntf, params1=natParams) 53 | # add host and connect to local switch 54 | host = self.addHost('h%d' % i, 55 | ip='192.168.%d.100/24' % i, 56 | defaultRoute='via %s' % localIP) 57 | self.addLink(host, switch) 58 | 59 | def run(): 60 | "Create network and run the CLI" 61 | topo = InternetTopo() 62 | net = Mininet(topo=topo) 63 | net.start() 64 | CLI(net) 65 | net.stop() 66 | 67 | if __name__ == '__main__': 68 | setLogLevel('info') 69 | run() 70 | -------------------------------------------------------------------------------- /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 | from mininet.net import Mininet 10 | from mininet.node import Controller 11 | from mininet.log import setLogLevel, info, warn 12 | 13 | def validatePort( switch, intf ): 14 | "Validate intf's OF port number" 15 | ofport = int( switch.cmd( 'ovs-vsctl get Interface', intf, 16 | 'ofport' ) ) 17 | if ofport != switch.ports[ intf ]: 18 | warn( 'WARNING: ofport for', intf, 'is actually', ofport, '\n' ) 19 | return 0 20 | else: 21 | return 1 22 | 23 | def testPortNumbering(): 24 | 25 | """Test port numbering: 26 | Create a network with 5 hosts (using Mininet's 27 | mid-level API) and check that implicit and 28 | explicit port numbering works as expected.""" 29 | 30 | net = Mininet( controller=Controller ) 31 | 32 | info( '*** Adding controller\n' ) 33 | net.addController( 'c0' ) 34 | 35 | info( '*** Adding hosts\n' ) 36 | h1 = net.addHost( 'h1', ip='10.0.0.1' ) 37 | h2 = net.addHost( 'h2', ip='10.0.0.2' ) 38 | h3 = net.addHost( 'h3', ip='10.0.0.3' ) 39 | h4 = net.addHost( 'h4', ip='10.0.0.4' ) 40 | h5 = net.addHost( 'h5', ip='10.0.0.5' ) 41 | 42 | info( '*** Adding switch\n' ) 43 | s1 = net.addSwitch( 's1' ) 44 | 45 | info( '*** Creating links\n' ) 46 | # host 1-4 connect to ports 1-4 on the switch 47 | net.addLink( h1, s1 ) 48 | net.addLink( h2, s1 ) 49 | net.addLink( h3, s1 ) 50 | net.addLink( h4, s1 ) 51 | # specify a different port to connect host 5 to on the switch. 52 | net.addLink( h5, s1, port1=1, port2= 9) 53 | 54 | info( '*** Starting network\n' ) 55 | net.start() 56 | 57 | # print the interfaces and their port numbers 58 | info( '\n*** printing and validating the ports ' 59 | 'running on each interface\n' ) 60 | for intfs in s1.intfList(): 61 | if not intfs.name == "lo": 62 | info( intfs, ': ', s1.ports[intfs], 63 | '\n' ) 64 | info( 'Validating that', intfs, 65 | 'is actually on port', s1.ports[intfs], '... ' ) 66 | if validatePort( s1, intfs ): 67 | info( 'Validated.\n' ) 68 | print('\n') 69 | 70 | # test the network with pingall 71 | net.pingAll() 72 | print('\n') 73 | 74 | info( '*** Stopping network' ) 75 | net.stop() 76 | 77 | if __name__ == '__main__': 78 | setLogLevel( 'info' ) 79 | testPortNumbering() 80 | -------------------------------------------------------------------------------- /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 | from mininet.net import Mininet 9 | from mininet.node import CPULimitedHost 10 | from mininet.topo import SingleSwitchTopo 11 | from mininet.log import setLogLevel 12 | from mininet.util import custom, pmonitor 13 | 14 | def monitorhosts( hosts=5, sched='cfs' ): 15 | "Start a bunch of pings and monitor them using popen" 16 | mytopo = SingleSwitchTopo( hosts ) 17 | cpu = .5 / hosts 18 | myhost = custom( CPULimitedHost, cpu=cpu, sched=sched ) 19 | net = Mininet( topo=mytopo, host=myhost ) 20 | net.start() 21 | # Start a bunch of pings 22 | popens = {} 23 | last = net.hosts[ -1 ] 24 | for host in net.hosts: 25 | popens[ host ] = host.popen( "ping -c5 %s" % last.IP() ) 26 | last = host 27 | # Monitor them and print output 28 | for host, line in pmonitor( popens ): 29 | if host: 30 | print(("<%s>: %s" % ( host.name, line.strip() ))) 31 | # Done 32 | net.stop() 33 | 34 | if __name__ == '__main__': 35 | setLogLevel( 'info' ) 36 | monitorhosts( hosts=5 ) 37 | -------------------------------------------------------------------------------- /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 time import time 9 | from signal import SIGINT 10 | 11 | def pmonitorTest( N=3, seconds=10 ): 12 | "Run pings and monitor multiple hosts using pmonitor" 13 | topo = SingleSwitchTopo( N ) 14 | net = Mininet( topo ) 15 | net.start() 16 | hosts = net.hosts 17 | print("Starting test...") 18 | server = hosts[ 0 ] 19 | popens = {} 20 | for h in hosts: 21 | popens[ h ] = h.popen('ping', server.IP() ) 22 | print("Monitoring output for", seconds, "seconds") 23 | endTime = time() + seconds 24 | for h, line in pmonitor( popens, timeoutms=500 ): 25 | if h: 26 | print('<%s>: %s' % ( h.name, line ), end=' ') 27 | if time() >= endTime: 28 | for p in list(popens.values()): 29 | p.send_signal( SIGINT ) 30 | net.stop() 31 | 32 | if __name__ == '__main__': 33 | pmonitorTest() 34 | -------------------------------------------------------------------------------- /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 | from mininet.net import Mininet 12 | from mininet.node import Node 13 | from mininet.link import Link 14 | from mininet.log import setLogLevel, info 15 | from mininet.util import quietRun 16 | 17 | from time import sleep 18 | 19 | def scratchNet( cname='controller', cargs='-v ptcp:' ): 20 | "Create network from scratch using Open vSwitch." 21 | 22 | info( "*** Creating nodes\n" ) 23 | controller = Node( 'c0', inNamespace=False ) 24 | switch = Node( 's0', inNamespace=False ) 25 | h0 = Node( 'h0' ) 26 | h1 = Node( 'h1' ) 27 | 28 | info( "*** Creating links\n" ) 29 | Link( h0, switch ) 30 | Link( h1, switch ) 31 | 32 | info( "*** Configuring hosts\n" ) 33 | h0.setIP( '192.168.123.1/24' ) 34 | h1.setIP( '192.168.123.2/24' ) 35 | info( str( h0 ) + '\n' ) 36 | info( str( h1 ) + '\n' ) 37 | 38 | info( "*** Starting network using Open vSwitch\n" ) 39 | controller.cmd( cname + ' ' + cargs + '&' ) 40 | switch.cmd( 'ovs-vsctl del-br dp0' ) 41 | switch.cmd( 'ovs-vsctl add-br dp0' ) 42 | for intf in list(switch.intfs.values()): 43 | print((switch.cmd( 'ovs-vsctl add-port dp0 %s' % intf ))) 44 | 45 | # Note: controller and switch are in root namespace, and we 46 | # can connect via loopback interface 47 | switch.cmd( 'ovs-vsctl set-controller dp0 tcp:127.0.0.1:6633' ) 48 | 49 | info( '*** Waiting for switch to connect to controller' ) 50 | while 'is_connected' not in quietRun( 'ovs-vsctl show' ): 51 | sleep( 1 ) 52 | info( '.' ) 53 | info( '\n' ) 54 | 55 | info( "*** Running test\n" ) 56 | h0.cmdPrint( 'ping -c1 ' + h1.IP() ) 57 | 58 | info( "*** Stopping network\n" ) 59 | controller.cmd( 'kill %' + cname ) 60 | switch.cmd( 'ovs-vsctl del-br dp0' ) 61 | switch.deleteIntfs() 62 | info( '\n' ) 63 | 64 | if __name__ == '__main__': 65 | setLogLevel( 'info' ) 66 | info( '*** Scratch network demo (kernel datapath)\n' ) 67 | Mininet.init() 68 | scratchNet() 69 | -------------------------------------------------------------------------------- /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( i ) for i in (sintf1, 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 | -------------------------------------------------------------------------------- /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 | from mininet.topo import Topo 13 | from mininet.net import Mininet 14 | from mininet.node import CPULimitedHost 15 | from mininet.link import TCLink 16 | from mininet.util import dumpNodeConnections 17 | from mininet.log import setLogLevel 18 | 19 | from sys import argv 20 | 21 | class SingleSwitchTopo(Topo): 22 | "Single switch connected to n hosts." 23 | def __init__(self, n=2, lossy=True, **opts): 24 | Topo.__init__(self, **opts) 25 | switch = self.addSwitch('s1') 26 | for h in range(n): 27 | # Each host gets 50%/n of system CPU 28 | host = self.addHost('h%s' % (h + 1), 29 | cpu=.5 / n) 30 | if lossy: 31 | # 10 Mbps, 5ms delay, 10% packet loss 32 | self.addLink(host, switch, 33 | bw=10, delay='5ms', loss=10, use_htb=True) 34 | else: 35 | # 10 Mbps, 5ms delay, no packet loss 36 | self.addLink(host, switch, 37 | bw=10, delay='5ms', loss=0, use_htb=True) 38 | 39 | 40 | def perfTest( lossy=True ): 41 | "Create network and run simple performance test" 42 | topo = SingleSwitchTopo( n=4, lossy=lossy ) 43 | net = Mininet( topo=topo, 44 | host=CPULimitedHost, link=TCLink, 45 | autoStaticArp=True ) 46 | net.start() 47 | print("Dumping host connections") 48 | dumpNodeConnections(net.hosts) 49 | print("Testing bandwidth between h1 and h4") 50 | h1, h4 = net.getNodeByName('h1', 'h4') 51 | net.iperf( ( h1, h4 ), l4Type='UDP' ) 52 | net.stop() 53 | 54 | if __name__ == '__main__': 55 | setLogLevel( 'info' ) 56 | # Prevent test_simpleperf from failing due to packet loss 57 | perfTest( lossy=( 'testmode' not in argv ) ) 58 | -------------------------------------------------------------------------------- /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 24 | from mininet.node import Node 25 | from mininet.topolib import TreeTopo 26 | from mininet.util import waitListening 27 | 28 | def TreeNet( depth=1, fanout=2, **kwargs ): 29 | "Convenience function for creating tree networks." 30 | topo = TreeTopo( depth, fanout ) 31 | return Mininet( topo, **kwargs ) 32 | 33 | def connectToRootNS( network, switch, ip, routes ): 34 | """Connect hosts to root namespace via switch. Starts network. 35 | network: Mininet() network object 36 | switch: switch to connect to root namespace 37 | ip: IP address for root namespace node 38 | routes: host networks to route to""" 39 | # Create a node in root namespace and link to switch 0 40 | root = Node( 'root', inNamespace=False ) 41 | intf = network.addLink( root, switch ).intf1 42 | root.setIP( ip, intf=intf ) 43 | # Start network that now includes link to root namespace 44 | network.start() 45 | # Add routes from root ns to hosts 46 | for route in routes: 47 | root.cmd( 'route add -net ' + route + ' dev ' + str( intf ) ) 48 | 49 | def sshd( network, cmd='/usr/sbin/sshd', opts='-D', 50 | ip='10.123.123.1/32', routes=None, switch=None ): 51 | """Start a network, connect it to root ns, and run sshd on all hosts. 52 | ip: root-eth0 IP address in root namespace (10.123.123.1/32) 53 | routes: Mininet host networks to route to (10.0/24) 54 | switch: Mininet switch to connect to root namespace (s1)""" 55 | if not switch: 56 | switch = network[ 's1' ] # switch to use 57 | if not routes: 58 | routes = [ '10.0.0.0/24' ] 59 | connectToRootNS( network, switch, ip, routes ) 60 | for host in network.hosts: 61 | host.cmd( cmd + ' ' + opts + '&' ) 62 | print("*** Waiting for ssh daemons to start") 63 | for server in network.hosts: 64 | waitListening( server=server, port=22, timeout=5 ) 65 | 66 | print() 67 | print("*** Hosts are running sshd at the following addresses:") 68 | print() 69 | for host in network.hosts: 70 | print((host.name, host.IP())) 71 | print() 72 | print("*** Type 'exit' or control-D to shut down network") 73 | CLI( network ) 74 | for host in network.hosts: 75 | host.cmd( 'kill %' + cmd ) 76 | network.stop() 77 | 78 | if __name__ == '__main__': 79 | lg.setLogLevel( 'info') 80 | net = TreeNet( depth=1, fanout=4 ) 81 | # get sshd args from the command line or use default args 82 | # useDNS=no -u0 to avoid reverse DNS lookup timeout 83 | argvopts = ' '.join( sys.argv[ 1: ] ) if len( sys.argv ) > 1 else ( 84 | '-D -o UseDNS=no -u0' ) 85 | sshd( net, opts=argvopts ) 86 | -------------------------------------------------------------------------------- /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 | MininetTestRunner( verbosity=verbosity ).run( testSuite ) 36 | 37 | if __name__ == '__main__': 38 | # get the directory containing example tests 39 | testDir = os.path.dirname( os.path.realpath( __file__ ) ) 40 | verbosity = 2 if '-v' in sys.argv else 1 41 | runTests( testDir, verbosity ) 42 | -------------------------------------------------------------------------------- /examples/test/test_baresshd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Tests for baresshd.py 5 | """ 6 | 7 | import unittest 8 | import pexpect 9 | from mininet.clean import cleanup, sh 10 | 11 | class testBareSSHD( unittest.TestCase ): 12 | 13 | opts = [ 'Welcome to h1', pexpect.EOF, pexpect.TIMEOUT ] 14 | 15 | def connected( self ): 16 | "Log into ssh server, check banner, then exit" 17 | p = pexpect.spawn( 'ssh 10.0.0.1 -o StrictHostKeyChecking=no -i /tmp/ssh/test_rsa exit' ) 18 | while True: 19 | index = p.expect( self.opts ) 20 | if index == 0: 21 | return True 22 | else: 23 | return False 24 | 25 | def setUp( self ): 26 | # verify that sshd is not running 27 | self.assertFalse( self.connected() ) 28 | # create public key pair for testing 29 | sh( 'rm -rf /tmp/ssh' ) 30 | sh( 'mkdir /tmp/ssh' ) 31 | sh( "ssh-keygen -t rsa -P '' -f /tmp/ssh/test_rsa" ) 32 | sh( 'cat /tmp/ssh/test_rsa.pub >> /tmp/ssh/authorized_keys' ) 33 | # run example with custom sshd args 34 | cmd = ( 'python -m mininet.examples.baresshd ' 35 | '-o AuthorizedKeysFile=/tmp/ssh/authorized_keys ' 36 | '-o StrictModes=no' ) 37 | p = pexpect.spawn( cmd ) 38 | runOpts = [ 'You may now ssh into h1 at 10.0.0.1', 39 | 'after 5 seconds, h1 is not listening on port 22', 40 | pexpect.EOF, pexpect.TIMEOUT ] 41 | while True: 42 | index = p.expect( runOpts ) 43 | if index == 0: 44 | break 45 | else: 46 | self.tearDown() 47 | self.fail( 'sshd failed to start in host h1' ) 48 | 49 | def testSSH( self ): 50 | "Simple test to verify that we can ssh into h1" 51 | result = False 52 | # try to connect up to 3 times; sshd can take a while to start 53 | result = self.connected() 54 | self.assertTrue( result ) 55 | 56 | def tearDown( self ): 57 | # kill the ssh process 58 | sh( "ps aux | grep 'ssh.*Banner' | awk '{ print $2 }' | xargs kill" ) 59 | cleanup() 60 | # remove public key pair 61 | sh( 'rm -rf /tmp/ssh' ) 62 | 63 | if __name__ == '__main__': 64 | unittest.main() 65 | -------------------------------------------------------------------------------- /examples/test/test_bind.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Tests for bind.py 5 | """ 6 | 7 | import unittest 8 | 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 | -------------------------------------------------------------------------------- /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 | 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 | -------------------------------------------------------------------------------- /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 | 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 | -------------------------------------------------------------------------------- /examples/test/test_controlnet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for controlnet.py 5 | """ 6 | 7 | import unittest 8 | 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 | -------------------------------------------------------------------------------- /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 client MB/s 9 | 10 | cfs 45.00% 13254.669841 11 | cfs 40.00% 11822.441399 12 | cfs 30.00% 5112.963009 13 | cfs 20.00% 3449.090009 14 | cfs 10.00% 2271.741564 15 | 16 | """ 17 | 18 | import unittest 19 | import pexpect 20 | import sys 21 | 22 | class testCPU( unittest.TestCase ): 23 | 24 | prompt = 'mininet>' 25 | 26 | @unittest.skipIf( '-quick' in sys.argv, 'long test' ) 27 | def testCPU( self ): 28 | "Verify that CPU utilization is monotonically decreasing for each scheduler" 29 | p = pexpect.spawn( 'python -m mininet.examples.cpu' ) 30 | # matches each line from results( shown above ) 31 | opts = [ '([a-z]+)\t([\d\.]+)%\t([\d\.]+)', 32 | pexpect.EOF ] 33 | scheds = [] 34 | while True: 35 | index = p.expect( opts, timeout=600 ) 36 | if index == 0: 37 | sched = p.match.group( 1 ) 38 | cpu = float( p.match.group( 2 ) ) 39 | bw = float( p.match.group( 3 ) ) 40 | if sched not in scheds: 41 | scheds.append( sched ) 42 | else: 43 | self.assertTrue( bw < previous_bw, 44 | "%f should be less than %f\n" % 45 | ( bw, previous_bw ) ) 46 | previous_bw = bw 47 | else: 48 | break 49 | 50 | self.assertTrue( len( scheds ) > 0 ) 51 | 52 | if __name__ == '__main__': 53 | unittest.main() 54 | -------------------------------------------------------------------------------- /examples/test/test_emptynet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for emptynet.py 5 | """ 6 | 7 | import unittest 8 | 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 | -------------------------------------------------------------------------------- /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 | 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.terminate() 61 | self.n0.terminate() 62 | 63 | if __name__ == '__main__': 64 | setLogLevel( 'warning' ) 65 | unittest.main() 66 | -------------------------------------------------------------------------------- /examples/test/test_intfoptions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for intfOptions.py 5 | """ 6 | 7 | import unittest 8 | 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 | -------------------------------------------------------------------------------- /examples/test/test_limit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for limit.py 5 | """ 6 | 7 | import unittest 8 | 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 | -------------------------------------------------------------------------------- /examples/test/test_linearbandwidth.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for linearbandwidth.py 5 | """ 6 | 7 | import unittest 8 | 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: %d bits/s across %d switches, ' 38 | 'previous: %d 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 | -------------------------------------------------------------------------------- /examples/test/test_linuxrouter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for linuxrouter.py 5 | """ 6 | 7 | import unittest 8 | 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | 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 | -------------------------------------------------------------------------------- /examples/test/test_multiping.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for multiping.py 5 | """ 6 | 7 | import unittest 8 | 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 ) 35 | else: 36 | self.assertEqual( received, 1 ) 37 | try: 38 | pings[ name ].remove( target ) 39 | except: 40 | pass 41 | else: 42 | break 43 | self.assertTrue( len( pings ) > 0 ) 44 | for t in list(pings.values()): 45 | self.assertEqual( len( t ), 0 ) 46 | 47 | if __name__ == '__main__': 48 | unittest.main() 49 | -------------------------------------------------------------------------------- /examples/test/test_multipoll.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for multipoll.py 5 | """ 6 | 7 | import unittest 8 | 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 = {} 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 list(pings.values()): 35 | self.assertTrue( count >= seconds ) 36 | 37 | if __name__ == '__main__': 38 | unittest.main() 39 | -------------------------------------------------------------------------------- /examples/test/test_multitest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for multitest.py 5 | """ 6 | 7 | import unittest 8 | 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 | -------------------------------------------------------------------------------- /examples/test/test_nat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for nat.py 5 | """ 6 | 7 | import unittest 8 | 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 | -------------------------------------------------------------------------------- /examples/test/test_natnet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for natnet.py 5 | """ 6 | 7 | import unittest 8 | 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 | -------------------------------------------------------------------------------- /examples/test/test_numberedports.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for numberedports.py 5 | """ 6 | 7 | import unittest 8 | 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 | -------------------------------------------------------------------------------- /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 | 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 list(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 | -------------------------------------------------------------------------------- /examples/test/test_scratchnet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for scratchnet.py 5 | """ 6 | 7 | import unittest 8 | 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 ) 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 | -------------------------------------------------------------------------------- /examples/test/test_simpleperf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for simpleperf.py 5 | """ 6 | 7 | import unittest 8 | 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 | -------------------------------------------------------------------------------- /examples/test/test_sshd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for sshd.py 5 | """ 6 | 7 | import unittest 8 | 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 | -------------------------------------------------------------------------------- /examples/test/test_tree1024.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for tree1024.py 5 | """ 6 | 7 | import unittest 8 | 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 | -------------------------------------------------------------------------------- /examples/test/test_treeping64.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for treeping64.py 5 | """ 6 | 7 | import unittest 8 | 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 | -------------------------------------------------------------------------------- /examples/test/test_vlanhost.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test for vlanhost.py 5 | """ 6 | 7 | import unittest 8 | 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /examples/treeping64.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | "Create a 64-node tree network, and test connectivity using ping." 4 | 5 | from mininet.log import setLogLevel 6 | from mininet.node import UserSwitch, OVSKernelSwitch # , KernelSwitch 7 | from mininet.topolib import TreeNet 8 | 9 | def treePing64(): 10 | "Run ping test on 64-node tree networks." 11 | 12 | results = {} 13 | switches = { # 'reference kernel': KernelSwitch, 14 | 'reference user': UserSwitch, 15 | 'Open vSwitch kernel': OVSKernelSwitch } 16 | 17 | for name in switches: 18 | print(("*** Testing", name, "datapath")) 19 | switch = switches[ name ] 20 | network = TreeNet( depth=2, fanout=8, switch=switch ) 21 | result = network.run( network.pingAll ) 22 | results[ name ] = result 23 | 24 | print() 25 | print("*** Tree network ping results:") 26 | for name in switches: 27 | print(("%s: %d%% packet loss" % ( name, results[ name ] ))) 28 | print() 29 | 30 | if __name__ == '__main__': 31 | setLogLevel( 'info' ) 32 | treePing64() 33 | -------------------------------------------------------------------------------- /mininet/__init__.py: -------------------------------------------------------------------------------- 1 | "Docstring to silence pylint; ignores --ignore option for __init__.py" 2 | -------------------------------------------------------------------------------- /mininet/ebpf.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from mininet.log import info, error 4 | from mininet.node import Host 5 | 6 | 7 | class EbpfXdpNode(Host): 8 | """ 9 | eBPF XDP node is an enhanced Mininet host that allows to install a specified XDP eBPF program on interfaces. 10 | It can load the default eBPF program or another one specified when loading. 11 | """ 12 | 13 | def __init__(self, name, ebpfProgram=None, **kwargs): 14 | self.defEbpfProgram = ebpfProgram 15 | self.ebpfProgramsDict = {} 16 | 17 | # call original Host.__init__ 18 | Host.__init__(self, name, **kwargs) 19 | 20 | def loadEbpfOnInterface(self, ebpfProgram=None, intf=None): 21 | """ 22 | Load the eBPF program on the interface 23 | :param ebpfProgram: 24 | :param intf: 25 | :return: 26 | """ 27 | ebpfProgram = self.defEbpfProgram if ebpfProgram is None else ebpfProgram 28 | if ebpfProgram is None: 29 | # Load the default eBPF Program 30 | error("No default eBPF program\n") 31 | return 32 | #TODO: what happen if the intf passed does not exist? 33 | intf_name = self.defaultIntf().name if intf is None else self.intf(intf).name 34 | if os.path.isfile(os.path.expanduser(ebpfProgram)): 35 | # TODO: check the output of the loading 36 | out = self.cmd("ip link set dev " + intf_name + " xdp obj " + ebpfProgram + " verb") 37 | info("%s loaded in %s\n" % (ebpfProgram, intf_name)) 38 | self.ebpfProgramsDict[self.intf(intf_name)] = ebpfProgram 39 | else: 40 | error("%s is not a file\n" % ebpfProgram) 41 | 42 | def unloadEbpfProgram(self, intf=None, ebpfProgram=None): 43 | """ 44 | Unload the eBPF program from the specified interface 45 | :param intf: 46 | :return: 47 | """ 48 | if ebpfProgram is not None: 49 | intf_name = "" 50 | for k, v in self.ebpfProgramsDict.items(): 51 | if v == ebpfProgram: 52 | intf_name = k.name 53 | break 54 | if intf_name == "": 55 | error("%s not loaded in any interface\n" % ebpfProgram) 56 | return 57 | elif self.intf(intf) in self.ebpfProgramsDict.keys(): 58 | intf_name = self.intf(intf).name 59 | else: 60 | error("In %s no eBPF program is loaded\n" % self.intf(intf)) 61 | return 62 | 63 | self.cmd("ip link set dev " + intf_name + " xdp off") 64 | 65 | # Remove the unloaded eBPF program from the dict 66 | self.ebpfProgramsDict.pop(self.intf(intf_name)) 67 | -------------------------------------------------------------------------------- /mininet/examples: -------------------------------------------------------------------------------- 1 | ../examples -------------------------------------------------------------------------------- /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/topolib.py: -------------------------------------------------------------------------------- 1 | "Library of potentially useful topologies for Mininet" 2 | 3 | from mininet.topo import Topo 4 | from mininet.net import Mininet, Containernet 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 | def TreeContainerNet( depth=1, fanout=2, dimage="ubuntu:trusty", **kwargs ): 42 | "Convenience function for creating tree networks with Docker." 43 | topo = TreeTopo( depth, fanout ) 44 | return Containernet( topo, dimage, **kwargs ) 45 | 46 | 47 | class TorusTopo( Topo ): 48 | """2-D Torus topology 49 | WARNING: this topology has LOOPS and WILL NOT WORK 50 | with the default controller or any Ethernet bridge 51 | without STP turned on! It can be used with STP, e.g.: 52 | # mn --topo torus,3,3 --switch lxbr,stp=1 --test pingall""" 53 | 54 | def build( self, x, y, n=1 ): 55 | """x: dimension of torus in x-direction 56 | y: dimension of torus in y-direction 57 | n: number of hosts per switch""" 58 | if x < 3 or y < 3: 59 | raise Exception( 'Please use 3x3 or greater for compatibility ' 60 | 'with 2.1' ) 61 | if n == 1: 62 | genHostName = lambda loc, k: 'h%s' % ( loc ) 63 | else: 64 | genHostName = lambda loc, k: 'h%sx%d' % ( loc, k ) 65 | 66 | hosts, switches, dpid = {}, {}, 0 67 | # Create and wire interior 68 | for i in range( 0, x ): 69 | for j in range( 0, y ): 70 | loc = '%dx%d' % ( i + 1, j + 1 ) 71 | # dpid cannot be zero for OVS 72 | dpid = ( i + 1 ) * 256 + ( j + 1 ) 73 | switch = switches[ i, j ] = self.addSwitch( 74 | 's' + loc, dpid='%x' % dpid ) 75 | for k in range( 0, n ): 76 | host = hosts[ i, j, k ] = self.addHost( 77 | genHostName( loc, k + 1 ) ) 78 | self.addLink( host, switch ) 79 | # Connect switches 80 | for i in range( 0, x ): 81 | for j in range( 0, y ): 82 | sw1 = switches[ i, j ] 83 | sw2 = switches[ i, ( j + 1 ) % y ] 84 | sw3 = switches[ ( i + 1 ) % x, j ] 85 | self.addLink( sw1, sw2 ) 86 | self.addLink( sw1, sw3 ) 87 | 88 | # pylint: enable=arguments-differ 89 | -------------------------------------------------------------------------------- /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 CONTAINERNET_VERSION 12 | 13 | scripts = [ join( 'bin', filename ) for filename in [ 'mn' ] ] 14 | 15 | modname = distname = 'mininet' 16 | 17 | setup( 18 | name=distname, 19 | version=CONTAINERNET_VERSION, 20 | description='Mininet fork that adds Container support.', 21 | author='Manuel Peuster', 22 | author_email='manuel.peuster@upb.de', 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 | Mininet author: Bob Lantz (rlantz@cs.stanford.edu) 30 | 31 | Containernet is a fork of Mininet that allows 32 | to use Docker containers as hosts in emulated 33 | networks. 34 | """, 35 | classifiers=[ 36 | "License :: OSI Approved :: BSD License", 37 | "Programming Language :: Python", 38 | "Development Status :: 5 - Production/Stable", 39 | "Intended Audience :: Developers", 40 | "Topic :: System :: Emulators", 41 | ], 42 | keywords='networking emulator protocol Internet OpenFlow SDN', 43 | license='BSD', 44 | install_requires=[ 45 | 'setuptools', 46 | 'urllib3', 47 | 'docker<=4.1.0', 48 | 'python-iptables', 49 | 'pytest', 50 | # fixes: https://github.com/pytest-dev/pytest/issues/4770 51 | 'more-itertools<=5.0.0' 52 | ], 53 | scripts=scripts, 54 | ) 55 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /util/docker/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -e 2 | 3 | # start OVS 4 | service openvswitch-switch start 5 | 6 | # check if docker socket is mounted 7 | if [ ! -S /var/run/docker.sock ]; then 8 | echo 'Error: the Docker socket file "/var/run/docker.sock" was not found. It should be mounted as a volume.' 9 | exit 1 10 | fi 11 | 12 | # this cannot be done from the Dockerfile since we have the socket not mounted during build 13 | set +e 14 | echo 'Pulling the "ubuntu:trusty" and "ubuntu:xenial" image for later use...' 15 | docker pull 'ubuntu:trusty' 16 | docker pull 'ubuntu:xenial' 17 | set -e 18 | 19 | echo "Welcome to Containernet running within a Docker container ..." 20 | 21 | if [[ $# -eq 0 ]]; then 22 | exec /bin/bash 23 | else 24 | exec $* 25 | fi 26 | -------------------------------------------------------------------------------- /util/docker/entrypoint_centos.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -e 2 | 3 | # start OVS 4 | /usr/share/openvswitch/scripts/ovs-ctl start --system-id=random 5 | 6 | # check if docker socket is mounted 7 | if [ ! -S /var/run/docker.sock ]; then 8 | echo 'Error: the Docker socket file "/var/run/docker.sock" was not found. It should be mounted as a volume.' 9 | exit 1 10 | fi 11 | 12 | # this cannot be done from the Dockerfile since we have the socket not mounted during build 13 | set +e 14 | echo 'Pulling the "centos:7" image for later use...' 15 | docker pull 'centos:7' 16 | set -e 17 | 18 | echo "Welcome to Containernet running within a Docker container ..." 19 | 20 | if [[ $# -eq 0 ]]; then 21 | exec /bin/bash 22 | else 23 | exec $* 24 | fi 25 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /util/install-p4-dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ############ 4 | # Tested on a clean Ubuntu 20.04 LTS installation 5 | # 6 | # Required specs: 7 | # - At least 2GB of RAM 8 | # - At least 12GB of FREE disk space 9 | ############ 10 | 11 | #Install everything in the home directory 12 | cd 13 | 14 | #Install basic packages 15 | sudo apt update 16 | 17 | #Install dependencies with the script from https://github.com/jafingerhut/p4-guide/blob/master/bin/README-install-troubleshooting.md 18 | git clone https://github.com/jafingerhut/p4-guide 19 | ./p4-guide/bin/install-p4dev-v4.sh |& tee dependencies_log.txt 20 | 21 | #Add paths to environment 22 | cat p4setup.bash >> .profile 23 | 24 | #Uninstall mininet pip package installed by the script, it will be substituded by the one of Containernet 25 | #Otherwise 'sudo python3 setup.py install' doesn't work correctly 26 | sudo pip3 uninstall -y mininet -------------------------------------------------------------------------------- /util/install-p4c-xdp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Build libbpf 4 | sudo apt install -y libelf-dev clang 5 | cd ~/p4c/backends/ebpf/ 6 | sudo ./build_libbpf 7 | 8 | #Clone 9 | cd ~/p4c/ 10 | mkdir extensions 11 | cd extensions 12 | git clone https://github.com/vmware/p4c-xdp.git 13 | ln -s ~/p4c p4c-xdp/p4c 14 | 15 | #Make 16 | cd ~/p4c/ 17 | mkdir -p build 18 | cd build/ 19 | cmake .. 20 | make 21 | 22 | #Make soft links 23 | cd ~/p4c/extensions/p4c-xdp 24 | ln -s ~/p4c/build/p4c-xdp p4c-xdp 25 | ln -s ~/p4c/backends/ebpf/run-ebpf-test.py run-ebpf-test.py 26 | 27 | #Run tests 28 | cd ~/p4c/build/ 29 | make check-xdp 30 | 31 | #Add needed env variables and load configuration 32 | echo "Adding env variables to .profile ..." 33 | echo 'export P4C="$HOME/p4c"' >> $HOME/.profile 34 | echo 'export PATH="$P4C/extensions/p4c-xdp:$PATH"' >> $HOME/.profile -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | container=`docker ps | grep "mn.$host$" | awk '{print $10};'` 13 | pid=`ps ax | grep "mininet:$host$" | grep bash | grep -v mnexec | awk '{print $1};'` 14 | 15 | if [ "$container" == "" ]; then 16 | if echo $pid | grep -q ' '; then 17 | echo "Error: found multiple mininet:$host processes" 18 | exit 2 19 | fi 20 | fi 21 | 22 | if [ "$container" == "" ] && [ "$pid" == "" ]; then 23 | echo "Could not find Mininet host $host" 24 | exit 3 25 | fi 26 | 27 | if [ -z $2 ]; then 28 | cmd='bash' 29 | else 30 | shift 31 | cmd=$* 32 | fi 33 | 34 | cgroup=/sys/fs/cgroup/cpu/$host 35 | if [ -d "$cgroup" ]; then 36 | cg="-g $host" 37 | fi 38 | 39 | # Check whether host should be running in a chroot dir 40 | rootdir="/var/run/mn/$host/root" 41 | if [ -d $rootdir -a -x $rootdir/bin/bash ]; then 42 | cmd="'cd `pwd`; exec $cmd'" 43 | cmd="chroot $rootdir /bin/bash -c $cmd" 44 | fi 45 | 46 | if [ "$container" != "" ]; then 47 | cmd="docker exec $container bash -c '$cmd'" 48 | else 49 | cmd="exec sudo mnexec $cg -a $pid $cmd" 50 | fi 51 | eval $cmd 52 | -------------------------------------------------------------------------------- /util/motd: -------------------------------------------------------------------------------- 1 | _____________________________________________________________________ 2 | 3 | Welcome to Containernet! 4 | 5 | You can run the example topology with the following command: 6 | > sudo python containernet/examples/dockerhosts.py 7 | 8 | Have fun! 9 | 10 | Manuel Peuster 11 | _____________________________________________________________________ 12 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------