Skip to content

Commit 0a491ff

Browse files
committed
test: add new tests for RIP
Signed-off-by: Joachim Wiberg <[email protected]>
1 parent 024b51c commit 0a491ff

File tree

21 files changed

+1620
-1
lines changed

21 files changed

+1620
-1
lines changed

test/case/routing/Readme.adoc

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@ Tests verifying standard routing protocols and configuration:
77
- OSPF basic neighbor discovery and LSA exchange
88
- OSPF unnumbered interface configuration
99
- OSPF multi-area configuration and inter-area routing
10-
- OSPF with BFD (Bidirectional Forwarding Detection)
10+
- OSPF with BFD (Bidirectional Forwarding Detection)
1111
- OSPF default route advertisement and propagation
1212
- OSPF debug logging configuration and verification
13+
- RIP basic neighbor discovery and route exchange
14+
- RIP passive interface configuration
15+
- RIP route redistribution (connected, static, and OSPF)
16+
- RIP multi-hop routing with multiple neighbors
1317
- Route preference handling for OSPF routes
1418
- Route preference handling for DHCP-learned routes
1519
- Administrative distance configuration (route preference 255)
@@ -42,6 +46,22 @@ include::ospf_debug/Readme.adoc[]
4246

4347
<<<
4448

49+
include::rip_basic/Readme.adoc[]
50+
51+
<<<
52+
53+
include::rip_passive_interface/Readme.adoc[]
54+
55+
<<<
56+
57+
include::rip_redistribute/Readme.adoc[]
58+
59+
<<<
60+
61+
include::rip_multihop/Readme.adoc[]
62+
63+
<<<
64+
4565
include::route_pref_ospf/Readme.adoc[]
4666

4767
<<<

test/case/routing/all.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,15 @@
2828

