doc: minor update based on mininet removal

Signed-off-by: Christian Hopps <chopps@labn.net>
This commit is contained in:
Christian Hopps 2021-07-18 15:59:40 +00:00
parent 351bc82cac
commit 77f3acb45e
4 changed files with 313 additions and 201 deletions

View File

@ -12,8 +12,8 @@ Installing Dependencies
sudo apt update sudo apt update
sudo apt-get install \ sudo apt-get install \
git autoconf automake libtool make libreadline-dev texinfo \ git autoconf automake libtool make libreadline-dev texinfo \
pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \ pkg-config libpam0g-dev libjson-c-dev bison flex \
libc-ares-dev python3-dev python-ipaddress python3-sphinx \ libc-ares-dev python3-dev python3-sphinx \
install-info build-essential libsnmp-dev perl libcap-dev \ install-info build-essential libsnmp-dev perl libcap-dev \
libelf-dev libelf-dev

View File

@ -12,8 +12,8 @@ Installing Dependencies
sudo apt update sudo apt update
sudo apt-get install \ sudo apt-get install \
git autoconf automake libtool make libreadline-dev texinfo \ git autoconf automake libtool make libreadline-dev texinfo \
pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \ pkg-config libpam0g-dev libjson-c-dev bison flex \
libc-ares-dev python3-dev python-ipaddress python3-sphinx \ libc-ares-dev python3-dev python3-sphinx \
install-info build-essential libsnmp-dev perl \ install-info build-essential libsnmp-dev perl \
libcap-dev python2 libelf-dev libcap-dev python2 libelf-dev

View File

@ -373,23 +373,18 @@ Building topology and configurations
Topology and initial configuration will be created in setup_module(). Following Topology and initial configuration will be created in setup_module(). Following
is the sample code:: is the sample code::
class TemplateTopo(Topo):
def build(self, *_args, **_opts):
"Build function"
tgen = get_topogen(self)
# Building topology from json file
build_topo_from_json(tgen, topo)
def setup_module(mod): def setup_module(mod):
tgen = Topogen(TemplateTopo, mod.__name__) json_file = "{}/my_test_name.json".format(CWD)
tgen = Topogen(json_file, mod.__name__)
# json topo object is now available in tgen.json_topo
# Starting topology, create tmp files which are loaded to routers # Starting topology, create tmp files which are loaded to routers
# to start deamons and then start routers # to start deamons and then start routers
start_topology(tgen) start_topology(tgen)
# Creating configuration from JSON # Creating configuration from JSON
build_config_from_json(tgen, topo) build_config_from_json(tgen)
def teardown_module(mod): def teardown_module(mod):
tgen = get_topogen() tgen = get_topogen()
@ -412,10 +407,12 @@ configurations are like, static routes, prefixlists and route maps etc configs,
these configs can be used by any other protocols as it is. these configs can be used by any other protocols as it is.
BGP config will be specific to BGP protocol testing. BGP config will be specific to BGP protocol testing.
* JSON file is passed to API build_config_from_json(), which looks for * json file is passed to API Topogen() which saves the JSON object in
configuration tags in JSON file. `self.json_topo`
* If tag is found in JSON, configuration is created as per input and written * The Topogen object is then passed to API build_config_from_json(), which looks
to file frr_json.conf for configuration tags in new JSON object.
* If tag is found in the JSON object, configuration is created as per input and
written to file frr_json.conf
* Once JSON parsing is over, frr_json.conf is loaded onto respective router. * Once JSON parsing is over, frr_json.conf is loaded onto respective router.
Config loading is done using 'vtysh -f <file>'. Initial config at this point Config loading is done using 'vtysh -f <file>'. Initial config at this point
is also saved frr_json_initial.conf. This file can be used to reset is also saved frr_json_initial.conf. This file can be used to reset
@ -428,10 +425,10 @@ Writing Tests
""""""""""""" """""""""""""
Test topologies should always be bootstrapped from the Test topologies should always be bootstrapped from the
example-test/test_example.py, because it contains important boilerplate code example_test/test_template_json.py, because it contains important boilerplate
that can't be avoided, like: code that can't be avoided, like:
imports: os, sys, pytest, topotest/topogen and mininet topology class imports: os, sys, pytest, and topotest/topogen.
The global variable CWD (Current Working directory): which is most likely going The global variable CWD (Current Working directory): which is most likely going
to be used to reference the routers configuration file location to be used to reference the routers configuration file location

