mirror of
https://github.com/kernelkit/infix.git
synced 2026-08-02 05:43:02 +02:00
ospf: add point-to-multipoint and hybrid interface type support
This commit is contained in:
@@ -10,6 +10,8 @@ Tests verifying standard routing protocols and configuration:
|
||||
- OSPF with BFD (Bidirectional Forwarding Detection)
|
||||
- OSPF default route advertisement and propagation
|
||||
- OSPF debug logging configuration and verification
|
||||
- OSPF point-to-multipoint hybrid (broadcast) interface type
|
||||
- OSPF point-to-multipoint (non-broadcast) interface type with static neighbors
|
||||
- RIP basic neighbor discovery and route exchange
|
||||
- RIP passive interface configuration
|
||||
- RIP route redistribution (connected, static, and OSPF)
|
||||
@@ -46,6 +48,14 @@ include::ospf_debug/Readme.adoc[]
|
||||
|
||||
<<<
|
||||
|
||||
include::ospf_point_to_multipoint_hybrid/Readme.adoc[]
|
||||
|
||||
<<<
|
||||
|
||||
include::ospf_point_to_multipoint/Readme.adoc[]
|
||||
|
||||
<<<
|
||||
|
||||
include::rip_basic/Readme.adoc[]
|
||||
|
||||
<<<
|
||||
|
||||
@@ -29,6 +29,12 @@
|
||||
- name: OSPF Debug Logging
|
||||
case: ospf_debug/test.py
|
||||
|
||||
- name: OSPF Point-to-Multipoint Hybrid
|
||||
case: ospf_point_to_multipoint_hybrid/test.py
|
||||
|
||||
- name: OSPF Point-to-Multipoint
|
||||
case: ospf_point_to_multipoint/test.py
|
||||
|
||||
- name: RIP Basic
|
||||
case: rip_basic/test.py
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
test.adoc
|
||||
Binary file not shown.
@@ -0,0 +1,49 @@
|
||||
=== OSPF Point-to-Multipoint
|
||||
|
||||
ifdef::topdoc[:imagesdir: {topdoc}../../test/case/routing/ospf_point_to_multipoint]
|
||||
|
||||
==== Description
|
||||
|
||||
Verify OSPF point-to-multipoint (non-broadcast) interface type by
|
||||
configuring three routers on a shared multi-access network with the
|
||||
ietf-ospf 'point-to-multipoint' interface type and static neighbors.
|
||||
This maps to FRR's 'point-to-multipoint non-broadcast' network type,
|
||||
which requires manual neighbor configuration since there is no
|
||||
multicast neighbor discovery.
|
||||
|
||||
R2 acts as the hub, bridging two physical links (link1, link2) into a
|
||||
single broadcast domain (br0). R1 and R3 each connect to one of R2's
|
||||
ports. The test verifies that all routers form OSPF adjacencies via
|
||||
unicast, exchange routes, and that the interface type is correctly
|
||||
reported as point-to-multipoint.
|
||||
|
||||
....
|
||||
+------------------+ +------------------+
|
||||
| R1 | | R3 |
|
||||
| 10.0.1.1/32 | | 10.0.3.1/32 |
|
||||
| (lo) | | (lo) |
|
||||
+--------+---------+ +--------+---------+
|
||||
| .1 | .3
|
||||
| +------------------+ |
|
||||
+----link1------+ R2 +------link2--------+
|
||||
| 10.0.2.1/32 |
|
||||
| (lo) |
|
||||
| br0: 10.0.123.2 |
|
||||
+------------------+
|
||||
10.0.123.0/24
|
||||
(P2MP non-broadcast / shared segment)
|
||||
....
|
||||
|
||||
==== Topology
|
||||
|
||||
image::topology.svg[OSPF Point-to-Multipoint topology, align=center, scaledwidth=75%]
|
||||
|
||||
==== Sequence
|
||||
|
||||
. Set up topology and attach to target DUTs
|
||||
. Configure targets
|
||||
. Wait for OSPF routes
|
||||
. Verify interface type is point-to-multipoint
|
||||
. Verify connectivity between all DUTs
|
||||
|
||||
|
||||
+341
@@ -0,0 +1,341 @@
|
||||
#!/usr/bin/env python3
|
||||
"""OSPF Point-to-Multipoint
|
||||
|
||||
Verify OSPF point-to-multipoint (non-broadcast) interface type by
|
||||
configuring three routers on a shared multi-access network with the
|
||||
ietf-ospf 'point-to-multipoint' interface type and static neighbors.
|
||||
This maps to FRR's 'point-to-multipoint non-broadcast' network type,
|
||||
which requires manual neighbor configuration since there is no
|
||||
multicast neighbor discovery.
|
||||
|
||||
R2 acts as the hub, bridging two physical links (link1, link2) into a
|
||||
single broadcast domain (br0). R1 and R3 each connect to one of R2's
|
||||
ports. The test verifies that all routers form OSPF adjacencies via
|
||||
unicast, exchange routes, and that the interface type is correctly
|
||||
reported as point-to-multipoint.
|
||||
|
||||
....
|
||||
+------------------+ +------------------+
|
||||
| R1 | | R3 |
|
||||
| 10.0.1.1/32 | | 10.0.3.1/32 |
|
||||
| (lo) | | (lo) |
|
||||
+--------+---------+ +--------+---------+
|
||||
| .1 | .3
|
||||
| +------------------+ |
|
||||
+----link1------+ R2 +------link2--------+
|
||||
| 10.0.2.1/32 |
|
||||
| (lo) |
|
||||
| br0: 10.0.123.2 |
|
||||
+------------------+
|
||||
10.0.123.0/24
|
||||
(P2MP non-broadcast / shared segment)
|
||||
....
|
||||
"""
|
||||
|
||||
import infamy
|
||||
import infamy.route as route
|
||||
from infamy.util import until, parallel
|
||||
|
||||
|
||||
def config_target1(target, link, data):
|
||||
target.put_config_dicts({
|
||||
"ietf-interfaces": {
|
||||
"interfaces": {
|
||||
"interface": [
|
||||
{
|
||||
"name": link,
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"forwarding": True,
|
||||
"address": [{
|
||||
"ip": "10.0.123.1",
|
||||
"prefix-length": 24
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": data,
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"forwarding": True,
|
||||
"address": [{
|
||||
"ip": "10.0.10.1",
|
||||
"prefix-length": 24
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lo",
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"address": [{
|
||||
"ip": "10.0.1.1",
|
||||
"prefix-length": 32
|
||||
}]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"ietf-routing": {
|
||||
"routing": {
|
||||
"control-plane-protocols": {
|
||||
"control-plane-protocol": [{
|
||||
"type": "infix-routing:ospfv2",
|
||||
"name": "default",
|
||||
"ospf": {
|
||||
"redistribute": {
|
||||
"redistribute": [{
|
||||
"protocol": "connected"
|
||||
}]
|
||||
},
|
||||
"areas": {
|
||||
"area": [{
|
||||
"area-id": "0.0.0.0",
|
||||
"interfaces": {
|
||||
"interface": [{
|
||||
"name": link,
|
||||
"enabled": True,
|
||||
"hello-interval": 1,
|
||||
"dead-interval": 3,
|
||||
"interface-type": "point-to-multipoint",
|
||||
"static-neighbors": {
|
||||
"neighbor": [
|
||||
{"identifier": "10.0.123.2"},
|
||||
{"identifier": "10.0.123.3"}
|
||||
]
|
||||
}
|
||||
}, {
|
||||
"name": "lo",
|
||||
"enabled": True
|
||||
}]
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
def config_target2(target, link1, link2):
|
||||
target.put_config_dicts({
|
||||
"ietf-interfaces": {
|
||||
"interfaces": {
|
||||
"interface": [
|
||||
{
|
||||
"name": "br0",
|
||||
"type": "infix-if-type:bridge",
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"forwarding": True,
|
||||
"address": [{
|
||||
"ip": "10.0.123.2",
|
||||
"prefix-length": 24
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": link1,
|
||||
"enabled": True,
|
||||
"infix-interfaces:bridge-port": {
|
||||
"bridge": "br0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": link2,
|
||||
"enabled": True,
|
||||
"infix-interfaces:bridge-port": {
|
||||
"bridge": "br0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lo",
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"address": [{
|
||||
"ip": "10.0.2.1",
|
||||
"prefix-length": 32
|
||||
}]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"ietf-routing": {
|
||||
"routing": {
|
||||
"control-plane-protocols": {
|
||||
"control-plane-protocol": [{
|
||||
"type": "infix-routing:ospfv2",
|
||||
"name": "default",
|
||||
"ospf": {
|
||||
"redistribute": {
|
||||
"redistribute": [{
|
||||
"protocol": "connected"
|
||||
}]
|
||||
},
|
||||
"areas": {
|
||||
"area": [{
|
||||
"area-id": "0.0.0.0",
|
||||
"interfaces": {
|
||||
"interface": [{
|
||||
"name": "br0",
|
||||
"enabled": True,
|
||||
"hello-interval": 1,
|
||||
"dead-interval": 3,
|
||||
"interface-type": "point-to-multipoint",
|
||||
"static-neighbors": {
|
||||
"neighbor": [
|
||||
{"identifier": "10.0.123.1"},
|
||||
{"identifier": "10.0.123.3"}
|
||||
]
|
||||
}
|
||||
}, {
|
||||
"name": "lo",
|
||||
"enabled": True
|
||||
}]
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
def config_target3(target, link, data):
|
||||
target.put_config_dicts({
|
||||
"ietf-interfaces": {
|
||||
"interfaces": {
|
||||
"interface": [
|
||||
{
|
||||
"name": link,
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"forwarding": True,
|
||||
"address": [{
|
||||
"ip": "10.0.123.3",
|
||||
"prefix-length": 24
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": data,
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"forwarding": True,
|
||||
"address": [{
|
||||
"ip": "10.0.30.1",
|
||||
"prefix-length": 24
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lo",
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"address": [{
|
||||
"ip": "10.0.3.1",
|
||||
"prefix-length": 32
|
||||
}]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"ietf-routing": {
|
||||
"routing": {
|
||||
"control-plane-protocols": {
|
||||
"control-plane-protocol": [{
|
||||
"type": "infix-routing:ospfv2",
|
||||
"name": "default",
|
||||
"ospf": {
|
||||
"redistribute": {
|
||||
"redistribute": [{
|
||||
"protocol": "connected"
|
||||
}]
|
||||
},
|
||||
"areas": {
|
||||
"area": [{
|
||||
"area-id": "0.0.0.0",
|
||||
"interfaces": {
|
||||
"interface": [{
|
||||
"name": link,
|
||||
"enabled": True,
|
||||
"hello-interval": 1,
|
||||
"dead-interval": 3,
|
||||
"interface-type": "point-to-multipoint",
|
||||
"static-neighbors": {
|
||||
"neighbor": [
|
||||
{"identifier": "10.0.123.1"},
|
||||
{"identifier": "10.0.123.2"}
|
||||
]
|
||||
}
|
||||
}, {
|
||||
"name": "lo",
|
||||
"enabled": True
|
||||
}]
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
with infamy.Test() as test:
|
||||
with test.step("Set up topology and attach to target DUTs"):
|
||||
env = infamy.Env()
|
||||
R1 = env.attach("R1", "mgmt")
|
||||
R2 = env.attach("R2", "mgmt")
|
||||
R3 = env.attach("R3", "mgmt")
|
||||
|
||||
|
||||
with test.step("Configure targets"):
|
||||
_, R1link = env.ltop.xlate("R1", "link")
|
||||
_, R1data = env.ltop.xlate("R1", "data")
|
||||
_, R2link1 = env.ltop.xlate("R2", "link1")
|
||||
_, R2link2 = env.ltop.xlate("R2", "link2")
|
||||
_, R3link = env.ltop.xlate("R3", "link")
|
||||
_, R3data = env.ltop.xlate("R3", "data")
|
||||
|
||||
parallel(config_target1(R1, R1link, R1data),
|
||||
config_target2(R2, R2link1, R2link2),
|
||||
config_target3(R3, R3link, R3data))
|
||||
|
||||
with test.step("Wait for OSPF routes"):
|
||||
print("Waiting for OSPF routes from all routers")
|
||||
until(lambda: route.ipv4_route_exist(R1, "10.0.2.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
||||
until(lambda: route.ipv4_route_exist(R1, "10.0.3.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
||||
until(lambda: route.ipv4_route_exist(R2, "10.0.1.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
||||
until(lambda: route.ipv4_route_exist(R2, "10.0.3.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
||||
until(lambda: route.ipv4_route_exist(R3, "10.0.1.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
||||
until(lambda: route.ipv4_route_exist(R3, "10.0.2.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
||||
|
||||
with test.step("Verify interface type is point-to-multipoint"):
|
||||
print("Checking OSPF interface type on all routers")
|
||||
assert route.ospf_get_interface_type(R1, "0.0.0.0", R1link) == "point-to-multipoint"
|
||||
assert route.ospf_get_interface_type(R2, "0.0.0.0", "br0") == "point-to-multipoint"
|
||||
assert route.ospf_get_interface_type(R3, "0.0.0.0", R3link) == "point-to-multipoint"
|
||||
|
||||
with test.step("Verify connectivity between all DUTs"):
|
||||
_, hport1 = env.ltop.xlate("PC", "data1")
|
||||
_, hport2 = env.ltop.xlate("PC", "data2")
|
||||
with infamy.IsolatedMacVlan(hport1) as ns1, \
|
||||
infamy.IsolatedMacVlan(hport2) as ns2:
|
||||
ns1.addip("10.0.10.2")
|
||||
ns2.addip("10.0.30.2")
|
||||
ns1.addroute("10.0.3.1/32", "10.0.10.1")
|
||||
ns2.addroute("10.0.1.1/32", "10.0.30.1")
|
||||
parallel(
|
||||
lambda: ns1.must_reach("10.0.3.1"),
|
||||
lambda: ns2.must_reach("10.0.1.1"),
|
||||
)
|
||||
test.succeed()
|
||||
@@ -0,0 +1,39 @@
|
||||
graph "3x1" {
|
||||
layout="neato";
|
||||
overlap="false";
|
||||
esep="+20";
|
||||
size=10
|
||||
|
||||
node [shape=record, fontname="DejaVu Sans Mono, Book"];
|
||||
edge [color="cornflowerblue", penwidth="2", fontname="DejaVu Serif, Book"];
|
||||
|
||||
PC [
|
||||
label="PC | { <mgmt1> mgmt1 | <data1> data1 | \n\n\n\n | <mgmt2> mgmt2 | <mgmt3> mgmt3 | <data2> data2 }",
|
||||
pos="20,30!",
|
||||
requires="controller",
|
||||
];
|
||||
|
||||
R1 [
|
||||
label="{ <mgmt> mgmt | <data> data | <link> link } | R1 \n 10.0.1.1/32 \n(lo)",
|
||||
pos="160,60!",
|
||||
requires="infix",
|
||||
];
|
||||
R2 [
|
||||
label="{ <link1> link1 | <mgmt> mgmt | <link2> link2 } | R2 \n 10.0.2.1/32 \n(lo) \n(br0: 10.0.123.2/24)",
|
||||
pos="160,30!",
|
||||
requires="infix",
|
||||
];
|
||||
R3 [
|
||||
label="{ <link> link | <mgmt> mgmt | <data> data } | R3 \n 10.0.3.1/32 \n(lo)",
|
||||
pos="160,0!",
|
||||
requires="infix",
|
||||
];
|
||||
|
||||
PC:mgmt1 -- R1:mgmt [requires="mgmt", color="lightgray"]
|
||||
PC:mgmt2 -- R2:mgmt [requires="mgmt", color="lightgray"]
|
||||
PC:mgmt3 -- R3:mgmt [requires="mgmt", color="lightgray"]
|
||||
PC:data1 -- R1:data [taillabel="10.0.10.2/24", headlabel="10.0.10.1/24"]
|
||||
R3:data -- PC:data2 [taillabel="10.0.30.1/24", headlabel="10.0.30.2/24"]
|
||||
R1:link -- R2:link1 [taillabel="10.0.123.1/24"]
|
||||
R3:link -- R2:link2 [taillabel="10.0.123.3/24"]
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
|
||||
<!-- Title: 3x1 Pages: 1 -->
|
||||
<svg width="720pt" height="312pt"
|
||||
viewBox="0.00 0.00 720.00 312.15" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(0.98 0.98) rotate(0) translate(4 314.02)">
|
||||
<title>3x1</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-314.02 729.56,-314.02 729.56,4 -4,4"/>
|
||||
<!-- PC -->
|
||||
<g id="node1" class="node">
|
||||
<title>PC</title>
|
||||
<polygon fill="none" stroke="black" points="0,-61.51 0,-248.51 91,-248.51 91,-61.51 0,-61.51"/>
|
||||
<text text-anchor="middle" x="16.5" y="-151.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">PC</text>
|
||||
<polyline fill="none" stroke="black" points="33,-61.51 33,-248.51 "/>
|
||||
<text text-anchor="middle" x="62" y="-233.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt1</text>
|
||||
<polyline fill="none" stroke="black" points="33,-225.51 91,-225.51 "/>
|
||||
<text text-anchor="middle" x="62" y="-210.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">data1</text>
|
||||
<polyline fill="none" stroke="black" points="33,-202.51 91,-202.51 "/>
|
||||
<polyline fill="none" stroke="black" points="33,-130.51 91,-130.51 "/>
|
||||
<text text-anchor="middle" x="62" y="-115.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt2</text>
|
||||
<polyline fill="none" stroke="black" points="33,-107.51 91,-107.51 "/>
|
||||
<text text-anchor="middle" x="62" y="-92.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt3</text>
|
||||
<polyline fill="none" stroke="black" points="33,-84.51 91,-84.51 "/>
|
||||
<text text-anchor="middle" x="62" y="-69.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">data2</text>
|
||||
</g>
|
||||
<!-- R1 -->
|
||||
<g id="node2" class="node">
|
||||
<title>R1</title>
|
||||
<polygon fill="none" stroke="black" points="518.56,-240.52 518.56,-309.52 692.56,-309.52 692.56,-240.52 518.56,-240.52"/>
|
||||
<text text-anchor="middle" x="543.56" y="-294.32" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
|
||||
<polyline fill="none" stroke="black" points="518.56,-286.52 568.56,-286.52 "/>
|
||||
<text text-anchor="middle" x="543.56" y="-271.32" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
|
||||
<polyline fill="none" stroke="black" points="518.56,-263.52 568.56,-263.52 "/>
|
||||
<text text-anchor="middle" x="543.56" y="-248.32" font-family="DejaVu Sans Mono, Book" font-size="14.00">link</text>
|
||||
<polyline fill="none" stroke="black" points="568.56,-240.52 568.56,-309.52 "/>
|
||||
<text text-anchor="middle" x="630.56" y="-286.32" font-family="DejaVu Sans Mono, Book" font-size="14.00">R1 </text>
|
||||
<text text-anchor="middle" x="630.56" y="-271.32" font-family="DejaVu Sans Mono, Book" font-size="14.00"> 10.0.1.1/32 </text>
|
||||
<text text-anchor="middle" x="630.56" y="-256.32" font-family="DejaVu Sans Mono, Book" font-size="14.00">(lo)</text>
|
||||
</g>
|
||||
<!-- PC--R1 -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>PC:mgmt1--R1:mgmt</title>
|
||||
<path fill="none" stroke="lightgray" stroke-width="2" d="M91.5,-237.01C91.5,-237.01 518.56,-298.02 518.56,-298.02"/>
|
||||
</g>
|
||||
<!-- PC--R1 -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>PC:data1--R1:data</title>
|
||||
<path fill="none" stroke="cornflowerblue" stroke-width="2" d="M91.5,-214.01C91.5,-214.01 518.56,-275.02 518.56,-275.02"/>
|
||||
<text text-anchor="middle" x="473.06" y="-278.82" font-family="DejaVu Serif, Book" font-size="14.00">10.0.10.1/24</text>
|
||||
<text text-anchor="middle" x="137" y="-217.81" font-family="DejaVu Serif, Book" font-size="14.00">10.0.10.2/24</text>
|
||||
</g>
|
||||
<!-- R2 -->
|
||||
<g id="node3" class="node">
|
||||
<title>R2</title>
|
||||
<polygon fill="none" stroke="black" points="485.56,-120.51 485.56,-189.51 725.56,-189.51 725.56,-120.51 485.56,-120.51"/>
|
||||
<text text-anchor="middle" x="514.56" y="-174.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">link1</text>
|
||||
<polyline fill="none" stroke="black" points="485.56,-166.51 543.56,-166.51 "/>
|
||||
<text text-anchor="middle" x="514.56" y="-151.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
|
||||
<polyline fill="none" stroke="black" points="485.56,-143.51 543.56,-143.51 "/>
|
||||
<text text-anchor="middle" x="514.56" y="-128.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">link2</text>
|
||||
<polyline fill="none" stroke="black" points="543.56,-120.51 543.56,-189.51 "/>
|
||||
<text text-anchor="middle" x="634.56" y="-173.81" font-family="DejaVu Sans Mono, Book" font-size="14.00">R2 </text>
|
||||
<text text-anchor="middle" x="634.56" y="-158.81" font-family="DejaVu Sans Mono, Book" font-size="14.00"> 10.0.2.1/32 </text>
|
||||
<text text-anchor="middle" x="634.56" y="-143.81" font-family="DejaVu Sans Mono, Book" font-size="14.00">(lo) </text>
|
||||
<text text-anchor="middle" x="634.56" y="-128.81" font-family="DejaVu Sans Mono, Book" font-size="14.00">(br0: 10.0.123.2/24)</text>
|
||||
</g>
|
||||
<!-- PC--R2 -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>PC:mgmt2--R2:mgmt</title>
|
||||
<path fill="none" stroke="lightgray" stroke-width="2" d="M91.5,-119.01C91.5,-119.01 485.56,-155.01 485.56,-155.01"/>
|
||||
</g>
|
||||
<!-- R3 -->
|
||||
<g id="node4" class="node">
|
||||
<title>R3</title>
|
||||
<polygon fill="none" stroke="black" points="518.56,-0.5 518.56,-69.5 692.56,-69.5 692.56,-0.5 518.56,-0.5"/>
|
||||
<text text-anchor="middle" x="543.56" y="-54.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">link</text>
|
||||
<polyline fill="none" stroke="black" points="518.56,-46.5 568.56,-46.5 "/>
|
||||
<text text-anchor="middle" x="543.56" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
|
||||
<polyline fill="none" stroke="black" points="518.56,-23.5 568.56,-23.5 "/>
|
||||
<text text-anchor="middle" x="543.56" y="-8.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
|
||||
<polyline fill="none" stroke="black" points="568.56,-0.5 568.56,-69.5 "/>
|
||||
<text text-anchor="middle" x="630.56" y="-46.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">R3 </text>
|
||||
<text text-anchor="middle" x="630.56" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00"> 10.0.3.1/32 </text>
|
||||
<text text-anchor="middle" x="630.56" y="-16.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">(lo)</text>
|
||||
</g>
|
||||
<!-- PC--R3 -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>PC:mgmt3--R3:mgmt</title>
|
||||
<path fill="none" stroke="lightgray" stroke-width="2" d="M91.5,-96.01C91.5,-96.01 518.56,-35 518.56,-35"/>
|
||||
</g>
|
||||
<!-- R1--R2 -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>R1:link--R2:link1</title>
|
||||
<path fill="none" stroke="cornflowerblue" stroke-width="2" d="M543.56,-240.02C543.56,-240.02 514.56,-190.01 514.56,-190.01"/>
|
||||
<text text-anchor="middle" x="493.56" y="-228.82" font-family="DejaVu Serif, Book" font-size="14.00">10.0.123.1/24</text>
|
||||
</g>
|
||||
<!-- R3--PC -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>R3:data--PC:data2</title>
|
||||
<path fill="none" stroke="cornflowerblue" stroke-width="2" d="M518.56,-12C518.56,-12 91.5,-73.01 91.5,-73.01"/>
|
||||
<text text-anchor="middle" x="137" y="-76.81" font-family="DejaVu Serif, Book" font-size="14.00">10.0.30.2/24</text>
|
||||
<text text-anchor="middle" x="473.06" y="-15.8" font-family="DejaVu Serif, Book" font-size="14.00">10.0.30.1/24</text>
|
||||
</g>
|
||||
<!-- R3--R2 -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>R3:link--R2:link2</title>
|
||||
<path fill="none" stroke="cornflowerblue" stroke-width="2" d="M543.56,-70C543.56,-70 514.56,-120.01 514.56,-120.01"/>
|
||||
<text text-anchor="middle" x="493.56" y="-73.8" font-family="DejaVu Serif, Book" font-size="14.00">10.0.123.3/24</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.4 KiB |
@@ -0,0 +1 @@
|
||||
test.adoc
|
||||
Binary file not shown.
@@ -0,0 +1,46 @@
|
||||
=== OSPF Point-to-Multipoint Hybrid
|
||||
|
||||
ifdef::topdoc[:imagesdir: {topdoc}../../test/case/routing/ospf_point_to_multipoint_hybrid]
|
||||
|
||||
==== Description
|
||||
|
||||
Verify OSPF point-to-multipoint hybrid (broadcast) interface type by
|
||||
configuring three routers on a shared multi-access network with the
|
||||
ietf-ospf 'hybrid' interface type. This maps to FRR's 'point-to-multipoint'
|
||||
network type, which uses multicast for neighbor discovery.
|
||||
|
||||
R2 acts as the hub, bridging two physical links (link1, link2) into a
|
||||
single broadcast domain (br0). R1 and R3 each connect to one of R2's
|
||||
ports. The test verifies that all routers form OSPF adjacencies, exchange
|
||||
routes, and that the interface type is correctly reported as hybrid.
|
||||
|
||||
....
|
||||
+------------------+ +------------------+
|
||||
| R1 | | R3 |
|
||||
| 10.0.1.1/32 | | 10.0.3.1/32 |
|
||||
| (lo) | | (lo) |
|
||||
+--------+---------+ +--------+---------+
|
||||
| .1 | .3
|
||||
| +------------------+ |
|
||||
+----link1------+ R2 +------link2--------+
|
||||
| 10.0.2.1/32 |
|
||||
| (lo) |
|
||||
| br0: 10.0.123.2 |
|
||||
+------------------+
|
||||
10.0.123.0/24
|
||||
(P2MP hybrid / shared segment)
|
||||
....
|
||||
|
||||
==== Topology
|
||||
|
||||
image::topology.svg[OSPF Point-to-Multipoint Hybrid topology, align=center, scaledwidth=75%]
|
||||
|
||||
==== Sequence
|
||||
|
||||
. Set up topology and attach to target DUTs
|
||||
. Configure targets
|
||||
. Wait for OSPF routes
|
||||
. Verify interface type is hybrid
|
||||
. Verify connectivity between all DUTs
|
||||
|
||||
|
||||
+334
@@ -0,0 +1,334 @@
|
||||
#!/usr/bin/env python3
|
||||
"""OSPF Point-to-Multipoint Hybrid
|
||||
|
||||
Verify OSPF point-to-multipoint hybrid (broadcast) interface type by
|
||||
configuring three routers on a shared multi-access network with the
|
||||
ietf-ospf 'hybrid' interface type. This maps to FRR's 'point-to-multipoint'
|
||||
network type, which uses multicast for neighbor discovery.
|
||||
|
||||
R2 acts as the hub, bridging two physical links (link1, link2) into a
|
||||
single broadcast domain (br0). R1 and R3 each connect to one of R2's
|
||||
ports. The test verifies that all routers form OSPF adjacencies, exchange
|
||||
routes, and that the interface type is correctly reported as hybrid.
|
||||
|
||||
....
|
||||
+------------------+ +------------------+
|
||||
| R1 | | R3 |
|
||||
| 10.0.1.1/32 | | 10.0.3.1/32 |
|
||||
| (lo) | | (lo) |
|
||||
+--------+---------+ +--------+---------+
|
||||
| .1 | .3
|
||||
| +------------------+ |
|
||||
+----link1------+ R2 +------link2--------+
|
||||
| 10.0.2.1/32 |
|
||||
| (lo) |
|
||||
| br0: 10.0.123.2 |
|
||||
+------------------+
|
||||
10.0.123.0/24
|
||||
(P2MP hybrid / shared segment)
|
||||
....
|
||||
"""
|
||||
|
||||
import infamy
|
||||
import infamy.route as route
|
||||
from infamy.util import until, parallel
|
||||
|
||||
|
||||
def config_target1(target, link, data):
|
||||
target.put_config_dicts({
|
||||
"ietf-interfaces": {
|
||||
"interfaces": {
|
||||
"interface": [
|
||||
{
|
||||
"name": link,
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"forwarding": True,
|
||||
"address": [{
|
||||
"ip": "10.0.123.1",
|
||||
"prefix-length": 24
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": data,
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"forwarding": True,
|
||||
"address": [{
|
||||
"ip": "10.0.10.1",
|
||||
"prefix-length": 24
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lo",
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"address": [{
|
||||
"ip": "10.0.1.1",
|
||||
"prefix-length": 32
|
||||
}]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"ietf-system": {
|
||||
"system": {
|
||||
"hostname": "R1"
|
||||
}
|
||||
},
|
||||
"ietf-routing": {
|
||||
"routing": {
|
||||
"control-plane-protocols": {
|
||||
"control-plane-protocol": [{
|
||||
"type": "infix-routing:ospfv2",
|
||||
"name": "default",
|
||||
"ospf": {
|
||||
"redistribute": {
|
||||
"redistribute": [{
|
||||
"protocol": "connected"
|
||||
}]
|
||||
},
|
||||
"areas": {
|
||||
"area": [{
|
||||
"area-id": "0.0.0.0",
|
||||
"interfaces": {
|
||||
"interface": [{
|
||||
"name": link,
|
||||
"enabled": True,
|
||||
"interface-type": "hybrid",
|
||||
"hello-interval": 1,
|
||||
"dead-interval": 3
|
||||
}, {
|
||||
"name": "lo",
|
||||
"enabled": True
|
||||
}]
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
def config_target2(target, link1, link2):
|
||||
target.put_config_dicts({
|
||||
"ietf-interfaces": {
|
||||
"interfaces": {
|
||||
"interface": [
|
||||
{
|
||||
"name": "br0",
|
||||
"type": "infix-if-type:bridge",
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"forwarding": True,
|
||||
"address": [{
|
||||
"ip": "10.0.123.2",
|
||||
"prefix-length": 24
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": link1,
|
||||
"enabled": True,
|
||||
"infix-interfaces:bridge-port": {
|
||||
"bridge": "br0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": link2,
|
||||
"enabled": True,
|
||||
"infix-interfaces:bridge-port": {
|
||||
"bridge": "br0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lo",
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"address": [{
|
||||
"ip": "10.0.2.1",
|
||||
"prefix-length": 32
|
||||
}]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"ietf-system": {
|
||||
"system": {
|
||||
"hostname": "R2"
|
||||
}
|
||||
},
|
||||
"ietf-routing": {
|
||||
"routing": {
|
||||
"control-plane-protocols": {
|
||||
"control-plane-protocol": [{
|
||||
"type": "infix-routing:ospfv2",
|
||||
"name": "default",
|
||||
"ospf": {
|
||||
"redistribute": {
|
||||
"redistribute": [{
|
||||
"protocol": "connected"
|
||||
}]
|
||||
},
|
||||
"areas": {
|
||||
"area": [{
|
||||
"area-id": "0.0.0.0",
|
||||
"interfaces": {
|
||||
"interface": [{
|
||||
"name": "br0",
|
||||
"enabled": True,
|
||||
"interface-type": "hybrid",
|
||||
"hello-interval": 1,
|
||||
"dead-interval": 3
|
||||
}, {
|
||||
"name": "lo",
|
||||
"enabled": True
|
||||
}]
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
def config_target3(target, link, data):
|
||||
target.put_config_dicts({
|
||||
"ietf-interfaces": {
|
||||
"interfaces": {
|
||||
"interface": [
|
||||
{
|
||||
"name": link,
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"forwarding": True,
|
||||
"address": [{
|
||||
"ip": "10.0.123.3",
|
||||
"prefix-length": 24
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": data,
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"forwarding": True,
|
||||
"address": [{
|
||||
"ip": "10.0.30.1",
|
||||
"prefix-length": 24
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lo",
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"address": [{
|
||||
"ip": "10.0.3.1",
|
||||
"prefix-length": 32
|
||||
}]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"ietf-system": {
|
||||
"system": {
|
||||
"hostname": "R3"
|
||||
}
|
||||
},
|
||||
"ietf-routing": {
|
||||
"routing": {
|
||||
"control-plane-protocols": {
|
||||
"control-plane-protocol": [{
|
||||
"type": "infix-routing:ospfv2",
|
||||
"name": "default",
|
||||
"ospf": {
|
||||
"redistribute": {
|
||||
"redistribute": [{
|
||||
"protocol": "connected"
|
||||
}]
|
||||
},
|
||||
"areas": {
|
||||
"area": [{
|
||||
"area-id": "0.0.0.0",
|
||||
"interfaces": {
|
||||
"interface": [{
|
||||
"name": link,
|
||||
"enabled": True,
|
||||
"interface-type": "hybrid",
|
||||
"hello-interval": 1,
|
||||
"dead-interval": 3
|
||||
}, {
|
||||
"name": "lo",
|
||||
"enabled": True
|
||||
}]
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
with infamy.Test() as test:
|
||||
with test.step("Set up topology and attach to target DUTs"):
|
||||
env = infamy.Env()
|
||||
R1 = env.attach("R1", "mgmt")
|
||||
R2 = env.attach("R2", "mgmt")
|
||||
R3 = env.attach("R3", "mgmt")
|
||||
|
||||
with test.step("Configure targets"):
|
||||
_, R1link = env.ltop.xlate("R1", "link")
|
||||
_, R1data = env.ltop.xlate("R1", "data")
|
||||
_, R2link1 = env.ltop.xlate("R2", "link1")
|
||||
_, R2link2 = env.ltop.xlate("R2", "link2")
|
||||
_, R3link = env.ltop.xlate("R3", "link")
|
||||
_, R3data = env.ltop.xlate("R3", "data")
|
||||
|
||||
parallel(config_target1(R1, R1link, R1data),
|
||||
config_target2(R2, R2link1, R2link2),
|
||||
config_target3(R3, R3link, R3data))
|
||||
|
||||
with test.step("Wait for OSPF routes"):
|
||||
print("Waiting for OSPF routes to converge")
|
||||
until(lambda: route.ipv4_route_exist(R1, "10.0.2.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
||||
until(lambda: route.ipv4_route_exist(R1, "10.0.3.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
||||
until(lambda: route.ipv4_route_exist(R2, "10.0.1.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
||||
until(lambda: route.ipv4_route_exist(R2, "10.0.3.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
||||
until(lambda: route.ipv4_route_exist(R3, "10.0.1.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
||||
until(lambda: route.ipv4_route_exist(R3, "10.0.2.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
||||
|
||||
with test.step("Verify interface type is hybrid"):
|
||||
print("Checking OSPF interface type on all routers")
|
||||
assert route.ospf_get_interface_type(R1, "0.0.0.0", R1link) == "hybrid"
|
||||
assert route.ospf_get_interface_type(R2, "0.0.0.0", "br0") == "hybrid"
|
||||
assert route.ospf_get_interface_type(R3, "0.0.0.0", R3link) == "hybrid"
|
||||
|
||||
with test.step("Verify connectivity between all DUTs"):
|
||||
_, hport1 = env.ltop.xlate("PC", "data1")
|
||||
_, hport2 = env.ltop.xlate("PC", "data2")
|
||||
with infamy.IsolatedMacVlan(hport1) as ns1, \
|
||||
infamy.IsolatedMacVlan(hport2) as ns2:
|
||||
ns1.addip("10.0.10.2")
|
||||
ns2.addip("10.0.30.2")
|
||||
ns1.addroute("10.0.3.1/32", "10.0.10.1")
|
||||
ns2.addroute("10.0.1.1/32", "10.0.30.1")
|
||||
parallel(
|
||||
lambda: ns1.must_reach("10.0.3.1"),
|
||||
lambda: ns2.must_reach("10.0.1.1"),
|
||||
)
|
||||
test.succeed()
|
||||
@@ -0,0 +1,39 @@
|
||||
graph "3r-p2mp" {
|
||||
layout="neato";
|
||||
overlap="false";
|
||||
esep="+20";
|
||||
size=10
|
||||
|
||||
node [shape=record, fontname="DejaVu Sans Mono, Book"];
|
||||
edge [color="cornflowerblue", penwidth="2", fontname="DejaVu Serif, Book"];
|
||||
|
||||
PC [
|
||||
label="PC | { <mgmt1> mgmt1 | <data1> data1 | \n\n\n\n | <mgmt2> mgmt2 | <mgmt3> mgmt3 | <data2> data2 }",
|
||||
pos="20,30!",
|
||||
requires="controller",
|
||||
];
|
||||
|
||||
R1 [
|
||||
label="{ <mgmt> mgmt | <data> data | <link> link } | R1 \n 10.0.1.1/32 \n(lo)",
|
||||
pos="160,60!",
|
||||
requires="infix",
|
||||
];
|
||||
R2 [
|
||||
label="{ <link1> link1 | <mgmt> mgmt | <link2> link2 } | R2 \n 10.0.2.1/32 \n(lo) \n(br0: 10.0.123.2/24)",
|
||||
pos="160,30!",
|
||||
requires="infix",
|
||||
];
|
||||
R3 [
|
||||
label="{ <link> link | <mgmt> mgmt | <data> data } | R3 \n 10.0.3.1/32 \n(lo)",
|
||||
pos="160,0!",
|
||||
requires="infix",
|
||||
];
|
||||
|
||||
PC:mgmt1 -- R1:mgmt [requires="mgmt", color="lightgray"]
|
||||
PC:mgmt2 -- R2:mgmt [requires="mgmt", color="lightgray"]
|
||||
PC:mgmt3 -- R3:mgmt [requires="mgmt", color="lightgray"]
|
||||
PC:data1 -- R1:data [taillabel="10.0.10.2/24", headlabel="10.0.10.1/24"]
|
||||
R3:data -- PC:data2 [taillabel="10.0.30.1/24", headlabel="10.0.30.2/24"]
|
||||
R1:link -- R2:link1 [taillabel="10.0.123.1/24"]
|
||||
R3:link -- R2:link2 [taillabel="10.0.123.3/24"]
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
|
||||
<!-- Title: 3r-p2mp Pages: 1 -->
|
||||
<svg width="720pt" height="312pt"
|
||||
viewBox="0.00 0.00 720.00 312.15" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(0.98 0.98) rotate(0) translate(4 314.02)">
|
||||
<title>3r-p2mp</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-314.02 729.56,-314.02 729.56,4 -4,4"/>
|
||||
<!-- PC -->
|
||||
<g id="node1" class="node">
|
||||
<title>PC</title>
|
||||
<polygon fill="none" stroke="black" points="0,-61.51 0,-248.51 91,-248.51 91,-61.51 0,-61.51"/>
|
||||
<text text-anchor="middle" x="16.5" y="-151.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">PC</text>
|
||||
<polyline fill="none" stroke="black" points="33,-61.51 33,-248.51 "/>
|
||||
<text text-anchor="middle" x="62" y="-233.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt1</text>
|
||||
<polyline fill="none" stroke="black" points="33,-225.51 91,-225.51 "/>
|
||||
<text text-anchor="middle" x="62" y="-210.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">data1</text>
|
||||
<polyline fill="none" stroke="black" points="33,-202.51 91,-202.51 "/>
|
||||
<polyline fill="none" stroke="black" points="33,-130.51 91,-130.51 "/>
|
||||
<text text-anchor="middle" x="62" y="-115.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt2</text>
|
||||
<polyline fill="none" stroke="black" points="33,-107.51 91,-107.51 "/>
|
||||
<text text-anchor="middle" x="62" y="-92.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt3</text>
|
||||
<polyline fill="none" stroke="black" points="33,-84.51 91,-84.51 "/>
|
||||
<text text-anchor="middle" x="62" y="-69.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">data2</text>
|
||||
</g>
|
||||
<!-- R1 -->
|
||||
<g id="node2" class="node">
|
||||
<title>R1</title>
|
||||
<polygon fill="none" stroke="black" points="518.56,-240.52 518.56,-309.52 692.56,-309.52 692.56,-240.52 518.56,-240.52"/>
|
||||
<text text-anchor="middle" x="543.56" y="-294.32" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
|
||||
<polyline fill="none" stroke="black" points="518.56,-286.52 568.56,-286.52 "/>
|
||||
<text text-anchor="middle" x="543.56" y="-271.32" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
|
||||
<polyline fill="none" stroke="black" points="518.56,-263.52 568.56,-263.52 "/>
|
||||
<text text-anchor="middle" x="543.56" y="-248.32" font-family="DejaVu Sans Mono, Book" font-size="14.00">link</text>
|
||||
<polyline fill="none" stroke="black" points="568.56,-240.52 568.56,-309.52 "/>
|
||||
<text text-anchor="middle" x="630.56" y="-286.32" font-family="DejaVu Sans Mono, Book" font-size="14.00">R1 </text>
|
||||
<text text-anchor="middle" x="630.56" y="-271.32" font-family="DejaVu Sans Mono, Book" font-size="14.00"> 10.0.1.1/32 </text>
|
||||
<text text-anchor="middle" x="630.56" y="-256.32" font-family="DejaVu Sans Mono, Book" font-size="14.00">(lo)</text>
|
||||
</g>
|
||||
<!-- PC--R1 -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>PC:mgmt1--R1:mgmt</title>
|
||||
<path fill="none" stroke="lightgray" stroke-width="2" d="M91.5,-237.01C91.5,-237.01 518.56,-298.02 518.56,-298.02"/>
|
||||
</g>
|
||||
<!-- PC--R1 -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>PC:data1--R1:data</title>
|
||||
<path fill="none" stroke="cornflowerblue" stroke-width="2" d="M91.5,-214.01C91.5,-214.01 518.56,-275.02 518.56,-275.02"/>
|
||||
<text text-anchor="middle" x="473.06" y="-278.82" font-family="DejaVu Serif, Book" font-size="14.00">10.0.10.1/24</text>
|
||||
<text text-anchor="middle" x="137" y="-217.81" font-family="DejaVu Serif, Book" font-size="14.00">10.0.10.2/24</text>
|
||||
</g>
|
||||
<!-- R2 -->
|
||||
<g id="node3" class="node">
|
||||
<title>R2</title>
|
||||
<polygon fill="none" stroke="black" points="485.56,-120.51 485.56,-189.51 725.56,-189.51 725.56,-120.51 485.56,-120.51"/>
|
||||
<text text-anchor="middle" x="514.56" y="-174.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">link1</text>
|
||||
<polyline fill="none" stroke="black" points="485.56,-166.51 543.56,-166.51 "/>
|
||||
<text text-anchor="middle" x="514.56" y="-151.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
|
||||
<polyline fill="none" stroke="black" points="485.56,-143.51 543.56,-143.51 "/>
|
||||
<text text-anchor="middle" x="514.56" y="-128.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">link2</text>
|
||||
<polyline fill="none" stroke="black" points="543.56,-120.51 543.56,-189.51 "/>
|
||||
<text text-anchor="middle" x="634.56" y="-173.81" font-family="DejaVu Sans Mono, Book" font-size="14.00">R2 </text>
|
||||
<text text-anchor="middle" x="634.56" y="-158.81" font-family="DejaVu Sans Mono, Book" font-size="14.00"> 10.0.2.1/32 </text>
|
||||
<text text-anchor="middle" x="634.56" y="-143.81" font-family="DejaVu Sans Mono, Book" font-size="14.00">(lo) </text>
|
||||
<text text-anchor="middle" x="634.56" y="-128.81" font-family="DejaVu Sans Mono, Book" font-size="14.00">(br0: 10.0.123.2/24)</text>
|
||||
</g>
|
||||
<!-- PC--R2 -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>PC:mgmt2--R2:mgmt</title>
|
||||
<path fill="none" stroke="lightgray" stroke-width="2" d="M91.5,-119.01C91.5,-119.01 485.56,-155.01 485.56,-155.01"/>
|
||||
</g>
|
||||
<!-- R3 -->
|
||||
<g id="node4" class="node">
|
||||
<title>R3</title>
|
||||
<polygon fill="none" stroke="black" points="518.56,-0.5 518.56,-69.5 692.56,-69.5 692.56,-0.5 518.56,-0.5"/>
|
||||
<text text-anchor="middle" x="543.56" y="-54.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">link</text>
|
||||
<polyline fill="none" stroke="black" points="518.56,-46.5 568.56,-46.5 "/>
|
||||
<text text-anchor="middle" x="543.56" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
|
||||
<polyline fill="none" stroke="black" points="518.56,-23.5 568.56,-23.5 "/>
|
||||
<text text-anchor="middle" x="543.56" y="-8.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
|
||||
<polyline fill="none" stroke="black" points="568.56,-0.5 568.56,-69.5 "/>
|
||||
<text text-anchor="middle" x="630.56" y="-46.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">R3 </text>
|
||||
<text text-anchor="middle" x="630.56" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00"> 10.0.3.1/32 </text>
|
||||
<text text-anchor="middle" x="630.56" y="-16.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">(lo)</text>
|
||||
</g>
|
||||
<!-- PC--R3 -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>PC:mgmt3--R3:mgmt</title>
|
||||
<path fill="none" stroke="lightgray" stroke-width="2" d="M91.5,-96.01C91.5,-96.01 518.56,-35 518.56,-35"/>
|
||||
</g>
|
||||
<!-- R1--R2 -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>R1:link--R2:link1</title>
|
||||
<path fill="none" stroke="cornflowerblue" stroke-width="2" d="M543.56,-240.02C543.56,-240.02 514.56,-190.01 514.56,-190.01"/>
|
||||
<text text-anchor="middle" x="493.56" y="-228.82" font-family="DejaVu Serif, Book" font-size="14.00">10.0.123.1/24</text>
|
||||
</g>
|
||||
<!-- R3--PC -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>R3:data--PC:data2</title>
|
||||
<path fill="none" stroke="cornflowerblue" stroke-width="2" d="M518.56,-12C518.56,-12 91.5,-73.01 91.5,-73.01"/>
|
||||
<text text-anchor="middle" x="137" y="-76.81" font-family="DejaVu Serif, Book" font-size="14.00">10.0.30.2/24</text>
|
||||
<text text-anchor="middle" x="473.06" y="-15.8" font-family="DejaVu Serif, Book" font-size="14.00">10.0.30.1/24</text>
|
||||
</g>
|
||||
<!-- R3--R2 -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>R3:link--R2:link2</title>
|
||||
<path fill="none" stroke="cornflowerblue" stroke-width="2" d="M543.56,-70C543.56,-70 514.56,-120.01 514.56,-120.01"/>
|
||||
<text text-anchor="middle" x="493.56" y="-73.8" font-family="DejaVu Serif, Book" font-size="14.00">10.0.123.3/24</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.4 KiB |
Reference in New Issue
Block a user