]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/rip_allow_ecmp/test_rip_allow_ecmp.py
tests: Check RIP allow-ecmp an arbitrary number of paths
[mirror_frr.git] / tests / topotests / rip_allow_ecmp / test_rip_allow_ecmp.py
CommitLineData
83c78d54
DA
1#!/usr/bin/env python
2# SPDX-License-Identifier: ISC
3
4# Copyright (c) 2023 by
5# Donatas Abraitis <donatas@opensourcerouting.org>
6#
7
8"""
9Test if RIP `allow-ecmp` command works correctly.
10"""
11
12import os
13import sys
14import json
15import pytest
16import functools
17
18CWD = os.path.dirname(os.path.realpath(__file__))
19sys.path.append(os.path.join(CWD, "../"))
20
21# pylint: disable=C0413
22from lib import topotest
23from lib.topogen import Topogen, TopoRouter, get_topogen
4972a6ee 24from lib.common_config import step
83c78d54
DA
25
26pytestmark = [pytest.mark.ripd]
27
28
29def setup_module(mod):
4972a6ee 30 topodef = {"s1": ("r1", "r2", "r3", "r4", "r5")}
83c78d54
DA
31 tgen = Topogen(topodef, mod.__name__)
32 tgen.start_topology()
33
34 router_list = tgen.routers()
35
36 for _, (rname, router) in enumerate(router_list.items(), 1):
37 router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
38
39 tgen.start_router()
40
41
42def teardown_module(mod):
43 tgen = get_topogen()
44 tgen.stop_topology()
45
46
47def test_rip_allow_ecmp():
48 tgen = get_topogen()
49
50 if tgen.routers_have_failure():
51 pytest.skip(tgen.errors)
52
53 r1 = tgen.gears["r1"]
54
55 def _show_rip_routes():
9b3fd1ef
CH
56 xpath = (
57 "/frr-ripd:ripd/instance[vrf='default']"
58 "/state/routes/route[prefix='10.10.10.1/32']"
8d6765aa 59 )
9b3fd1ef
CH
60 try:
61 output = json.loads(
62 r1.vtysh_cmd(f"show yang operational-data {xpath} ripd")
63 )
64 except Exception:
65 return False
66
83c78d54
DA
67 try:
68 output = output["frr-ripd:ripd"]["instance"][0]["state"]["routes"]
69 except KeyError:
70 return False
71
72 expected = {
73 "route": [
74 {
75 "prefix": "10.10.10.1/32",
76 "nexthops": {
77 "nexthop": [
78 {
79 "nh-type": "ip4",
80 "protocol": "rip",
81 "rip-type": "normal",
82 "gateway": "192.168.1.2",
83 "from": "192.168.1.2",
84 "tag": 0,
85 },
86 {
87 "nh-type": "ip4",
88 "protocol": "rip",
89 "rip-type": "normal",
90 "gateway": "192.168.1.3",
91 "from": "192.168.1.3",
92 "tag": 0,
93 },
94 ]
95 },
96 "metric": 2,
83c78d54
DA
97 },
98 ]
99 }
100 return topotest.json_cmp(output, expected)
101
102 test_func = functools.partial(_show_rip_routes)
103 _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
104 assert result is None, "Can't see 10.10.10.1/32 as multipath in `show ip rip`"
105
66e0f6c4 106 def _show_routes(nh_num):
83c78d54
DA
107 output = json.loads(r1.vtysh_cmd("show ip route json"))
108 expected = {
109 "10.10.10.1/32": [
110 {
66e0f6c4
DA
111 "internalNextHopNum": nh_num,
112 "internalNextHopActiveNum": nh_num,
83c78d54
DA
113 "nexthops": [
114 {
115 "ip": "192.168.1.2",
116 "active": True,
117 },
118 {
119 "ip": "192.168.1.3",
120 "active": True,
121 },
66e0f6c4 122 ],
83c78d54
DA
123 }
124 ]
125 }
126 return topotest.json_cmp(output, expected)
127
66e0f6c4 128 test_func = functools.partial(_show_routes, 4)
83c78d54 129 _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
66e0f6c4 130 assert result is None, "Can't see 10.10.10.1/32 as multipath (4) in `show ip route`"
83c78d54 131
4972a6ee
DA
132 step(
133 "Configure allow-ecmp 2, ECMP group routes SHOULD have next-hops with the lowest IPs"
134 )
135 r1.vtysh_cmd(
136 """
137 configure terminal
138 router rip
139 allow-ecmp 2
140 """
141 )
142
143 test_func = functools.partial(_show_rip_routes)
144 _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
145 assert (
146 result is None
147 ), "Can't see 10.10.10.1/32 as ECMP with the lowest next-hop IPs"
148
66e0f6c4
DA
149 test_func = functools.partial(_show_routes, 2)
150 _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
151 assert result is None, "Can't see 10.10.10.1/32 as multipath (2) in `show ip route`"
152
83c78d54
DA
153
154if __name__ == "__main__":
155 args = ["-s"] + sys.argv[1:]
156 sys.exit(pytest.main(args))