Add new test: ospf_container

Aims to test a complex setup with multiple containers, OSPF and NAT
This commit is contained in:
Mattias Walström
2024-11-25 14:04:07 +01:00
parent 82fd4bdb68
commit bbc9a55c1e
3 changed files with 732 additions and 0 deletions
+475
View File
@@ -0,0 +1,475 @@
#!/usr/bin/env python3
r"""OSPF container
Good test
"""
import infamy
import infamy.util as util
def config_generic(target, router, ring1, ring2, link):
target.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [
{
"name": "lo",
"type": "infix-if-type:loopback",
"ietf-ip:ipv4": {
"address": [
{
"ip": "127.0.0.1",
"prefix-length": 8
}
]
},
"ietf-ip:ipv6": {
"address": [
{
"ip": "::1",
"prefix-length": 128
}
]
}
},
{
"name": ring1,
"ietf-ip:ipv6": {},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": f"{ring1}.8",
"type": "infix-if-type:vlan",
"infix-interfaces:vlan": {
"tag-type": "ieee802-dot1q-types:c-vlan",
"id": 8,
"lower-layer-if": ring1
},
"ipv4": {
"address": [{
"ip": f"10.0.{router}.1",
"prefix-length": 32
}]
}
},
{
"name": ring2,
"ietf-ip:ipv6": {},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": f"{ring2}.8",
"type": "infix-if-type:vlan",
"infix-interfaces:vlan": {
"tag-type": "ieee802-dot1q-types:c-vlan",
"id": 8,
"lower-layer-if": ring2
},
"ipv4": {
"address": [{
"ip": f"10.0.{router}.1",
"prefix-length": 32
}]
}
},
{
"name": link,
"ietf-ip:ipv4": {
"forwarding": True
},
"ietf-ip:ipv6": {}
},
{
"name": "br0",
"type": "infix-if-type:bridge",
"ietf-ip:ipv4": {
"enabled": True,
"forwarding": True,
"infix-ip:autoconf": {
"enabled": True,
"request-address": "169.254.1.1"
}
},
"ietf-ip:ipv6": {
"enabled": True
},
"infix-interfaces:bridge": {
"ieee-group-forward": [
"lldp"
]
}
},
{
"name": "br1",
"type": "infix-if-type:bridge",
"infix-interfaces:bridge": {
"vlans": {
"vlan": [
{
"vid": 6,
"untagged": [
"veth1b"
]
}
]
}
}
},
{
"name": "veth0a",
"type": "infix-if-type:veth",
"infix-interfaces:container-network": {
"type": "host"
},
"infix-interfaces:veth": {
"peer": "veth0b"
},
"infix-interfaces:custom-phys-address": {
"chassis": {
"offset": "06:00:00:00:00:00"
}
}
},
{
"name": "veth0b",
"type": "infix-if-type:veth",
"infix-interfaces:bridge-port": {
"bridge": "br0"
},
"infix-interfaces:veth": {
"peer": "veth0a"
}
},
{
"name": "veth1a",
"type": "infix-if-type:veth",
"infix-interfaces:container-network": {
"type": "host"
},
"infix-interfaces:veth": {
"peer": "veth1b"
},
"infix-interfaces:custom-phys-address": {
"chassis": {
"offset": "06:00:00:00:00:00"
}
}
},
{
"name": "veth1b",
"type": "infix-if-type:veth",
"infix-interfaces:bridge-port": {
"bridge": "br1",
"pvid": 6
},
"infix-interfaces:veth": {
"peer": "veth1a"
}
},
{
"name": "veth2a",
"type": "infix-if-type:veth",
"infix-interfaces:container-network": {
"type": "host"
},
"infix-interfaces:veth": {
"peer": "veth2b"
},
"infix-interfaces:custom-phys-address": {
"chassis": {
"offset": "06:00:00:00:00:00"
}
}
},
{
"name": "veth2b",
"type": "infix-if-type:veth",
"infix-interfaces:bridge-port": {
"bridge": "br0"
},
"infix-interfaces:veth": {
"peer": "veth2a"
}
},
{
"name": "veth3a",
"type": "infix-if-type:veth",
"infix-interfaces:container-network": {
"type": "host"
},
"infix-interfaces:veth": {
"peer": "veth3b"
},
"infix-interfaces:custom-phys-address": {
"chassis": {
"offset": "06:00:00:00:00:00"
}
}
},
{
"name": "veth3b",
"type": "infix-if-type:veth",
"infix-interfaces:bridge-port": {
"bridge": "br1",
"pvid": 6
},
"infix-interfaces:veth": {
"peer": "veth3a"
}
}
]
}})
target.put_config_dict("infix-containers", {
"containers": {
"container": [
{
"name": "container-A",
"image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}",
"hostname": "web-container-%m",
"privileged": True,
"restart-policy": "retry",
"network": {
"interface": [
{
"name": "veth0a",
"option": [
"interface_name=br0"
]
},
{
"name": "veth1a",
"option": [
"interface_name=br1"
]
}
]
},
"mount": [
{
"name": "infix",
"source": "/proc/1",
"target": "/1"
}
],
"volume": [
{
"name": "persistent",
"target": "/var/persistent"
}
]
},
{
"name": "container-B",
"image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}",
"hostname": "web-container-%m",
"privileged": True,
"restart-policy": "retry",
"network": {
"interface": [
{
"name": "veth2a"
},
{
"name": "veth3a"
}
]
}
}
]
}})
target.put_config_dict("ietf-routing", {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [
{
"type": "infix-routing:ospfv2",
"name": "default",
"ietf-ospf:ospf": {
"areas": {
"area": [
{
"area-id": "0.0.80.79",
"area-type": "nssa-area",
"interfaces": {
"interface": [
{
"name": f"{ring1}.8",
"interface-type": "point-to-point",
"enabled": True
},
{
"name": f"{ring2}.8",
"interface-type": "point-to-point",
"enabled": True
},
{
"name": "lo",
"enabled": True
}
]
}
}
]
}
}
}
]
}
}})
def config_abr(target, data, link1, link2, link3):
target.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [
{
"name": "lo",
"type": "infix-if-type:loopback",
"ietf-ip:ipv4": {
"address": [
{
"ip": "127.0.0.1",
"prefix-length": 8
}
]
},
"ietf-ip:ipv6": {
"address": [
{
"ip": "::1",
"prefix-length": 128
}
]
}
},
{
"name": data,
"ipv4": {
"address": [{
"ip": "192.168.100.1",
"prefix-length": 24
}]
}
},
{
"name": "br0",
"type": "infix-if-type:bridge",
"ipv4": {
"address": [{
"ip": "10.0.0.100",
"prefix-length": 24
}]
}
},
{
"name": link1,
"bridge-port": {
"bridge": "br0"
}
},
{
"name": link2,
"bridge-port": {
"bridge": "br0"
}
},
{
"name": link3,
"bridge-port": {
"bridge": "br0"
}
}
]
}
})
target.put_config_dict("ietf-routing", {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [
{
"type": "infix-routing:ospfv2",
"name": "default",
"ietf-ospf:ospf": {
"areas": {
"area": [
{
"area-id": "0.0.0.0",
"interfaces": {
"interface": [
{
"name": data,
"enabled": True
}
]
}
},
{
"area-id": "0.0.80.79",
"area-type": "nssa-area",
"interfaces": {
"interface":
[
{
"name": "br0",
"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")
ABR = env.attach("ABR", "mgmt")
if not R1.has_model("infix-containers"):
test.skip()
if not R2.has_model("infix-containers"):
test.skip()
if not R3.has_model("infix-containers"):
test.skip()
with test.step("Configure DUTs"):
_, R1ring1 = env.ltop.xlate("R1", "ring1")
_, R1ring2 = env.ltop.xlate("R1", "ring2")
_, R2ring1 = env.ltop.xlate("R2", "ring1")
_, R2ring2 = env.ltop.xlate("R2", "ring2")
_, R3ring1 = env.ltop.xlate("R3", "ring1")
_, R3ring2 = env.ltop.xlate("R3", "ring2")
_, hostR1ring1 = env.ltop.xlate("host", "R1ring1")
_, hostR1ring2 = env.ltop.xlate("host", "R1ring2")
_, hostR2ring1 = env.ltop.xlate("host", "R2ring1")
_, hostR2ring2 = env.ltop.xlate("host", "R2ring2")
_, hostR3ring1 = env.ltop.xlate("host", "R3ring1")
_, hostR3ring2 = env.ltop.xlate("host", "R3ring2")
_, R1link = env.ltop.xlate("R1", "link")
_, R2link = env.ltop.xlate("R2", "link")
_, R3link = env.ltop.xlate("R3", "link")
_, R1data = env.ltop.xlate("R1", "data")
_, R3data = env.ltop.xlate("R3", "data")
_, ABRdata = env.ltop.xlate("ABR", "data")
_, ABRlink1 = env.ltop.xlate("ABR", "link1")
_, ABRlink2 = env.ltop.xlate("ABR", "link2")
_, ABRlink3 = env.ltop.xlate("ABR", "link3")
util.parallel(lambda: config_generic(R1, 1, R1ring1, R1ring2, R1link),
lambda: config_generic(R2, 2, R2ring1, R2ring2, R2link),
lambda: config_generic(R3, 3, R3ring1, R3ring2, R3link),
lambda: config_abr(ABR, ABRdata, ABRlink1, ABRlink2, ABRlink3))
test.succeed()
@@ -0,0 +1,61 @@
graph "ospf_containers" {
layout="neato";
overlap=false;
esep="+20";
splines=true;
size=10;
node [ shape=record, fontname="DejaVu Sans Mono, Book"];
edge [color="black", penwidth="2", fontname="DejaVu Serif, Book"];
host [
label=" { { <R1ring1> R1ring1 | <R1ring2> R1ring2 | <data1> data1 | <mgmt1> mgmt1 | <mgmt2> mgmt2 | <data2> data2 | <R2ring1> R2ring1 | <R2ring2> R2ring2 | <data3> data3 | <mgmt3> mgmt3 | <R3ring1> R3ring1 | <R3ring2> R3ring2 | <mgmt4> mgmt4 | <data4> data4 } | host } ",
pos="0,5!"
kind="controller",
];
R1 [
label="{{ <link> link } | R1 | {<ring1> ring1 | <ring2> ring2 | <data> data | <mgmt> mgmt }}"
pos="-1,6!"
kind="infix",
];
R2 [
label="{{ <link> link } | R2 | { <mgmt> mgmt | <data> data | <ring1> ring1 | <ring2> ring2 }}"
pos="0,6!",
kind="infix",
];
R3 [
label="{ <link> link | R3 | { <data> data | <mgmt> mgmt | <ring1> ring1 | <ring2> ring2 }}"
pos="1,6!"
kind="infix",
];
ABR [
label="{ ABR | {<link1> link1 | <link2> link2 |<link3> link3 | <mgmt> mgmt | <data> data }}"
pos="2,6.5!"
kind="infix",
];
host:mgmt1 -- R1:mgmt [kind=mgmt, color="lightgray"]
host:mgmt2 -- R2:mgmt [kind=mgmt, color="lightgray"]
host:mgmt3 -- R3:mgmt [kind=mgmt, color="lightgray"]
host:mgmt4 -- ABR:mgmt [kind=mgmt, color="lightgray"]
# host-Dut links
host:data1 -- R1:data
host:data2 -- R2:data
host:data3 -- R3:data
host:data4 -- ABR:data
host:R1ring1 -- R1:ring1
host:R2ring1 -- R2:ring1
host:R3ring1 -- R3:ring1
host:R1ring2 -- R1:ring2
host:R2ring2 -- R2:ring2
host:R3ring2 -- R3:ring2
R1:link -- ABR:link1
R2:link -- ABR:link2
R3:link -- ABR:link3
}
@@ -0,0 +1,196 @@
<?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">
<!-- Generated by graphviz version 2.43.0 (0)
-->
<!-- Title: ospf_containers Pages: 1 -->
<svg width="720pt" height="291pt"
viewBox="0.00 0.00 720.00 291.37" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(0.64 0.64) rotate(0) translate(4 453.72)">
<title>ospf_containers</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-453.72 1127.05,-453.72 1127.05,4 -4,4"/>
<!-- host -->
<g id="node1" class="node">
<title>host</title>
<polygon fill="none" stroke="black" points="0,-0.5 0,-46.5 908,-46.5 908,-0.5 0,-0.5"/>
<text text-anchor="middle" x="37" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">R1ring1</text>
<polyline fill="none" stroke="black" points="74,-23.5 74,-46.5 "/>
<text text-anchor="middle" x="111" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">R1ring2</text>
<polyline fill="none" stroke="black" points="148,-23.5 148,-46.5 "/>
<text text-anchor="middle" x="177" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">data1</text>
<polyline fill="none" stroke="black" points="206,-23.5 206,-46.5 "/>
<text text-anchor="middle" x="235" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt1</text>
<polyline fill="none" stroke="black" points="264,-23.5 264,-46.5 "/>
<text text-anchor="middle" x="293" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt2</text>
<polyline fill="none" stroke="black" points="322,-23.5 322,-46.5 "/>
<text text-anchor="middle" x="351" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">data2</text>
<polyline fill="none" stroke="black" points="380,-23.5 380,-46.5 "/>
<text text-anchor="middle" x="417" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">R2ring1</text>
<polyline fill="none" stroke="black" points="454,-23.5 454,-46.5 "/>
<text text-anchor="middle" x="491" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">R2ring2</text>
<polyline fill="none" stroke="black" points="528,-23.5 528,-46.5 "/>
<text text-anchor="middle" x="557" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">data3</text>
<polyline fill="none" stroke="black" points="586,-23.5 586,-46.5 "/>
<text text-anchor="middle" x="615" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt3</text>
<polyline fill="none" stroke="black" points="644,-23.5 644,-46.5 "/>
<text text-anchor="middle" x="681" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">R3ring1</text>
<polyline fill="none" stroke="black" points="718,-23.5 718,-46.5 "/>
<text text-anchor="middle" x="755" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">R3ring2</text>
<polyline fill="none" stroke="black" points="792,-23.5 792,-46.5 "/>
<text text-anchor="middle" x="821" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt4</text>
<polyline fill="none" stroke="black" points="850,-23.5 850,-46.5 "/>
<text text-anchor="middle" x="879" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">data4</text>
<polyline fill="none" stroke="black" points="0,-23.5 908,-23.5 "/>
<text text-anchor="middle" x="454" y="-8.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">host</text>
</g>
<!-- R1 -->
<g id="node2" class="node">
<title>R1</title>
<polygon fill="none" stroke="black" points="79.97,-255.03 79.97,-324.03 295.97,-324.03 295.97,-255.03 79.97,-255.03"/>
<text text-anchor="middle" x="187.97" y="-308.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">link</text>
<polyline fill="none" stroke="black" points="79.97,-301.03 295.97,-301.03 "/>
<text text-anchor="middle" x="187.97" y="-285.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">R1</text>
<polyline fill="none" stroke="black" points="79.97,-278.03 295.97,-278.03 "/>
<text text-anchor="middle" x="108.97" y="-262.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">ring1</text>
<polyline fill="none" stroke="black" points="137.97,-255.03 137.97,-278.03 "/>
<text text-anchor="middle" x="166.97" y="-262.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">ring2</text>
<polyline fill="none" stroke="black" points="195.97,-255.03 195.97,-278.03 "/>
<text text-anchor="middle" x="220.97" y="-262.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
<polyline fill="none" stroke="black" points="245.97,-255.03 245.97,-278.03 "/>
<text text-anchor="middle" x="270.97" y="-262.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
</g>
<!-- host&#45;&#45;R1 -->
<g id="edge1" class="edge">
<title>host:mgmt1&#45;&#45;R1:mgmt</title>
<path fill="none" stroke="lightgray" stroke-width="2" d="M235,-46.5C235,-46.5 323.15,-144.12 315.97,-235.03 314.67,-251.57 296.04,-266.6 296.04,-266.6"/>
</g>
<!-- host&#45;&#45;R1 -->
<g id="edge5" class="edge">
<title>host:data1&#45;&#45;R1:data</title>
<path fill="none" stroke="black" stroke-width="2" d="M177,-46.5C177,-46.5 220.97,-254.53 220.97,-254.53"/>
</g>
<!-- host&#45;&#45;R1 -->
<g id="edge9" class="edge">
<title>host:R1ring1&#45;&#45;R1:ring1</title>
<path fill="none" stroke="black" stroke-width="2" d="M37,-46.5C37,-46.5 108.97,-254.53 108.97,-254.53"/>
</g>
<!-- host&#45;&#45;R1 -->
<g id="edge12" class="edge">
<title>host:R1ring2&#45;&#45;R1:ring2</title>
<path fill="none" stroke="black" stroke-width="2" d="M111,-46.5C111,-46.5 166.97,-254.53 166.97,-254.53"/>
</g>
<!-- R2 -->
<g id="node3" class="node">
<title>R2</title>
<polygon fill="none" stroke="black" points="346,-255.03 346,-324.03 562,-324.03 562,-255.03 346,-255.03"/>
<text text-anchor="middle" x="454" y="-308.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">link</text>
<polyline fill="none" stroke="black" points="346,-301.03 562,-301.03 "/>
<text text-anchor="middle" x="454" y="-285.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">R2</text>
<polyline fill="none" stroke="black" points="346,-278.03 562,-278.03 "/>
<text text-anchor="middle" x="371" y="-262.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
<polyline fill="none" stroke="black" points="396,-255.03 396,-278.03 "/>
<text text-anchor="middle" x="421" y="-262.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
<polyline fill="none" stroke="black" points="446,-255.03 446,-278.03 "/>
<text text-anchor="middle" x="475" y="-262.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">ring1</text>
<polyline fill="none" stroke="black" points="504,-255.03 504,-278.03 "/>
<text text-anchor="middle" x="533" y="-262.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">ring2</text>
</g>
<!-- host&#45;&#45;R2 -->
<g id="edge2" class="edge">
<title>host:mgmt2&#45;&#45;R2:mgmt</title>
<path fill="none" stroke="lightgray" stroke-width="2" d="M293,-46.5C293,-46.5 371,-254.53 371,-254.53"/>
</g>
<!-- host&#45;&#45;R2 -->
<g id="edge6" class="edge">
<title>host:data2&#45;&#45;R2:data</title>
<path fill="none" stroke="black" stroke-width="2" d="M351,-46.5C351,-46.5 421,-254.53 421,-254.53"/>
</g>
<!-- host&#45;&#45;R2 -->
<g id="edge10" class="edge">
<title>host:R2ring1&#45;&#45;R2:ring1</title>
<path fill="none" stroke="black" stroke-width="2" d="M417,-46.5C417,-46.5 475,-254.53 475,-254.53"/>
</g>
<!-- host&#45;&#45;R2 -->
<g id="edge13" class="edge">
<title>host:R2ring2&#45;&#45;R2:ring2</title>
<path fill="none" stroke="black" stroke-width="2" d="M491,-46.5C491,-46.5 533,-254.53 533,-254.53"/>
</g>
<!-- R3 -->
<g id="node4" class="node">
<title>R3</title>
<polygon fill="none" stroke="black" points="612.03,-255.03 612.03,-324.03 828.03,-324.03 828.03,-255.03 612.03,-255.03"/>
<text text-anchor="middle" x="720.03" y="-308.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">link</text>
<polyline fill="none" stroke="black" points="612.03,-301.03 828.03,-301.03 "/>
<text text-anchor="middle" x="720.03" y="-285.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">R3</text>
<polyline fill="none" stroke="black" points="612.03,-278.03 828.03,-278.03 "/>
<text text-anchor="middle" x="637.03" y="-262.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
<polyline fill="none" stroke="black" points="662.03,-255.03 662.03,-278.03 "/>
<text text-anchor="middle" x="687.03" y="-262.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
<polyline fill="none" stroke="black" points="712.03,-255.03 712.03,-278.03 "/>
<text text-anchor="middle" x="741.03" y="-262.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">ring1</text>
<polyline fill="none" stroke="black" points="770.03,-255.03 770.03,-278.03 "/>
<text text-anchor="middle" x="799.03" y="-262.83" font-family="DejaVu Sans Mono, Book" font-size="14.00">ring2</text>
</g>
<!-- host&#45;&#45;R3 -->
<g id="edge3" class="edge">
<title>host:mgmt3&#45;&#45;R3:mgmt</title>
<path fill="none" stroke="lightgray" stroke-width="2" d="M615,-46.5C615,-46.5 687.03,-254.53 687.03,-254.53"/>
</g>
<!-- host&#45;&#45;R3 -->
<g id="edge7" class="edge">
<title>host:data3&#45;&#45;R3:data</title>
<path fill="none" stroke="black" stroke-width="2" d="M557,-46.5C557,-46.5 560.94,-155.68 592.03,-235.03 598.08,-250.48 611.96,-266.6 611.96,-266.6"/>
</g>
<!-- host&#45;&#45;R3 -->
<g id="edge11" class="edge">
<title>host:R3ring1&#45;&#45;R3:ring1</title>
<path fill="none" stroke="black" stroke-width="2" d="M681,-46.5C681,-46.5 741.03,-254.53 741.03,-254.53"/>
</g>
<!-- host&#45;&#45;R3 -->
<g id="edge14" class="edge">
<title>host:R3ring2&#45;&#45;R3:ring2</title>
<path fill="none" stroke="black" stroke-width="2" d="M755,-46.5C755,-46.5 799.03,-254.53 799.03,-254.53"/>
</g>
<!-- ABR -->
<g id="node5" class="node">
<title>ABR</title>
<polygon fill="none" stroke="black" points="849.05,-399.54 849.05,-445.54 1123.05,-445.54 1123.05,-399.54 849.05,-399.54"/>
<text text-anchor="middle" x="986.05" y="-430.34" font-family="DejaVu Sans Mono, Book" font-size="14.00">ABR</text>
<polyline fill="none" stroke="black" points="849.05,-422.54 1123.05,-422.54 "/>
<text text-anchor="middle" x="878.05" y="-407.34" font-family="DejaVu Sans Mono, Book" font-size="14.00">link1</text>
<polyline fill="none" stroke="black" points="907.05,-399.54 907.05,-422.54 "/>
<text text-anchor="middle" x="936.05" y="-407.34" font-family="DejaVu Sans Mono, Book" font-size="14.00">link2</text>
<polyline fill="none" stroke="black" points="965.05,-399.54 965.05,-422.54 "/>
<text text-anchor="middle" x="994.05" y="-407.34" font-family="DejaVu Sans Mono, Book" font-size="14.00">link3</text>
<polyline fill="none" stroke="black" points="1023.05,-399.54 1023.05,-422.54 "/>
<text text-anchor="middle" x="1048.05" y="-407.34" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
<polyline fill="none" stroke="black" points="1073.05,-399.54 1073.05,-422.54 "/>
<text text-anchor="middle" x="1098.05" y="-407.34" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
</g>
<!-- host&#45;&#45;ABR -->
<g id="edge4" class="edge">
<title>host:mgmt4&#45;&#45;ABR:mgmt</title>
<path fill="none" stroke="lightgray" stroke-width="2" d="M821,-46.5C821,-46.5 1048.05,-399.54 1048.05,-399.54"/>
</g>
<!-- host&#45;&#45;ABR -->
<g id="edge8" class="edge">
<title>host:data4&#45;&#45;ABR:data</title>
<path fill="none" stroke="black" stroke-width="2" d="M879,-46.5C879,-46.5 1098.05,-399.54 1098.05,-399.54"/>
</g>
<!-- R1&#45;&#45;ABR -->
<g id="edge15" class="edge">
<title>R1:link&#45;&#45;ABR:link1</title>
<path fill="none" stroke="black" stroke-width="2" d="M295.97,-312.53C295.97,-312.53 317.37,-339.66 326,-344.03 535.15,-449.72 849.05,-410.54 849.05,-410.54"/>
</g>
<!-- R2&#45;&#45;ABR -->
<g id="edge16" class="edge">
<title>R2:link&#45;&#45;ABR:link2</title>
<path fill="none" stroke="black" stroke-width="2" d="M562,-312.53C562,-312.53 583.44,-339.57 592.03,-344.03 686.56,-393.12 724.01,-361.89 829.05,-379.54 876.8,-387.56 936.15,-399.5 936.15,-399.5"/>
</g>
<!-- R3&#45;&#45;ABR -->
<g id="edge17" class="edge">
<title>R3:link&#45;&#45;ABR:link3</title>
<path fill="none" stroke="black" stroke-width="2" d="M828.03,-312.53C828.03,-312.53 994.05,-399.54 994.05,-399.54"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB