Skip to content

Commit 8f9c89e

Browse files
committed
tests/bgp-vrf: init
1 parent 5c9f088 commit 8f9c89e

File tree

3 files changed

+303
-1
lines changed

3 files changed

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

0 commit comments

Comments
 (0)