|
1 | | -{ ... }: |
| 1 | +{ lib, pkgs, ... }: |
2 | 2 | { |
3 | 3 | name = "bgp-simple"; |
4 | 4 |
|
|
12 | 12 | ipv4.addresses = [ |
13 | 13 | { |
14 | 14 | address = "192.0.2.1"; |
15 | | - prefixLength = 30; |
| 15 | + prefixLength = 29; |
16 | 16 | } |
17 | 17 | ]; |
18 | 18 | ipv6.addresses = [ |
|
25 | 25 | services.frr = { |
26 | 26 | bgpd.enable = true; |
27 | 27 | config = '' |
| 28 | + ip route 198.51.100.0/25 reject |
| 29 | + ipv6 route 2001:db8:beef::/48 reject |
28 | 30 | router bgp 64496 |
29 | 31 | no bgp ebgp-requires-policy |
30 | 32 | no bgp default ipv4-unicast |
|
33 | 35 | neighbor 192.0.2.2 remote-as 64497 |
34 | 36 | neighbor 2001:db8::2 remote-as 64497 |
35 | 37 |
|
| 38 | + neighbor 192.0.2.3 remote-as 64498 |
| 39 | + neighbor 2001:db8::3 remote-as 64498 |
| 40 | +
|
36 | 41 | address-family ipv4 unicast |
| 42 | + network 198.51.100.0/25 |
37 | 43 | neighbor 192.0.2.2 activate |
| 44 | + neighbor 192.0.2.3 activate |
38 | 45 | exit-address-family |
39 | 46 |
|
40 | 47 | address-family ipv6 unicast |
| 48 | + network 2001:db8:beef::/48 |
41 | 49 | neighbor 2001:db8::2 activate |
| 50 | + neighbor 2001:db8::3 activate |
42 | 51 | exit-address-family |
43 | 52 | ''; |
44 | 53 | }; |
|
48 | 57 | ipv4.addresses = [ |
49 | 58 | { |
50 | 59 | address = "192.0.2.2"; |
51 | | - prefixLength = 30; |
| 60 | + prefixLength = 29; |
52 | 61 | } |
53 | 62 | ]; |
54 | 63 | ipv6.addresses = [ |
|
91 | 100 | # families and to disable/enable various groups of static routes on the fly). |
92 | 101 | protocol static static4 { |
93 | 102 | ipv4; |
| 103 | +
|
| 104 | + route 198.51.100.128/25 unreachable; |
94 | 105 | } |
95 | 106 | protocol static static6 { |
96 | 107 | ipv6; |
| 108 | +
|
| 109 | + route 2001:db8:c0de::/48 unreachable; |
97 | 110 | } |
98 | 111 |
|
99 | 112 | protocol bgp a_v4 { |
|
106 | 119 | }; |
107 | 120 | } |
108 | 121 |
|
| 122 | + protocol bgp c_v4 { |
| 123 | + local as 64497; |
| 124 | + neighbor 192.0.2.3 as 64498; |
| 125 | +
|
| 126 | + ipv4 { |
| 127 | + import all; |
| 128 | + export all; |
| 129 | + }; |
| 130 | + } |
| 131 | +
|
109 | 132 | protocol bgp a_v6 { |
110 | 133 | local as 64497; |
111 | 134 | neighbor 2001:db8::1 as 64496; |
|
115 | 138 | export all; |
116 | 139 | }; |
117 | 140 | } |
| 141 | +
|
| 142 | + protocol bgp c_v6 { |
| 143 | + local as 64497; |
| 144 | + neighbor 2001:db8::3 as 64498; |
| 145 | +
|
| 146 | + ipv6 { |
| 147 | + import all; |
| 148 | + export all; |
| 149 | + }; |
| 150 | + } |
118 | 151 | ''; |
119 | 152 | }; |
120 | 153 | }; |
| 154 | + c = { |
| 155 | + environment.systemPackages = with pkgs; [ gobgp ]; |
| 156 | + networking.interfaces = { |
| 157 | + eth1 = { |
| 158 | + ipv4.addresses = [ |
| 159 | + { |
| 160 | + address = "192.0.2.3"; |
| 161 | + prefixLength = 29; |
| 162 | + } |
| 163 | + ]; |
| 164 | + ipv6.addresses = [ |
| 165 | + { |
| 166 | + address = "2001:db8::3"; |
| 167 | + prefixLength = 64; |
| 168 | + } |
| 169 | + ]; |
| 170 | + }; |
| 171 | + lo = { |
| 172 | + ipv4.routes = [ |
| 173 | + { |
| 174 | + address = "203.0.113.0"; |
| 175 | + prefixLength = 24; |
| 176 | + } |
| 177 | + ]; |
| 178 | + ipv6.routes = [ |
| 179 | + { |
| 180 | + address = "2001:db8:dead::"; |
| 181 | + prefixLength = 48; |
| 182 | + } |
| 183 | + ]; |
| 184 | + }; |
| 185 | + }; |
| 186 | + users = { |
| 187 | + groups.gobgpd = { }; |
| 188 | + users.gobgpd = { |
| 189 | + description = "GoBGP Daemon User"; |
| 190 | + isSystemUser = true; |
| 191 | + group = "gobgpd"; |
| 192 | + }; |
| 193 | + }; |
| 194 | + systemd = { |
| 195 | + services = { |
| 196 | + frr.postStart = "${pkgs.acl}/bin/setfacl -m u:gobgpd:rwx /run/frr/zserv.api"; |
| 197 | + gobgpd = { |
| 198 | + after = [ "frr.service" ]; |
| 199 | + serviceConfig = { |
| 200 | + DynamicUser = lib.mkForce false; |
| 201 | + User = "gobgpd"; |
| 202 | + Group = "gobgpd"; |
| 203 | + }; |
| 204 | + }; |
| 205 | + }; |
| 206 | + }; |
| 207 | + services = { |
| 208 | + # any frr service will do, we just need the zebra socket |
| 209 | + # a upstream module modification to frr would be better |
| 210 | + frr.sharpd.enable = true; |
| 211 | + gobgpd = { |
| 212 | + enable = true; |
| 213 | + settings = { |
| 214 | + global.config = { |
| 215 | + as = 64498; |
| 216 | + router-id = "192.0.2.3"; |
| 217 | + }; |
| 218 | + global.apply-policy.config = { |
| 219 | + default-import-policy = "accept-route"; |
| 220 | + default-export-policy = "accept-route"; |
| 221 | + }; |
| 222 | + zebra.config = { |
| 223 | + enabled = true; |
| 224 | + software-name = "frr${lib.versions.majorMinor pkgs.frr.version}"; |
| 225 | + version = 6; |
| 226 | + url = "unix:/run/frr/zserv.api"; |
| 227 | + redistribute-route-type-list = [ |
| 228 | + "kernel" |
| 229 | + "directly-connected" |
| 230 | + "static" |
| 231 | + ]; |
| 232 | + }; |
| 233 | + neighbors = [ |
| 234 | + { |
| 235 | + config = { |
| 236 | + neighbor-address = "192.0.2.1"; |
| 237 | + peer-as = 64496; |
| 238 | + }; |
| 239 | + afi-safis = [ |
| 240 | + { |
| 241 | + config.afi-safi-name = "ipv4-unicast"; |
| 242 | + } |
| 243 | + ]; |
| 244 | + } |
| 245 | + { |
| 246 | + config = { |
| 247 | + neighbor-address = "192.0.2.2"; |
| 248 | + peer-as = 64497; |
| 249 | + }; |
| 250 | + afi-safis = [ |
| 251 | + { |
| 252 | + config.afi-safi-name = "ipv4-unicast"; |
| 253 | + } |
| 254 | + ]; |
| 255 | + } |
| 256 | + { |
| 257 | + config = { |
| 258 | + neighbor-address = "2001:db8::1"; |
| 259 | + peer-as = 64496; |
| 260 | + }; |
| 261 | + afi-safis = [ |
| 262 | + { |
| 263 | + config.afi-safi-name = "ipv6-unicast"; |
| 264 | + } |
| 265 | + ]; |
| 266 | + } |
| 267 | + { |
| 268 | + config = { |
| 269 | + neighbor-address = "2001:db8::2"; |
| 270 | + peer-as = 64497; |
| 271 | + }; |
| 272 | + afi-safis = [ |
| 273 | + { |
| 274 | + config.afi-safi-name = "ipv6-unicast"; |
| 275 | + } |
| 276 | + ]; |
| 277 | + } |
| 278 | + ]; |
| 279 | + }; |
| 280 | + }; |
| 281 | + }; |
| 282 | + }; |
121 | 283 | }; |
122 | 284 |
|
123 | 285 | testScript = '' |
124 | 286 | start_all() |
125 | 287 |
|
126 | 288 | a.wait_for_unit("network.target") |
127 | 289 | b.wait_for_unit("network.target") |
| 290 | + c.wait_for_unit("network.target") |
128 | 291 |
|
129 | 292 | a.wait_for_unit("frr.service") |
130 | 293 | b.wait_for_unit("bird.service") |
| 294 | + c.wait_for_unit("gobgpd.service") |
| 295 | +
|
| 296 | + with subtest("ensure bgp sessions are established"): |
| 297 | + a.wait_until_succeeds("vtysh -c 'show bgp ipv4 summary' | grep '192.0.2.2.*1\\s*2\\s*N/A'") |
| 298 | + a.wait_until_succeeds("vtysh -c 'show bgp ipv4 summary' | grep '192.0.2.3.*1\\s*2\\s*N/A'") |
| 299 | + b.wait_until_succeeds("birdc show protocols | grep 'a_v4.*Established'") |
| 300 | + b.wait_until_succeeds("birdc show protocols | grep 'c_v4.*Established'") |
| 301 | + c.wait_until_succeeds("gobgp neighbor -a 'ipv4' | grep '192.0.2.1.*Establ.*|.*2.*2'") |
| 302 | + c.wait_until_succeeds("gobgp neighbor -a 'ipv4' | grep '192.0.2.2.*Establ.*|.*2.*2'") |
131 | 303 |
|
132 | | - a.wait_until_succeeds("vtysh -c 'show bgp ipv4 summary' | grep '192.0.2.2.*0\\s*0\\s*N/A'") |
133 | | - b.wait_until_succeeds("birdc show protocols | grep 'a_v4.*Established'") |
| 304 | + # IPv6 DAD might need some time to complete for the local link address, which is required by frr |
| 305 | + a.wait_until_succeeds("vtysh -c 'show bgp ipv6 summary' | grep '2001:db8::2.*1\\s*2\\s*N/A'") |
| 306 | + a.wait_until_succeeds("vtysh -c 'show bgp ipv6 summary' | grep '2001:db8::3.*1\\s*2\\s*N/A'") |
| 307 | + b.wait_until_succeeds("birdc show protocols | grep 'a_v6.*Established'") |
| 308 | + b.wait_until_succeeds("birdc show protocols | grep 'c_v4.*Established'") |
| 309 | + c.wait_until_succeeds("gobgp neighbor -a 'ipv6' | grep '2001:db8::1.*Establ.*|.*2.*2'") |
| 310 | + c.wait_until_succeeds("gobgp neighbor -a 'ipv6' | grep '2001:db8::2.*Establ.*|.*2.*2'") |
134 | 311 |
|
135 | | - # IPv6 DAD might need some time to complete for the local link address, which is required by frr |
136 | | - a.wait_until_succeeds("vtysh -c 'show bgp ipv6 summary' | grep '2001:db8::2.*0\\s*0\\s*N/A'") |
137 | | - b.wait_until_succeeds("birdc show protocols | grep 'a_v6.*Established'") |
| 312 | + with subtest("ensure routes have been installed in fib"): |
| 313 | + b.succeed("ip route show | grep 198.51.100.0/25") |
| 314 | + c.succeed("ip route show | grep 198.51.100.0/25") |
| 315 | + a.succeed("ip route show | grep 198.51.100.128/25") |
| 316 | + c.succeed("ip route show | grep 198.51.100.128/25") |
| 317 | + a.succeed("ip route show | grep 203.0.113.0/24") |
| 318 | + b.succeed("ip route show | grep 203.0.113.0/24") |
| 319 | + b.succeed("ip -6 route show | grep 2001:db8:beef::/48") |
| 320 | + c.succeed("ip -6 route show | grep 2001:db8:beef::/48") |
| 321 | + a.succeed("ip -6 route show | grep 2001:db8:c0de::/48") |
| 322 | + c.succeed("ip -6 route show | grep 2001:db8:c0de::/48") |
| 323 | + a.succeed("ip -6 route show | grep 2001:db8:dead::/48") |
| 324 | + b.succeed("ip -6 route show | grep 2001:db8:dead::/48") |
138 | 325 | ''; |
139 | 326 | } |
0 commit comments