View File

@ -3,32 +3,37 @@
Topotests Topotests
========= =========
Topotests is a suite of topology tests for FRR built on top of Mininet. Topotests is a suite of topology tests for FRR built on top of micronet.
Installation and Setup Installation and Setup
---------------------- ----------------------
Only tested with Ubuntu 16.04 and Ubuntu 18.04 (which uses Mininet 2.2.x). Topotests run under python3. Additionally, for ExaBGP (which is used in some of
the BGP tests) an older python2 version must be installed.
Tested with Ubuntu 20.04 and Ubuntu 18.04 and Debian 11.
Instructions are the same for all setups (i.e. ExaBGP is only used for BGP Instructions are the same for all setups (i.e. ExaBGP is only used for BGP
tests). tests).
Installing Mininet Infrastructure Installing Topotest Requirements
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code:: shell .. code:: shell
apt-get install mininet apt-get install iproute2
apt-get install python-pip apt-get install net-tools
apt-get install iproute apt-get install python3-pip
apt-get install iperf python3 -m pip install wheel
pip install ipaddr python3 -m pip install 'pytest>=6.2.4'
pip install "pytest<5" python3 -m pip install 'pytest-xdist>=2.3.0'
pip install "scapy>=2.4.2" python3 -m pip install 'scapy>=2.4.5'
pip install exabgp==3.4.17 (Newer 4.0 version of exabgp is not yet python3 -m pip install xmltodict
supported) # Use python2 pip to install older ExaBGP
python2 -m pip install 'exabgp<4.0.0'
useradd -d /var/run/exabgp/ -s /bin/false exabgp useradd -d /var/run/exabgp/ -s /bin/false exabgp
Enable Coredumps Enable Coredumps
"""""""""""""""" """"""""""""""""
@ -125,20 +130,125 @@ And create ``frr`` user and ``frrvty`` group as follows:
Executing Tests Executing Tests
--------------- ---------------
Execute all tests with output to console Execute all tests in distributed test mode
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code:: shell .. code:: shell
py.test -s -v --tb=no py.test -s -v -nauto --dist=loadfile
The above command must be executed from inside the topotests directory. The above command must be executed from inside the topotests directory.
All test\_\* scripts in subdirectories are detected and executed (unless All test\_\* scripts in subdirectories are detected and executed (unless
disabled in ``pytest.ini`` file). disabled in ``pytest.ini`` file). Pytest will execute up to N tests in parallel
where N is based on the number of cores on the host.
Analyze Test Results (``analyze.py``)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
By default router and execution logs are saved in ``/tmp/topotests`` and an XML
results file is saved in ``/tmp/topotests.xml``. An analysis tool ``analyze.py``
is provided to archive and analyze these results after the run completes.
After the test run completes one should pick an archive directory to store the
results in and pass this value to ``analyze.py``. On first execution the results
are copied to that directory from ``/tmp``, and subsequent runs use that
directory for analyzing the results. Below is an example of this which also
shows the default behavior which is to display all failed and errored tests in
the run.
.. code:: shell
~/frr/tests/topotests# ./analyze.py -Ar run-save
bgp_multiview_topo1/test_bgp_multiview_topo1.py::test_bgp_converge
ospf_basic_functionality/test_ospf_lan.py::test_ospf_lan_tc1_p0
bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py::test_BGP_GR_10_p2
bgp_multiview_topo1/test_bgp_multiview_topo1.py::test_bgp_routingTable
Here we see that 4 tests have failed. We an dig deeper by displaying the
captured logs and errors. First let's redisplay the results enumerated by adding
the ``-E`` flag
.. code:: shell
~/frr/tests/topotests# ./analyze.py -Ar run-save -E
0 bgp_multiview_topo1/test_bgp_multiview_topo1.py::test_bgp_converge
1 ospf_basic_functionality/test_ospf_lan.py::test_ospf_lan_tc1_p0
2 bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py::test_BGP_GR_10_p2
3 bgp_multiview_topo1/test_bgp_multiview_topo1.py::test_bgp_routingTable
Now to look at the error message for a failed test we use ``-T N`` where N is
the number of the test we are interested in along with ``--errmsg`` option.
.. code:: shell
~/frr/tests/topotests# ./analyze.py -Ar run-save -T0 --errmsg
bgp_multiview_topo1/test_bgp_multiview_topo1.py::test_bgp_converge: AssertionError: BGP did not converge:
IPv4 Unicast Summary (VIEW 1):
BGP router identifier 172.30.1.1, local AS number 100 vrf-id -1
BGP table version 1
RIB entries 1, using 184 bytes of memory
Peers 3, using 2169 KiB of memory
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc
172.16.1.1 4 65001 0 0 0 0 0 never Connect 0 N/A
172.16.1.2 4 65002 0 0 0 0 0 never Connect 0 N/A
172.16.1.5 4 65005 0 0 0 0 0 never Connect 0 N/A
Total number of neighbors 3
assert False
Now to look at the full text of the error for a failed test we use ``-T N``
where N is the number of the test we are interested in along with ``--errtext``
option.
.. code:: shell
~/frr/tests/topotests# ./analyze.py -Ar run-save -T0 --errtext
bgp_multiview_topo1/test_bgp_multiview_topo1.py::test_bgp_converge: def test_bgp_converge():
"Check for BGP converged on all peers and BGP views"
global fatal_error
global net
[...]
else:
# Bail out with error if a router fails to converge
bgpStatus = net["r%s" % i].cmd('vtysh -c "show ip bgp view %s summary"' % view)
> assert False, "BGP did not converge:\n%s" % bgpStatus
E AssertionError: BGP did not converge:
E
E IPv4 Unicast Summary (VIEW 1):
E BGP router identifier 172.30.1.1, local AS number 100 vrf-id -1
[...]
E Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc
E 172.16.1.1 4 65001 0 0 0 0 0 never Connect 0 N/A
E 172.16.1.2 4 65002 0 0 0 0 0 never Connect 0 N/A
[...]
To look at the full capture for a test including the stdout and stderr which
includes full debug logs, just use the ``-T N`` option without the ``--errmsg``
or ``--errtext`` options.
.. code:: shell
~/frr/tests/topotests# ./analyze.py -Ar run-save -T0
@classname: bgp_multiview_topo1.test_bgp_multiview_topo1
@name: test_bgp_converge
@time: 141.401
@message: AssertionError: BGP did not converge:
[...]
system-out: --------------------------------- Captured Log ---------------------------------
2021-08-09 02:55:06,581 DEBUG: lib.micronet_compat.topo: Topo(unnamed): Creating
2021-08-09 02:55:06,581 DEBUG: lib.micronet_compat.topo: Topo(unnamed): addHost r1
[...]
2021-08-09 02:57:16,932 DEBUG: topolog.r1: LinuxNamespace(r1): cmd_status("['/bin/bash', '-c', 'vtysh -c "show ip bgp view 1 summary" 2> /dev/null | grep ^[0-9] | grep -vP " 11\\s+(\\d+)"']", kwargs: {'encoding': 'utf-8', 'stdout': -1, 'stderr': -2, 'shell': False})
2021-08-09 02:57:22,290 DEBUG: topolog.r1: LinuxNamespace(r1): cmd_status("['/bin/bash', '-c', 'vtysh -c "show ip bgp view 1 summary" 2> /dev/null | grep ^[0-9] | grep -vP " 11\\s+(\\d+)"']", kwargs: {'encoding': 'utf-8', 'stdout': -1, 'stderr': -2, 'shell': False})
2021-08-09 02:57:27,636 DEBUG: topolog.r1: LinuxNamespace(r1): cmd_status("['/bin/bash', '-c', 'vtysh -c "show ip bgp view 1 summary"']", kwargs: {'encoding': 'utf-8', 'stdout': -1, 'stderr': -2, 'shell': False})
--------------------------------- Captured Out ---------------------------------
system-err: --------------------------------- Captured Err ---------------------------------
``--tb=no`` disables the python traceback which might be irrelevant unless the
test script itself is debugged.
Execute single test Execute single test
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
@ -161,9 +271,6 @@ Test will set exit code which can be used with ``git bisect``.
For the simulated topology, see the description in the python file. For the simulated topology, see the description in the python file.
If you need to clear the mininet setup between tests (if it isn't cleanly
shutdown), then use the ``mn -c`` command to clean up the environment.
StdErr log from daemos after exit StdErr log from daemos after exit
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -235,18 +342,64 @@ and create ``frr`` user and ``frrvty`` group as shown above.
Debugging Topotest Failures Debugging Topotest Failures
^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
For the below debugging options which launch programs, if the topotest is run Install and run tests inside ``tmux`` or ``byobu`` for best results.
within screen_ or tmux_, ``gdb``, the shell or ``vtysh`` will be launched using
that windowing program, otherwise mininet's ``xterm`` functionality will be used
to launch the given program.
If you wish to force the use of ``xterm`` rather than ``tmux`` or ``screen``, or ``XTerm`` is also fully supported. GNU ``screen`` can be used in most
wish to use ``gnome-terminal`` instead of ``xterm``, set the environment situations; however, it does not work as well with launching ``vtysh`` or shell
variable ``FRR_TOPO_TERMINAL`` to either ``xterm`` or ``gnome-terminal``. on error.
For the below debugging options which launch programs or CLIs, topotest should
be run within ``tmux`` (or ``screen``)_, as ``gdb``, the shell or ``vtysh`` will
be launched using that windowing program, otherwise ``xterm`` will be attempted
to launch the given programs.
.. _screen: https://www.gnu.org/software/screen/ .. _screen: https://www.gnu.org/software/screen/
.. _tmux: https://github.com/tmux/tmux/wiki .. _tmux: https://github.com/tmux/tmux/wiki
Spawning Debugging CLI, ``vtysh`` or Shells on Routers on Test Failure
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
One can have a debugging CLI invoked on test failures by specifying the
``--cli-on-error`` CLI option as shown in the example below.
.. code:: shell
pytest --cli-on-error all-protocol-startup
The debugging CLI can run shell or vtysh commands on any combination of routers
It can also open shells or vtysh in their own windows for any combination of
routers. This is usually the most useful option when debugging failures. Here is
the help command from within a CLI launched on error:
.. code:: shell
test_bgp_multiview_topo1/test_bgp_routingTable> help
Commands:
help :: this help
sh [hosts] <shell-command> :: execute <shell-command> on <host>
term [hosts] :: open shell terminals for hosts
vtysh [hosts] :: open vtysh terminals for hosts
[hosts] <vtysh-command> :: execute vtysh-command on hosts
test_bgp_multiview_topo1/test_bgp_routingTable> r1 show int br
------ Host: r1 ------
Interface Status VRF Addresses
--------- ------ --- ---------
erspan0 down default
gre0 down default
gretap0 down default
lo up default
r1-eth0 up default 172.16.1.254/24
r1-stub up default 172.20.0.1/28
----------------------
test_bgp_multiview_topo1/test_bgp_routingTable>
Additionally, one can have ``vtysh`` or a shell launched on all routers when a
test fails. To launch the given process on each router after a test failure
specify one of ``--shell-on-error`` or ``--vtysh-on-error``.
Spawning ``vtysh`` or Shells on Routers Spawning ``vtysh`` or Shells on Routers
""""""""""""""""""""""""""""""""""""""" """""""""""""""""""""""""""""""""""""""
@ -255,8 +408,8 @@ a test. This is enabled by specifying 1 of 2 CLI arguments ``--shell`` or
``--vtysh``. Both of these options can be set to a single router value, multiple ``--vtysh``. Both of these options can be set to a single router value, multiple
comma-seperated values, or ``all``. comma-seperated values, or ``all``.
When either of these options are specified topotest will pause after each test When either of these options are specified topotest will pause after setup and
to allow for inspection of the router state. each test to allow for inspection of the router state.
Here's an example of launching ``vtysh`` on routers ``rt1`` and ``rt2``. Here's an example of launching ``vtysh`` on routers ``rt1`` and ``rt2``.
@ -264,29 +417,6 @@ Here's an example of launching ``vtysh`` on routers ``rt1`` and ``rt2``.
pytest --vtysh=rt1,rt2 all-protocol-startup pytest --vtysh=rt1,rt2 all-protocol-startup
Spawning Mininet CLI, ``vtysh`` or Shells on Routers on Test Failure
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Similar to the previous section one can have ``vtysh`` or a shell launched on
routers, but in this case only when a test fails. To launch the given process on
each router after a test failure specify one of ``--shell-on-error`` or
``--vtysh-on-error``.
Here's an example of having ``vtysh`` launched on test failure.
.. code:: shell
pytest --vtysh-on-error all-protocol-startup
Additionally, one can have the mininet CLI invoked on test failures by
specifying the ``--mininet-on-error`` CLI option as shown in the example below.
.. code:: shell
pytest --mininet-on-error all-protocol-startup
Debugging with GDB Debugging with GDB
"""""""""""""""""" """"""""""""""""""
@ -424,7 +554,7 @@ top level directory of topotest:
$ # Change to the top level directory of topotests. $ # Change to the top level directory of topotests.
$ cd path/to/topotests $ cd path/to/topotests
$ # Tests must be run as root, since Mininet requires it. $ # Tests must be run as root, since micronet requires it.
$ sudo pytest $ sudo pytest
In order to run a specific test, you can use the following command: In order to run a specific test, you can use the following command:
@ -493,15 +623,16 @@ Some things to keep in mind:
- Avoid including unstable data in your test: don't rely on link-local - Avoid including unstable data in your test: don't rely on link-local
addresses or ifindex values, for example, because these can change addresses or ifindex values, for example, because these can change
from run to run. from run to run.
- Using sleep is almost never appropriate to wait for some convergence - Using sleep is almost never appropriate. As an example: if the test resets the
event as the sole item done. As an example: if the test resets the peers peers in BGP, the test should look for the peers re-converging instead of just
in BGP, the test should look for the peers reconverging instead of just sleeping an arbitrary amount of time and continuing on. See
sleeping an arbitrary amount of time and continuing on. It is ok to `verify_bgp_convergence` as a good example of this. In particular look at it's
use sleep in a tight loop with appropriate show commands to ensure that use of the `@retry` decorator. If you are having troubles figuring out what to
the protocol reaches the desired state. This should be bounded by look for, please do not be afraid to ask.
appropriate timeouts for the protocol in question though. See - Don't duplicate effort. There exists many protocol utility functions that can
verify_bgp_convergence as a good example of this. If you are having be found in their eponymous module under `tests/topotests/lib/` (e.g.,
troubles figuring out what to look for, please do not be afraid to ask. `ospf.py`)
Topotest File Hierarchy Topotest File Hierarchy
@ -661,25 +792,32 @@ Here is the template topology described in the previous section in python code:
.. code:: py .. code:: py
class TemplateTopo(Topo): topodef = {
"Test topology builder" "s1": "r1"
def build(self, *_args, **_opts): "s2": ("r1", "r2")
"Build function" }
tgen = get_topogen(self)
# Create 2 routers If more specialized topology definitions, or router initialization arguments are
for routern in range(1, 3): required a build function can be used instead of a dictionary:
tgen.add_router('r{}'.format(routern))
# Create a switch with just one router connected to it to simulate a .. code:: py
# empty network.
switch = tgen.add_switch('s1')
switch.add_link(tgen.gears['r1'])
# Create a connection between r1 and r2 def build_topo(tgen):
switch = tgen.add_switch('s2') "Build function"
switch.add_link(tgen.gears['r1'])
switch.add_link(tgen.gears['r2']) # Create 2 routers
for routern in range(1, 3):
tgen.add_router("r{}".format(routern))
# Create a switch with just one router connected to it to simulate a
# empty network.
switch = tgen.add_switch("s1")
switch.add_link(tgen.gears["r1"])
# Create a connection between r1 and r2
switch = tgen.add_switch("s2")
switch.add_link(tgen.gears["r1"])
switch.add_link(tgen.gears["r2"])
- Run the topology - Run the topology
@ -701,8 +839,8 @@ Parameters explanation:
.. option:: -s .. option:: -s
Actives input/output capture. This is required by mininet in order to show Actives input/output capture. If this is not specified a new window will be
the interactive shell. opened for the interactive CLI, otherwise it will be activated inline.
.. option:: --topology-only .. option:: --topology-only
@ -713,110 +851,84 @@ output:
.. code:: shell .. code:: shell
=== test session starts === frr/tests/topotests# sudo pytest -s --topology-only ospf_topo1/test_ospf_topo1.py
platform linux2 -- Python 2.7.12, pytest-3.1.2, py-1.4.34, pluggy-0.4.0 ============================= test session starts ==============================
rootdir: /media/sf_src/topotests, inifile: pytest.ini platform linux -- Python 3.9.2, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
collected 3 items rootdir: /home/chopps/w/frr/tests/topotests, configfile: pytest.ini
plugins: forked-1.3.0, xdist-2.3.0
collected 11 items
ospf-topo1/test_ospf_topo1.py *** Starting controller [...]
unet>
*** Starting 6 switches The last line shows us that we are now using the CLI (Command Line
switch1 switch2 switch3 switch4 switch5 switch6 ...
r2: frr zebra started
r2: frr ospfd started
r3: frr zebra started
r3: frr ospfd started
r1: frr zebra started
r1: frr ospfd started
r4: frr zebra started
r4: frr ospfd started
*** Starting CLI:
mininet>
The last line shows us that we are now using the Mininet CLI (Command Line
Interface), from here you can call your router ``vtysh`` or even bash. Interface), from here you can call your router ``vtysh`` or even bash.
Here's the help text:
.. code:: shell
unet> help
Commands:
help :: this help
sh [hosts] <shell-command> :: execute <shell-command> on <host>
term [hosts] :: open shell terminals for hosts
vtysh [hosts] :: open vtysh terminals for hosts
[hosts] <vtysh-command> :: execute vtysh-command on hosts
.. code:: shell
Here are some commands example: Here are some commands example:
.. code:: shell .. code:: shell
mininet> r1 ping 10.0.3.1 unet> sh r1 ping 10.0.3.1
PING 10.0.3.1 (10.0.3.1) 56(84) bytes of data. PING 10.0.3.1 (10.0.3.1) 56(84) bytes of data.
64 bytes from 10.0.3.1: icmp_seq=1 ttl=64 time=0.576 ms 64 bytes from 10.0.3.1: icmp_seq=1 ttl=64 time=0.576 ms
64 bytes from 10.0.3.1: icmp_seq=2 ttl=64 time=0.083 ms 64 bytes from 10.0.3.1: icmp_seq=2 ttl=64 time=0.083 ms
64 bytes from 10.0.3.1: icmp_seq=3 ttl=64 time=0.088 ms 64 bytes from 10.0.3.1: icmp_seq=3 ttl=64 time=0.088 ms
^C ^C
--- 10.0.3.1 ping statistics --- --- 10.0.3.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1998ms 3 packets transmitted, 3 received, 0% packet loss, time 1998ms
rtt min/avg/max/mdev = 0.083/0.249/0.576/0.231 ms rtt min/avg/max/mdev = 0.083/0.249/0.576/0.231 ms
unet> r1 show run
Building configuration...
Current configuration:
!
frr version 8.1-dev-my-manual-build
frr defaults traditional
hostname r1
log file /tmp/topotests/ospf_topo1.test_ospf_topo1/r1/zebra.log
[...]
end
mininet> r1 ping 10.0.3.3 unet> show daemons
PING 10.0.3.3 (10.0.3.3) 56(84) bytes of data. ------ Host: r1 ------
64 bytes from 10.0.3.3: icmp_seq=1 ttl=64 time=2.87 ms zebra ospfd ospf6d staticd
64 bytes from 10.0.3.3: icmp_seq=2 ttl=64 time=0.080 ms ------- End: r1 ------
64 bytes from 10.0.3.3: icmp_seq=3 ttl=64 time=0.091 ms ------ Host: r2 ------
^C zebra ospfd ospf6d staticd
--- 10.0.3.3 ping statistics --- ------- End: r2 ------
3 packets transmitted, 3 received, 0% packet loss, time 2003ms ------ Host: r3 ------
rtt min/avg/max/mdev = 0.080/1.014/2.872/1.313 ms zebra ospfd ospf6d staticd
------- End: r3 ------
------ Host: r4 ------
zebra ospfd ospf6d staticd
mininet> r3 vtysh ------- End: r4 ------
Hello, this is FRRouting (version 3.1-devrzalamena-build).
Copyright 1996-2005 Kunihiro Ishiguro, et al.
frr-1# show running-config
Building configuration...
Current configuration:
!
frr version 3.1-devrzalamena-build
frr defaults traditional
hostname r3
no service integrated-vtysh-config
!
log file zebra.log
!
log file ospfd.log
!
interface r3-eth0
ip address 10.0.3.1/24
!
interface r3-eth1
ip address 10.0.10.1/24
!
interface r3-eth2
ip address 172.16.0.2/24
!
router ospf
ospf router-id 10.0.255.3
redistribute kernel
redistribute connected
redistribute static
network 10.0.3.0/24 area 0
network 10.0.10.0/24 area 0
network 172.16.0.0/24 area 1
!
line vty
!
end
frr-1#
After you successfully configured your topology, you can obtain the After you successfully configured your topology, you can obtain the
configuration files (per-daemon) using the following commands: configuration files (per-daemon) using the following commands:
.. code:: shell .. code:: shell
mininet> r3 vtysh -d ospfd unet> sh r3 vtysh -d ospfd
Hello, this is FRRouting (version 3.1-devrzalamena-build). Hello, this is FRRouting (version 3.1-devrzalamena-build).
Copyright 1996-2005 Kunihiro Ishiguro, et al. Copyright 1996-2005 Kunihiro Ishiguro, et al.
frr-1# show running-config r1# show running-config
Building configuration... Building configuration...
Current configuration: Current configuration:
@ -839,7 +951,7 @@ configuration files (per-daemon) using the following commands:
line vty line vty
! !
end end
frr-1# r1#
Writing Tests Writing Tests
""""""""""""" """""""""""""
@ -848,15 +960,12 @@ Test topologies should always be bootstrapped from
:file:`tests/topotests/example-test/test_template.py` because it contains :file:`tests/topotests/example-test/test_template.py` because it contains
important boilerplate code that can't be avoided, like: important boilerplate code that can't be avoided, like:
- imports: os, sys, pytest, topotest/topogen and mininet topology class
- The global variable CWD (Current Working directory): which is most likely
going to be used to reference the routers configuration file location
Example: Example:
.. code:: py .. code:: py
# For all registered routers, load the zebra configuration file # For all registered routers, load the zebra configuration file
CWD = os.path.dirname(os.path.realpath(__file__))
for rname, router in router_list.items(): for rname, router in router_list.items():
router.load_config( router.load_config(
TopoRouter.RD_ZEBRA, TopoRouter.RD_ZEBRA,
@ -865,21 +974,28 @@ Example:
# os.path.join() joins the CWD string with arguments adding the necessary # os.path.join() joins the CWD string with arguments adding the necessary
# slashes ('/'). Arguments must not begin with '/'. # slashes ('/'). Arguments must not begin with '/'.
- The topology class that inherits from Mininet Topo class: - The topology definition or build function
.. code:: py .. code:: py
class TemplateTopo(Topo): topodef = {
def build(self, *_args, **_opts): "s1": ("r1", "r2"),
tgen = get_topogen(self) "s2": ("r2", "r3")
}
def build_topo(tgen):
# topology build code # topology build code
...
- pytest ``setup_module()`` and ``teardown_module()`` to start the topology - pytest ``setup_module()`` and ``teardown_module()`` to start the topology
.. code:: py .. code:: py
def setup_module(_m): def setup_module(module):
tgen = Topogen(TemplateTopo) tgen = Topogen(topodef, module.__name__)
# or
tgen = Topogen(build_topo, module.__name__)
tgen.start_topology('debug') tgen.start_topology('debug')
def teardown_module(_m): def teardown_module(_m):
@ -1042,11 +1158,10 @@ Example of pdb usage:
(Pdb) router1 = tgen.gears[router] (Pdb) router1 = tgen.gears[router]
(Pdb) router1.vtysh_cmd('show ip ospf route') (Pdb) router1.vtysh_cmd('show ip ospf route')
'============ 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' '============ 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'
(Pdb) tgen.mininet_cli() (Pdb) tgen.cli()
*** Starting CLI: unet>
mininet>
To enable more debug messages in other Topogen subsystems (like Mininet), more To enable more debug messages in other Topogen subsystems, more
logging messages can be displayed by modifying the test configuration file logging messages can be displayed by modifying the test configuration file
``pytest.ini``: ``pytest.ini``: