Skip to content

Commit 08bec18

Browse files
committed
tests/bgp-vrf: init
1 parent 5c9f088 commit 08bec18

File tree

3 files changed

+308
-1
lines changed

3 files changed

+308
-1
lines changed

flake.lock

Lines changed: 70 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
inputs = {
33
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
44
bird.url = "github:NuschtOS/bird.nix";
5+
ifstate.url = "git+https://codeberg.org/liske/ifstate";
56
};
67
outputs =
78
{ ... }@inputs:

tests/bgp-vrf/default.nix

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
{
2+
lib,
3+
pkgs,
4+
inputs,
5+
...
6+
}:
7+
{
8+
name = "bgp-vrf";
9+
10+
defaults = {
11+
networking = {
12+
useDHCP = false;
13+
firewall.allowedTCPPorts = [ 179 ];
14+
};
15+
};
16+
17+
nodes = {
18+
a = {
19+
imports = [ "${inputs.ifstate}/module.nix" ];
20+
environment.systemPackages = [ inputs.ifstate.packages.${pkgs.system}.default ];
21+
networking = {
22+
iproute2 = {
23+
enable = true;
24+
rttablesExtraConfig = ''
25+
10 vrf0
26+
'';
27+
};
28+
ifstate = {
29+
enable = true;
30+
package = inputs.ifstate.packages.${pkgs.system}.default;
31+
settings = {
32+
parameters.ignore.ifname = [
33+
"eth0"
34+
];
35+
interfaces = {
36+
vrf0 = {
37+
link = {
38+
state = "up";
39+
kind = "vrf";
40+
vrf_table = 10;
41+
};
42+
};
43+
eth1 = {
44+
addresses = [
45+
"192.0.2.1/30"
46+
"2001:db8::1/64"
47+
];
48+
link = {
49+
state = "up";
50+
kind = "physical";
51+
master = "vrf0";
52+
};
53+
};
54+
};
55+
sysctl.all = {
56+
ipv4.forwarding = 1;
57+
ipv6.forwarding = 1;
58+
};
59+
};
60+
};
61+
};
62+
63+
services.frr = {
64+
bgpd.enable = true;
65+
config = ''
66+
vrf vrf0
67+
ip route 198.51.100.0/24 unreachable
68+
ipv6 route 2001:db8:beef::/48 unreachable
69+
exit-vrf
70+
71+
router bgp 65001 vrf vrf0
72+
no bgp ebgp-requires-policy
73+
no bgp default ipv4-unicast
74+
no bgp network import-check
75+
bgp router-id 192.0.2.1
76+
77+
neighbor 192.0.2.2 remote-as 65002
78+
neighbor 2001:db8::2 remote-as 65002
79+
80+
address-family ipv4 unicast
81+
network 198.51.100.0/24
82+
neighbor 192.0.2.2 activate
83+
exit-address-family
84+
85+
address-family ipv6 unicast
86+
network 2001:db8:beef::/48
87+
neighbor 2001:db8::2 activate
88+
exit-address-family
89+
'';
90+
};
91+
};
92+
b = {
93+
systemd.network = {
94+
enable = true;
95+
config = {
96+
addRouteTablesToIPRoute2 = true;
97+
routeTables = {
98+
example = 10;
99+
};
100+
};
101+
networks = {
102+
"10-eth1" = {
103+
matchConfig.Name = "eth1";
104+
address = [
105+
"192.0.2.2/30"
106+
"2001:db8::2/64"
107+
];
108+
networkConfig.VRF = "vrf0";
109+
};
110+
"99-vrf0" = {
111+
matchConfig.Name = "vrf0";
112+
linkConfig = {
113+
ActivationPolicy = "up";
114+
RequiredForOnline = "no";
115+
};
116+
networkConfig = {
117+
IPv4Forwarding = true;
118+
IPv6Forwarding = true;
119+
};
120+
};
121+
};
122+
netdevs."vrf0" = {
123+
enable = true;
124+
netdevConfig = {
125+
Kind = "vrf";
126+
Name = "vrf0";
127+
};
128+
vrfConfig.Table = 10;
129+
};
130+
};
131+
services.bird = {
132+
enable = true;
133+
package = pkgs.bird2;
134+
config = ''
135+
log syslog all;
136+
router id 192.0.2.2;
137+
138+
ipv4 table vrf0_v4;
139+
ipv6 table vrf0_v6;
140+
141+
protocol device {
142+
scan time 10;
143+
}
144+
145+
protocol kernel kernel4 {
146+
vrf "vrf0";
147+
kernel table 10;
148+
149+
ipv4 {
150+
export all;
151+
};
152+
}
153+
154+
protocol kernel kernel6 {
155+
vrf "vrf0";
156+
kernel table 10;
157+
158+
ipv6 {
159+
export all;
160+
};
161+
}
162+
163+
protocol static static4 {
164+
vrf "vrf0";
165+
ipv4;
166+
167+
route 203.0.113.0/24 unreachable;
168+
}
169+
170+
protocol static static6 {
171+
vrf "vrf0";
172+
ipv6;
173+
174+
route 2001:db8:c0de::/48 unreachable;
175+
}
176+
177+
protocol bgp a4 {
178+
local as 65002;
179+
neighbor 192.0.2.1 as 65001;
180+
181+
vrf "vrf0";
182+
183+
ipv4 {
184+
import all;
185+
export all;
186+
};
187+
}
188+
189+
protocol bgp a6 {
190+
local as 65002;
191+
neighbor 2001:db8::1 as 65001;
192+
193+
vrf "vrf0";
194+
195+
ipv6 {
196+
import all;
197+
export all;
198+
};
199+
}
200+
'';
201+
};
202+
};
203+
};
204+
205+
testScript = ''
206+
start_all()
207+
208+
for m in [a, b]:
209+
m.wait_for_unit("network.target")
210+
211+
a.wait_for_unit("frr.service")
212+
b.wait_for_unit("bird.service")
213+
214+
with subtest("ensure vrfs have been created"):
215+
for m in [a, b]:
216+
m.succeed("ip -j vrf | ${lib.getExe pkgs.jq} -r '.[] | .name' | grep vrf0")
217+
m.succeed("ip -j vrf | ${lib.getExe pkgs.jq} -r '.[] | .table' | grep 10")
218+
219+
with subtest("ensure vrf interfaces can reach each other"):
220+
a.succeed("ip vrf exec vrf0 ping -c 1 192.0.2.2")
221+
b.succeed("ip vrf exec vrf0 ping -c 1 192.0.2.1")
222+
223+
with subtest("ensure bgp sessions are established"):
224+
a.wait_until_succeeds("vtysh -c 'show bgp vrf vrf0 ipv4 summary' | grep '192.0.2.2.*1\\s*2\\s*N/A'")
225+
b.wait_until_succeeds("birdc show protocols | grep 'a4.*Established'")
226+
227+
# IPv6 DAD might need some time to complete for the local link address, which is required by frr
228+
a.wait_until_succeeds("vtysh -c 'show bgp vrf vrf0 ipv6 summary' | grep '2001:db8::2.*1\\s*2\\s*N/A'")
229+
b.wait_until_succeeds("birdc show protocols | grep 'a6.*Established'")
230+
231+
with subtest("ensure routes have been installed in vrf"):
232+
a.succeed("ip route show vrf vrf0 | grep 203.0.113.0/24")
233+
b.succeed("ip route show vrf vrf0 | grep 198.51.100.0/24")
234+
a.succeed("ip -6 route show vrf vrf0 | grep 2001:db8:c0de::/48")
235+
b.succeed("ip -6 route show vrf vrf0 | grep 2001:db8:beef::/48")
236+
'';
237+
}

0 commit comments

Comments
 (0)