2929
- name: OSPF Debug Logging
3030
case: ospf_debug/test.py
31+
32+
- name: RIP Basic
33+
case: rip_basic/test.py
34+
35+
- name: RIP Passive Interface
36+
case: rip_passive_interface/test.py
37+
38+
- name: RIP Redistribution
39+
case: rip_redistribute/test.py
40+
41+
- name: RIP Multi-hop
42+
case: rip_multihop/test.py
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test.adoc
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
=== RIP Basic
2+
3+
ifdef::topdoc[:imagesdir: {topdoc}../../test/case/routing/rip_basic]
4+
5+
==== Description
6+
7+
Verifies basic RIP functionality by configuring two routers (R1 and R2)
8+
with RIP on their interconnecting link. The test ensures RIP routes are
9+
exchanged between the routers and end-to-end connectivity is achieved.
10+
11+
The test PC uses data1 interface to connect to R1's data port, and data2
12+
interface to connect to R2's data port (which does not have RIP enabled).
13+
This verifies that RIP status information remains accessible when a router
14+
has non-RIP interfaces.
15+
16+
==== Topology
17+
18+
image::topology.svg[RIP Basic topology, align=center, scaledwidth=75%]
19+
20+
==== Sequence
21+
22+
. Set up topology and attach to target DUTs
23+
. Configure targets
24+
. Wait for RIP routes to be exchanged
25+
. Test connectivity from PC:data1 to R2 loopback via RIP
26+
. Test connectivity from PC:data2 to R1 loopback via RIP
27+
28+
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
#!/usr/bin/env python3
2+
"""RIP Basic
3+
4+
Verifies basic RIP functionality by configuring two routers (R1 and R2)
5+
with RIP on their interconnecting link. The test ensures RIP routes are
6+
exchanged between the routers and end-to-end connectivity is achieved.
7+
8+
The test PC uses data1 interface to connect to R1's data port, and data2
9+
interface to connect to R2's data port (which does not have RIP enabled).
10+
This verifies that RIP status information remains accessible when a router
11+
has non-RIP interfaces.
12+
13+
"""
14+
15+
import infamy
16+
import infamy.route as route
17+
from infamy.util import until, parallel
18+
19+
20+
def config_target1(target, data, link):
21+
target.put_config_dicts({
22+
"ietf-interfaces": {
23+
"interfaces": {
24+
"interface": [{
25+
"name": data,
26+
"enabled": True,
27+
"ipv4": {
28+
"forwarding": True,
29+
"address": [{
30+
"ip": "192.168.10.1",
31+
"prefix-length": 24
32+
}]}
33+
}, {
34+
"name": link,
35+
"enabled": True,
36+
"ipv4": {
37+
"forwarding": True,
38+
"address": [{
39+
"ip": "192.168.50.1",
40+
"prefix-length": 24
41+
}]
42+
}
43+
}, {
44+
"name": "lo",
45+
"enabled": True,
46+
"ipv4": {
47+
"address": [{
48+
"ip": "192.168.100.1",
49+
"prefix-length": 32
50+
}]
51+
}
52+
}]
53+
}
54+
},
55+
"ietf-system": {
56+
"system": {
57+
"hostname": "R1"
58+
}
59+
},
60+
"ietf-routing": {
61+
"routing": {
62+
"control-plane-protocols": {
63+
"control-plane-protocol": [{
64+
"type": "infix-routing:static",
65+
"name": "default",
66+
"static-routes": {
67+
"ipv4": {
68+
"route": [{
69+
"destination-prefix": "192.168.33.1/32",
70+
"next-hop": {
71+
"special-next-hop": "blackhole"
72+
}
73+
}]
74+
}
75+
}
76+
}, {
77+
"type": "infix-routing:ripv2",
78+
"name": "default",
79+
"rip": {
80+
"timers": {
81+
"update-interval": 5,
82+
"invalid-interval": 15,
83+
"flush-interval": 20
84+
},
85+
"redistribute": {
86+
"redistribute": [{
87+
"protocol": "static"
88+
}, {
89+
"protocol": "connected"
90+
}]
91+
},
92+
"interfaces": {
93+
"interface": [{
94+
"interface": link
95+
}]
96+
}
97+
}
98+
}]
99+
}
100+
}
101+
}
102+
})
103+
104+
105+
def config_target2(target, link, data):
106+
target.put_config_dicts({
107+
"ietf-interfaces": {
108+
"interfaces": {
109+
"interface": [{
110+
"name": link,
111+
"enabled": True,
112+
"ipv4": {
113+
"forwarding": True,
114+
"address": [{
115+
"ip": "192.168.50.2",
116+
"prefix-length": 24
117+
}]
118+
}
119+
}, {
120+
"name": data,
121+
"enabled": True,
122+
"ipv4": {
123+
"forwarding": True,
124+
"address": [{
125+
"ip": "192.168.60.1",
126+
"prefix-length": 24
127+
}]
128+
}
129+
}, {
130+
"name": "lo",
131+
"enabled": True,
132+
"forwarding": True,
133+
"ipv4": {
134+
"address": [{
135+
"ip": "192.168.200.1",
136+
"prefix-length": 32
137+
}]
138+
}
139+
}]
140+
}
141+
},
142+
"ietf-system": {
143+
"system": {
144+
"hostname": "R2"
145+
}
146+
},
147+
"ietf-routing": {
148+
"routing": {
149+
"control-plane-protocols": {
150+
"control-plane-protocol": [{
151+
"type": "infix-routing:ripv2",
152+
"name": "default",
153+
"rip": {
154+
"timers": {
155+
"update-interval": 5,
156+
"invalid-interval": 15,
157+
"flush-interval": 20
158+
},
159+
"redistribute": {
160+
"redistribute": [{
161+
"protocol": "connected"
162+
}]
163+
},
164+
"interfaces": {
165+
"interface": [{
166+
"interface": link
167+
}]
168+
}
169+
}
170+
}]
171+
}
172+
}
173+
}
174+
})
175+
176+
177+
with infamy.Test() as test:
178+
with test.step("Set up topology and attach to target DUTs"):
179+
env = infamy.Env()
180+
R1 = env.attach("R1", "mgmt")
181+
R2 = env.attach("R2", "mgmt")
182+
183+
with test.step("Configure targets"):
184+
_, R1data = env.ltop.xlate("R1", "data")
185+
_, R2link = env.ltop.xlate("R2", "link")
186+
_, R1link = env.ltop.xlate("R1", "link")
187+
_, R2data = env.ltop.xlate("R2", "data")
188+
189+
parallel(config_target1(R1, R1data, R1link),
190+
config_target2(R2, R2link, R2data))
191+
192+
with test.step("Wait for RIP routes to be exchanged"):
193+
print("Waiting for RIP routes to propagate...")
194+
# R1 should learn R2's loopback
195+
until(lambda: route.ipv4_route_exist(R1, "192.168.200.1/32", proto="ietf-rip:rip"), attempts=40)
196+
# R2 should learn R1's loopback
197+
until(lambda: route.ipv4_route_exist(R2, "192.168.100.1/32", proto="ietf-rip:rip"), attempts=40)
198+
# R2 should learn R1's static route (redistributed)
199+
until(lambda: route.ipv4_route_exist(R2, "192.168.33.1/32", proto="ietf-rip:rip"), attempts=40)
200+
201+
with test.step("Test connectivity from PC:data1 to R2 loopback via RIP"):
202+
_, hport0 = env.ltop.xlate("PC", "data1")
203+
with infamy.IsolatedMacVlan(hport0) as ns0:
204+
ns0.addip("192.168.10.2")
205+
ns0.addroute("192.168.200.1/32", "192.168.10.1")
206+
ns0.must_reach("192.168.200.1")
207+
208+
with test.step("Test connectivity from PC:data2 to R1 loopback via RIP"):
209+
_, hport1 = env.ltop.xlate("PC", "data2")
210+
with infamy.IsolatedMacVlan(hport1) as ns1:
211+
ns1.addip("192.168.60.2")
212+
ns1.addroute("192.168.100.1/32", "192.168.60.1")
213+
ns1.must_reach("192.168.100.1")
214+
215+
test.succeed()
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
graph "2x2" {
2+
layout="neato";
3+
overlap="false";
4+
esep="+40";
5+
size=10
6+
7+
node [shape=record, fontname="DejaVu Sans Mono, Book"];
8+
edge [color="cornflowerblue", penwidth="2", fontname="DejaVu Serif, Book"];
9+
10+
PC [
11+
label="PC | { <mgmt1> mgmt1 | <data1> data1 | \n\n\n\n\n\n\n\n | <mgmt2> mgmt2 | <data2> data2 }",
12+
pos="20,50!",
13+
requires="controller",
14+
];
15+
16+
R1 [
17+
label="{ <mgmt> mgmt | <data> data | <link> link} | R1 \n 192.168.100.1/32 \n(lo)",
18+
pos="190,85!",
19+
20+
requires="infix",
21+
];
22+
R2 [
23+
label="{ <link> link | <mgmt> mgmt | <data> data } | R2 \n 192.168.200.1/32 \n(lo)",
24+
pos="190,15!",
25+
26+
requires="infix",
27+
];
28+
29+
PC:mgmt1 -- R1:mgmt [requires="mgmt", color="lightgray"]
30+
PC:mgmt2 -- R2:mgmt [requires="mgmt", color="lightgray"]
31+
PC:data1 -- R1:data [color="black", label="192.168.10.0/24", headlabel=".1", taillabel=".2", labeldistance=2, fontcolor="black"]
32+
R1:link -- R2:link [label="192.168.50.0/24", headlabel=".2", taillabel=".1", labeldistance=2, fontcolor="black", color="black"]
33+
PC:data2 -- R2:data [label="192.168.60.0/24", headlabel=".1", taillabel=".2", labeldistance=2, fontcolor="black", color="black"]
34+
}

0 commit comments

Comments
 (0)