6 Topotests is a suite of topology tests for FRR built on top of Mininet.
11 Only tested with Ubuntu 16.04 and Ubuntu 18.04 (which uses Mininet 2.2.x).
13 Instructions are the same for all setups (i.e. ExaBGP is only used for BGP
16 Installing Mininet Infrastructure
17 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21 apt-get install mininet
22 apt-get install python-pip
23 apt-get install iproute
26 pip install "pytest<5"
27 pip install "scapy>=2.4.2"
28 pip install exabgp==3.4.17 (Newer 4.0 version of exabgp is not yet
30 useradd -d /var/run/exabgp/ -s /bin/false exabgp
35 Optional, will give better output.
40 disable apport (which move core files)
42 Set ``enabled=0`` in ``/etc/default/apport``.
44 Next, update security limits by changing :file:`/etc/security/limits.conf` to::
46 #<domain> <type> <item> <value>
48 root soft core unlimited
50 root hard core unlimited
52 Reboot for options to take effect.
54 SNMP Utilities Installation
55 """""""""""""""""""""""""""
57 To run SNMP test you need to install SNMP utilities and MIBs. Unfortunately
58 there are some errors in the upstream MIBS which need to be patched up. The
59 following steps will get you there on Ubuntu 20.04.
63 apt install snmpd snmp
64 apt install snmp-mibs-downloader
66 wget http://www.iana.org/assignments/ianaippmmetricsregistry-mib/ianaippmmetricsregistry-mib -O /usr/share/snmp/mibs/iana/IANA-IPPM-METRICS-REGISTRY-MIB
67 wget http://pastebin.com/raw.php?i=p3QyuXzZ -O /usr/share/snmp/mibs/ietf/SNMPv2-PDU
68 wget http://pastebin.com/raw.php?i=gG7j8nyk -O /usr/share/snmp/mibs/ietf/IPATM-IPMC-MIB
69 edit /etc/snmp/snmp.conf to look like this
70 # As the snmp packages come without MIB files due to license reasons, loading
71 # of MIBs is disabled by default. If you added the MIBs you can reenable
72 # loading them by commenting out the following line.
79 FRR needs to be installed separately. It is assume to be configured like the
80 standard Ubuntu Packages:
82 - Binaries in :file:`/usr/lib/frr`
83 - State Directory :file:`/var/run/frr`
84 - Running under user ``frr``, group ``frr``
85 - vtygroup: ``frrvty``
86 - config directory: :file:`/etc/frr`
87 - For FRR Packages, install the dbg package as well for coredump decoding
89 No FRR config needs to be done and no FRR daemons should be run ahead of the
90 test. They are all started as part of the test.
95 If you prefer to manually build FRR, then use the following suggested config:
101 --localstatedir=/var/run/frr \
102 --sbindir=/usr/lib/frr \
103 --sysconfdir=/etc/frr \
107 --enable-multipath=64 \
110 --enable-vty-group=frrvty \
111 --enable-snmp=agentx \
112 --with-pkg-extra-version=-my-manual-build
114 And create ``frr`` user and ``frrvty`` group as follows:
118 addgroup --system --gid 92 frr
119 addgroup --system --gid 85 frrvty
120 adduser --system --ingroup frr --home /var/run/frr/ \
121 --gecos "FRRouting suite" --shell /bin/false frr
122 usermod -G frrvty frr
127 Execute all tests with output to console
128 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
132 py.test -s -v --tb=no
134 The above command must be executed from inside the topotests directory.
136 All test\_\* scripts in subdirectories are detected and executed (unless
137 disabled in ``pytest.ini`` file).
139 ``--tb=no`` disables the python traceback which might be irrelevant unless the
140 test script itself is debugged.
150 For example, and assuming you are inside the frr directory:
154 cd tests/topotests/bgp_l3vpn_to_bgp_vrf
155 ./test_bgp_l3vpn_to_bgp_vrf.py
157 For further options, refer to pytest documentation.
159 Test will set exit code which can be used with ``git bisect``.
161 For the simulated topology, see the description in the python file.
163 If you need to clear the mininet setup between tests (if it isn't cleanly
164 shutdown), then use the ``mn -c`` command to clean up the environment.
166 StdErr log from daemos after exit
167 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
169 To enable the reporting of any messages seen on StdErr after the daemons exit,
170 the following env variable can be set::
172 export TOPOTESTS_CHECK_STDERR=Yes
174 (The value doesn't matter at this time. The check is whether the env
175 variable exists or not.) There is no pass/fail on this reporting; the
176 Output will be reported to the console.
178 Collect Memory Leak Information
179 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
181 FRR processes can report unfreed memory allocations upon exit. To
182 enable the reporting of memory leaks, define an environment variable
183 ``TOPOTESTS_CHECK_MEMLEAK`` with the file prefix, i.e.::
185 export TOPOTESTS_CHECK_MEMLEAK="/home/mydir/memleak_"
187 This will enable the check and output to console and the writing of
188 the information to files with the given prefix (followed by testname),
189 ie :file:`/home/mydir/memcheck_test_bgp_multiview_topo1.txt` in case
192 Running Topotests with AddressSanitizer
193 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
195 Topotests can be run with AddressSanitizer. It requires GCC 4.8 or newer.
196 (Ubuntu 16.04 as suggested here is fine with GCC 5 as default). For more
197 information on AddressSanitizer, see
198 https://github.com/google/sanitizers/wiki/AddressSanitizer.
200 The checks are done automatically in the library call of ``checkRouterRunning``
201 (ie at beginning of tests when there is a check for all daemons running). No
202 changes or extra configuration for topotests is required beside compiling the
203 suite with AddressSanitizer enabled.
205 If a daemon crashed, then the errorlog is checked for AddressSanitizer output.
206 If found, then this is added with context (calling test) to
207 :file:`/tmp/AddressSanitizer.txt` in Markdown compatible format.
209 Compiling for GCC AddressSanitizer requires to use ``gcc`` as a linker as well
210 (instead of ``ld``). Here is a suggest way to compile frr with AddressSanitizer
211 for ``master`` branch:
215 git clone https://github.com/FRRouting/frr.git
219 --enable-address-sanitizer \
220 --prefix=/usr/lib/frr --sysconfdir=/etc/frr \
221 --localstatedir=/var/run/frr \
222 --sbindir=/usr/lib/frr --bindir=/usr/lib/frr \
223 --enable-exampledir=/usr/lib/frr/examples \
224 --with-moduledir=/usr/lib/frr/modules \
225 --enable-multipath=0 --enable-rtadv \
226 --enable-tcp-zebra --enable-fpm --enable-pimd \
230 # Create symlink for vtysh, so topotest finds it in /usr/lib/frr
231 sudo ln -s /usr/lib/frr/vtysh /usr/bin/
233 and create ``frr`` user and ``frrvty`` group as shown above.
235 .. _topotests_docker:
237 Running Tests with Docker
238 -------------------------
240 There is a Docker image which allows to run topotests.
245 If you have Docker installed, you can run the topotests in Docker. The easiest
246 way to do this, is to use the make targets from this repository.
248 Your current user needs to have access to the Docker daemon. Alternatively you
249 can run these commands as root.
255 This command will pull the most recent topotests image from Dockerhub, compile
256 FRR inside of it, and run the topotests.
261 Internally, the topotests make target uses a shell script to pull the image and
262 spawn the Docker container.
264 There are several environment variables which can be used to modify the
265 behavior of the script, these can be listed by calling it with ``-h``:
269 ./tests/topotests/docker/frr-topotests.sh -h
271 For example, a volume is used to cache build artifacts between multiple runs of
272 the image. If you need to force a complete recompile, you can set
277 TOPOTEST_CLEAN=1 ./tests/topotests/docker/frr-topotests.sh
279 By default, ``frr-topotests.sh`` will build frr and run pytest. If you append
280 arguments and the first one starts with ``/`` or ``./``, they will replace the
281 call to pytest. If the appended arguments do not match this patttern, they will
282 be provided to pytest as arguments. So, to run a specific test with more
287 ./tests/topotests/docker/frr-topotests.sh -vv -s all-protocol-startup/test_all_protocol_startup.py
289 And to compile FRR but drop into a shell instead of running pytest:
293 ./tests/topotests/docker/frr-topotests.sh /bin/bash
298 The Docker image just includes all the components to run the topotests, but not
299 the topotests themselves. So if you just want to write tests and don't want to
300 make changes to the environment provided by the Docker image. You don't need to
301 build your own Docker image if you do not want to.
303 When developing new tests, there is one caveat though: The startup script of
304 the container will run a ``git-clean`` on its copy of the FRR tree to avoid any
305 pollution of the container with build artefacts from the host. This will also
306 result in your newly written tests being unavailable in the container unless at
307 least added to the index with ``git-add``.
309 If you do want to test changes to the Docker image, you can locally build the
310 image and run the tests without pulling from the registry using the following
316 TOPOTEST_PULL=0 make topotests
319 .. _topotests-guidelines:
327 To run the whole suite of tests the following commands must be executed at the
328 top level directory of topotest:
332 $ # Change to the top level directory of topotests.
333 $ cd path/to/topotests
334 $ # Tests must be run as root, since Mininet requires it.
337 In order to run a specific test, you can use the following command:
341 $ # running a specific topology
342 $ sudo pytest ospf-topo1/
343 $ # or inside the test folder
345 $ sudo pytest # to run all tests inside the directory
346 $ sudo pytest test_ospf_topo1.py # to run a specific test
347 $ # or outside the test folder
349 $ sudo pytest ospf-topo1/test_ospf_topo1.py # to run a specific one
351 The output of the tested daemons will be available at the temporary folder of
356 $ ls /tmp/topotest/ospf-topo1.test_ospf-topo1/r1
358 zebra.err # zebra stderr output
359 zebra.log # zebra log file
360 zebra.out # zebra stdout output
363 You can also run memory leak tests to get reports:
367 $ # Set the environment variable to apply to a specific test...
368 $ sudo env TOPOTESTS_CHECK_MEMLEAK="/tmp/memleak_report_" pytest ospf-topo1/test_ospf_topo1.py
369 $ # ...or apply to all tests adding this line to the configuration file
370 $ echo 'memleak_path = /tmp/memleak_report_' >> pytest.ini
371 $ # You can also use your editor
373 $ # After running tests you should see your files:
374 $ ls /tmp/memleak_report_*
375 memleak_report_test_ospf_topo1.txt
380 This section will guide you in all recommended steps to produce a standard
383 This is the recommended test writing routine:
385 - Write a topology (Graphviz recommended)
386 - Obtain configuration files
387 - Write the test itself
388 - Format the new code using `black <https://github.com/psf/black>`_
389 - Create a Pull Request
393 BGP tests MUST use generous convergence timeouts - you must ensure
394 that any test involving BGP uses a convergence timeout of at least
397 Topotest File Hierarchy
398 """""""""""""""""""""""
400 Before starting to write any tests one must know the file hierarchy. The
401 repository hierarchy looks like this:
405 $ cd path/to/topotest
408 ./README.md # repository read me
409 ./GUIDELINES.md # this file
410 ./conftest.py # test hooks - pytest related functions
411 ./example-test # example test folder
412 ./example-test/__init__.py # python package marker - must always exist.
413 ./example-test/test_template.jpg # generated topology picture - see next section
414 ./example-test/test_template.dot # Graphviz dot file
415 ./example-test/test_template.py # the topology plus the test
417 ./ospf-topo1 # the ospf topology test
418 ./ospf-topo1/r1 # router 1 configuration files
419 ./ospf-topo1/r1/zebra.conf # zebra configuration file
420 ./ospf-topo1/r1/ospfd.conf # ospf configuration file
421 ./ospf-topo1/r1/ospfroute.txt # 'show ip ospf' output reference file
422 # removed other for shortness sake
424 ./lib # shared test/topology functions
425 ./lib/topogen.py # topogen implementation
426 ./lib/topotest.py # topotest implementation
428 Guidelines for creating/editing topotest:
430 - New topologies that don't fit the existing directories should create its own
431 - Always remember to add the ``__init__.py`` to new folders, this makes auto
432 complete engines and pylint happy
433 - Router (Quagga/FRR) specific code should go on topotest.py
434 - Generic/repeated router actions should have an abstraction in
436 - Generic/repeated non-router code should go to topotest.py
437 - pytest related code should go to conftest.py (e.g. specialized asserts)
439 Defining the Topology
440 """""""""""""""""""""
442 The first step to write a new test is to define the topology. This step can be
443 done in many ways, but the recommended is to use Graphviz to generate a drawing
444 of the topology. It allows us to see the topology graphically and to see the
445 names of equipment, links and addresses.
447 Here is an example of Graphviz dot file that generates the template topology
448 :file:`tests/topotests/example-test/test_template.dot` (the inlined code might
449 get outdated, please see the linked file)::
471 label="s1\n192.168.0.0/24",
477 label="s2\n192.168.1.0/24",
483 r1 -- s1 [label="eth0\n.1"];
485 r1 -- s2 [label="eth1\n.100"];
486 r2 -- s2 [label="eth0\n.1"];
489 Here is the produced graph:
513 label="s1\n192.168.0.0/24",
519 label="s2\n192.168.1.0/24",
525 r1 -- s1 [label="eth0\n.1"];
527 r1 -- s2 [label="eth1\n.100"];
528 r2 -- s2 [label="eth0\n.1"];
531 Generating / Obtaining Configuration Files
532 """"""""""""""""""""""""""""""""""""""""""
534 In order to get the configuration files or command output for each router, we
535 need to run the topology and execute commands in ``vtysh``. The quickest way to
536 achieve that is writing the topology building code and running the topology.
538 To bootstrap your test topology, do the following steps:
540 - Copy the template test
545 $ touch new-topo/__init__.py
546 $ cp example-test/test_template.py new-topo/test_new_topo.py
548 - Modify the template according to your dot file
550 Here is the template topology described in the previous section in python code:
554 class TemplateTopo(Topo):
555 "Test topology builder"
556 def build(self, *_args, **_opts):
558 tgen = get_topogen(self)
561 for routern in range(1, 3):
562 tgen.add_router('r{}'.format(routern))
564 # Create a switch with just one router connected to it to simulate a
566 switch = tgen.add_switch('s1')
567 switch.add_link(tgen.gears['r1'])
569 # Create a connection between r1 and r2
570 switch = tgen.add_switch('s2')
571 switch.add_link(tgen.gears['r1'])
572 switch.add_link(tgen.gears['r2'])
576 Topogen allows us to run the topology without running any tests, you can do
577 that using the following example commands:
581 $ # Running your bootstraped topology
582 $ sudo pytest -s --topology-only new-topo/test_new_topo.py
583 $ # Running the test_template.py topology
584 $ sudo pytest -s --topology-only example-test/test_template.py
585 $ # Running the ospf_topo1.py topology
586 $ sudo pytest -s --topology-only ospf-topo1/test_ospf_topo1.py
588 Parameters explanation:
594 Actives input/output capture. This is required by mininet in order to show
595 the interactive shell.
597 .. option:: --topology-only
599 Don't run any tests, just build the topology.
601 After executing the commands above, you should get the following terminal
606 === test session starts ===
607 platform linux2 -- Python 2.7.12, pytest-3.1.2, py-1.4.34, pluggy-0.4.0
608 rootdir: /media/sf_src/topotests, inifile: pytest.ini
611 ospf-topo1/test_ospf_topo1.py *** Starting controller
613 *** Starting 6 switches
614 switch1 switch2 switch3 switch4 switch5 switch6 ...
615 r2: frr zebra started
616 r2: frr ospfd started
617 r3: frr zebra started
618 r3: frr ospfd started
619 r1: frr zebra started
620 r1: frr ospfd started
621 r4: frr zebra started
622 r4: frr ospfd started
626 The last line shows us that we are now using the Mininet CLI (Command Line
627 Interface), from here you can call your router ``vtysh`` or even bash.
629 Here are some commands example:
633 mininet> r1 ping 10.0.3.1
634 PING 10.0.3.1 (10.0.3.1) 56(84) bytes of data.
635 64 bytes from 10.0.3.1: icmp_seq=1 ttl=64 time=0.576 ms
636 64 bytes from 10.0.3.1: icmp_seq=2 ttl=64 time=0.083 ms
637 64 bytes from 10.0.3.1: icmp_seq=3 ttl=64 time=0.088 ms
639 --- 10.0.3.1 ping statistics ---
640 3 packets transmitted, 3 received, 0% packet loss, time 1998ms
641 rtt min/avg/max/mdev = 0.083/0.249/0.576/0.231 ms
645 mininet> r1 ping 10.0.3.3
646 PING 10.0.3.3 (10.0.3.3) 56(84) bytes of data.
647 64 bytes from 10.0.3.3: icmp_seq=1 ttl=64 time=2.87 ms
648 64 bytes from 10.0.3.3: icmp_seq=2 ttl=64 time=0.080 ms
649 64 bytes from 10.0.3.3: icmp_seq=3 ttl=64 time=0.091 ms
651 --- 10.0.3.3 ping statistics ---
652 3 packets transmitted, 3 received, 0% packet loss, time 2003ms
653 rtt min/avg/max/mdev = 0.080/1.014/2.872/1.313 ms
659 Hello, this is FRRouting (version 3.1-devrzalamena-build).
660 Copyright 1996-2005 Kunihiro Ishiguro, et al.
662 frr-1# show running-config
663 Building configuration...
665 Current configuration:
667 frr version 3.1-devrzalamena-build
668 frr defaults traditional
670 no service integrated-vtysh-config
677 ip address 10.0.3.1/24
680 ip address 10.0.10.1/24
683 ip address 172.16.0.2/24
686 ospf router-id 10.0.255.3
688 redistribute connected
690 network 10.0.3.0/24 area 0
691 network 10.0.10.0/24 area 0
692 network 172.16.0.0/24 area 1
699 After you successfully configured your topology, you can obtain the
700 configuration files (per-daemon) using the following commands:
704 mininet> r3 vtysh -d ospfd
706 Hello, this is FRRouting (version 3.1-devrzalamena-build).
707 Copyright 1996-2005 Kunihiro Ishiguro, et al.
709 frr-1# show running-config
710 Building configuration...
712 Current configuration:
714 frr version 3.1-devrzalamena-build
715 frr defaults traditional
716 no service integrated-vtysh-config
721 ospf router-id 10.0.255.3
723 redistribute connected
725 network 10.0.3.0/24 area 0
726 network 10.0.10.0/24 area 0
727 network 172.16.0.0/24 area 1
737 Test topologies should always be bootstrapped from
738 :file:`tests/topotests/example-test/test_template.py` because it contains
739 important boilerplate code that can't be avoided, like:
741 - imports: os, sys, pytest, topotest/topogen and mininet topology class
742 - The global variable CWD (Current Working directory): which is most likely
743 going to be used to reference the routers configuration file location
749 # For all registered routers, load the zebra configuration file
750 for rname, router in router_list.items():
753 os.path.join(CWD, '{}/zebra.conf'.format(rname))
755 # os.path.join() joins the CWD string with arguments adding the necessary
756 # slashes ('/'). Arguments must not begin with '/'.
758 - The topology class that inherits from Mininet Topo class:
762 class TemplateTopo(Topo):
763 def build(self, *_args, **_opts):
764 tgen = get_topogen(self)
765 # topology build code
767 - pytest ``setup_module()`` and ``teardown_module()`` to start the topology
771 def setup_module(_m):
772 tgen = Topogen(TemplateTopo)
773 tgen.start_topology('debug')
775 def teardown_module(_m):
779 - ``__main__`` initialization code (to support running the script directly)
783 if __name__ == '__main__':
784 sys.exit(pytest.main(["-s"]))
788 - Test code should always be declared inside functions that begin with the
789 ``test_`` prefix. Functions beginning with different prefixes will not be run
791 - Configuration files and long output commands should go into separated files
792 inside folders named after the equipment.
793 - Tests must be able to run without any interaction. To make sure your test
794 conforms with this, run it without the :option:`-s` parameter.
795 - Use `black <https://github.com/psf/black>`_ code formatter before creating
796 a pull request. This ensures we have a unified code style.
797 - Mark test modules with pytest markers depending on the daemons used during the
802 - Keep results in stack variables, so people inspecting code with ``pdb`` can
803 easily print their values.
809 assert foobar(router1, router2)
815 result = foobar(router1, router2)
818 - Use ``assert`` messages to indicate where the test failed.
824 for router in router_list:
826 assert condition, 'Router "{}" condition failed'.format(router.name)
831 The most effective ways to inspect topology tests are:
833 - Run pytest with ``--pdb`` option. This option will cause a pdb shell to
834 appear when an assertion fails
836 Example: ``pytest -s --pdb ospf-topo1/test_ospf_topo1.py``
838 - Set a breakpoint in the test code with ``pdb``
844 # Add the pdb import at the beginning of the file
848 # Add a breakpoint where you think the problem is
854 The `Python Debugger <https://docs.python.org/2.7/library/pdb.html>`__ (pdb)
855 shell allows us to run many useful operations like:
857 - Setting breaking point on file/function/conditions (e.g. ``break``,
859 - Inspecting variables (e.g. ``p`` (print), ``pp`` (pretty print))
860 - Running python code
864 The TopoGear (equipment abstraction class) implements the ``__str__`` method
865 that allows the user to inspect equipment information.
867 Example of pdb usage:
871 > /media/sf_src/topotests/ospf-topo1/test_ospf_topo1.py(121)test_ospf_convergence()
872 -> for rnum in range(1, 5):
874 Documented commands (type help <topic>):
875 ========================================
876 EOF bt cont enable jump pp run unt
877 a c continue exit l q s until
878 alias cl d h list quit step up
879 args clear debug help n r tbreak w
880 b commands disable ignore next restart u whatis
881 break condition down j p return unalias where
883 Miscellaneous help topics:
884 ==========================
887 Undocumented commands:
888 ======================
892 116 title2="Expected output")
894 118 def test_ospf_convergence():
895 119 "Test OSPF daemon convergence"
897 121 -> for rnum in range(1, 5):
898 122 router = 'r{}'.format(rnum)
900 124 # Load expected results from the command
901 125 reffile = os.path.join(CWD, '{}/ospfroute.txt'.format(router))
902 126 expected = open(reffile).read()
904 > /media/sf_src/topotests/ospf-topo1/test_ospf_topo1.py(122)test_ospf_convergence()
905 -> router = 'r{}'.format(rnum)
907 > /media/sf_src/topotests/ospf-topo1/test_ospf_topo1.py(125)test_ospf_convergence()
908 -> reffile = os.path.join(CWD, '{}/ospfroute.txt'.format(router))
913 (Pdb) tgen = get_topogen()
914 (Pdb) pp tgen.gears[router]
915 <lib.topogen.TopoRouter object at 0x7f74e06c9850>
916 (Pdb) pp str(tgen.gears[router])
917 'TopoGear<name="r1",links=["r1-eth0"<->"s1-eth0","r1-eth1"<->"s3-eth0"]> TopoRouter<>'
920 121 for rnum in range(1, 5):
921 122 router = 'r{}'.format(rnum)
923 124 # Load expected results from the command
924 125 -> reffile = os.path.join(CWD, '{}/ospfroute.txt'.format(router))
925 126 expected = open(reffile).read()
927 128 # Run test function until we get an result. Wait at most 60 seconds.
928 129 test_func = partial(compare_show_ip_ospf, router, expected)
929 130 result, diff = topotest.run_and_expect(test_func, '',
930 (Pdb) router1 = tgen.gears[router]
931 (Pdb) router1.vtysh_cmd('show ip ospf route')
932 '============ OSPF network routing table ============\r\nN 10.0.1.0/24 [10] area: 0.0.0.0\r\n directly attached to r1-eth0\r\nN 10.0.2.0/24 [20] area: 0.0.0.0\r\n via 10.0.3.3, r1-eth1\r\nN 10.0.3.0/24 [10] area: 0.0.0.0\r\n directly attached to r1-eth1\r\nN 10.0.10.0/24 [20] area: 0.0.0.0\r\n via 10.0.3.1, r1-eth1\r\nN IA 172.16.0.0/24 [20] area: 0.0.0.0\r\n via 10.0.3.1, r1-eth1\r\nN IA 172.16.1.0/24 [30] area: 0.0.0.0\r\n via 10.0.3.1, r1-eth1\r\n\r\n============ OSPF router routing table =============\r\nR 10.0.255.2 [10] area: 0.0.0.0, ASBR\r\n via 10.0.3.3, r1-eth1\r\nR 10.0.255.3 [10] area: 0.0.0.0, ABR, ASBR\r\n via 10.0.3.1, r1-eth1\r\nR 10.0.255.4 IA [20] area: 0.0.0.0, ASBR\r\n via 10.0.3.1, r1-eth1\r\n\r\n============ OSPF external routing table ===========\r\n\r\n\r\n'
933 (Pdb) tgen.mininet_cli()
937 To enable more debug messages in other Topogen subsystems (like Mininet), more
938 logging messages can be displayed by modifying the test configuration file
944 # Change the default verbosity line from 'info'...
949 Instructions for use, write or debug topologies can be found in :ref:`topotests-guidelines`.
950 To learn/remember common code snippets see :ref:`topotests-snippets`.
952 Before creating a new topology, make sure that there isn't one already that
953 does what you need. If nothing is similar, then you may create a new topology,
954 preferably, using the newest template
955 (:file:`tests/topotests/example-test/test_template.py`).
957 .. include:: topotests-markers.rst
959 .. include:: topotests-snippets.rst
964 All the configs and scripts are licensed under a ISC-style license. See Python