|
1 | | -{ pkgs, ... }: |
| 1 | +{ lib, pkgs, ... }: |
2 | 2 | { |
3 | 3 | name = "bgp-simple"; |
4 | 4 |
|
|
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 |
|
37 | 39 | neighbor 2001:db8::3 remote-as 64498 |
38 | 40 |
|
39 | 41 | address-family ipv4 unicast |
| 42 | + network 198.51.100.0/25 |
40 | 43 | neighbor 192.0.2.2 activate |
41 | 44 | neighbor 192.0.2.3 activate |
42 | 45 | exit-address-family |
43 | 46 |
|
44 | 47 | address-family ipv6 unicast |
| 48 | + network 2001:db8:beef::/48 |
45 | 49 | neighbor 2001:db8::2 activate |
46 | 50 | neighbor 2001:db8::3 activate |
47 | 51 | exit-address-family |
|
96 | 100 | # families and to disable/enable various groups of static routes on the fly). |
97 | 101 | protocol static static4 { |
98 | 102 | ipv4; |
| 103 | +
|
| 104 | + route 198.51.100.128/25 unreachable; |
99 | 105 | } |
100 | 106 | protocol static static6 { |
101 | 107 | ipv6; |
| 108 | +
|
| 109 | + route 2001:db8:c0de::/48 unreachable; |
102 | 110 | } |
103 | 111 |
|
104 | 112 | protocol bgp a_v4 { |
|
145 | 153 | }; |
146 | 154 | c = { |
147 | 155 | environment.systemPackages = with pkgs; [ gobgp ]; |
148 | | - networking.interfaces.eth1 = { |
149 | | - ipv4.addresses = [ |
150 | | - { |
151 | | - address = "192.0.2.3"; |
152 | | - prefixLength = 29; |
153 | | - } |
154 | | - ]; |
155 | | - ipv6.addresses = [ |
156 | | - { |
157 | | - address = "2001:db8::3"; |
158 | | - prefixLength = 64; |
159 | | - } |
160 | | - ]; |
161 | | - }; |
162 | | - services.gobgpd = { |
163 | | - enable = true; |
164 | | - settings = { |
165 | | - global.config = { |
166 | | - as = 64498; |
167 | | - router-id = "192.0.2.3"; |
168 | | - }; |
169 | | - neighbors = [ |
| 156 | + networking.interfaces = { |
| 157 | + eth1 = { |
| 158 | + ipv4.addresses = [ |
170 | 159 | { |
171 | | - config = { |
172 | | - neighbor-address = "192.0.2.1"; |
173 | | - peer-as = 64496; |
174 | | - }; |
175 | | - afi-safis = [ |
176 | | - { |
177 | | - config.afi-safi-name = "ipv4-unicast"; |
178 | | - } |
179 | | - ]; |
| 160 | + address = "192.0.2.3"; |
| 161 | + prefixLength = 29; |
180 | 162 | } |
| 163 | + ]; |
| 164 | + ipv6.addresses = [ |
181 | 165 | { |
182 | | - config = { |
183 | | - neighbor-address = "192.0.2.2"; |
184 | | - peer-as = 64497; |
185 | | - }; |
186 | | - afi-safis = [ |
187 | | - { |
188 | | - config.afi-safi-name = "ipv4-unicast"; |
189 | | - } |
190 | | - ]; |
| 166 | + address = "2001:db8::3"; |
| 167 | + prefixLength = 64; |
191 | 168 | } |
| 169 | + ]; |
| 170 | + }; |
| 171 | + lo = { |
| 172 | + ipv4.routes = [ |
192 | 173 | { |
193 | | - config = { |
194 | | - neighbor-address = "2001:db8::1"; |
195 | | - peer-as = 64496; |
196 | | - }; |
197 | | - afi-safis = [ |
198 | | - { |
199 | | - config.afi-safi-name = "ipv6-unicast"; |
200 | | - } |
201 | | - ]; |
| 174 | + address = "203.0.113.0"; |
| 175 | + prefixLength = 24; |
202 | 176 | } |
| 177 | + ]; |
| 178 | + ipv6.routes = [ |
203 | 179 | { |
204 | | - config = { |
205 | | - neighbor-address = "2001:db8::2"; |
206 | | - peer-as = 64497; |
207 | | - }; |
208 | | - afi-safis = [ |
209 | | - { |
210 | | - config.afi-safi-name = "ipv6-unicast"; |
211 | | - } |
212 | | - ]; |
| 180 | + address = "2001:db8:dead::"; |
| 181 | + prefixLength = 48; |
213 | 182 | } |
214 | 183 | ]; |
215 | 184 | }; |
216 | 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 | + }; |
217 | 282 | }; |
218 | 283 | }; |
219 | 284 |
|
|
228 | 293 | b.wait_for_unit("bird.service") |
229 | 294 | c.wait_for_unit("gobgpd.service") |
230 | 295 |
|
231 | | - a.wait_until_succeeds("vtysh -c 'show bgp ipv4 summary' | grep '192.0.2.2.*0\\s*0\\s*N/A'") |
232 | | - a.wait_until_succeeds("vtysh -c 'show bgp ipv4 summary' | grep '192.0.2.3.*0\\s*0\\s*N/A'") |
233 | | - b.wait_until_succeeds("birdc show protocols | grep 'a_v4.*Established'") |
234 | | - b.wait_until_succeeds("birdc show protocols | grep 'c_v4.*Established'") |
235 | | - c.wait_until_succeeds("gobgp neighbor -a 'ipv4' | grep '192.0.2.1.*Establ'") |
236 | | - c.wait_until_succeeds("gobgp neighbor -a 'ipv4' | grep '192.0.2.2.*Establ'") |
237 | | -
|
238 | | - # IPv6 DAD might need some time to complete for the local link address, which is required by frr |
239 | | - a.wait_until_succeeds("vtysh -c 'show bgp ipv6 summary' | grep '2001:db8::2.*0\\s*0\\s*N/A'") |
240 | | - a.wait_until_succeeds("vtysh -c 'show bgp ipv6 summary' | grep '2001:db8::3.*0\\s*0\\s*N/A'") |
241 | | - b.wait_until_succeeds("birdc show protocols | grep 'a_v6.*Established'") |
242 | | - b.wait_until_succeeds("birdc show protocols | grep 'c_v4.*Established'") |
243 | | - c.wait_until_succeeds("gobgp neighbor -a 'ipv6' | grep '2001:db8::1.*Establ'") |
244 | | - c.wait_until_succeeds("gobgp neighbor -a 'ipv6' | grep '2001:db8::2.*Establ'") |
| 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'") |
| 303 | +
|
| 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'") |
| 311 | +
|
| 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") |
245 | 325 | ''; |
246 | 326 | } |
0 commit comments