bgpwtf/machines: init edge01.waw
This configures our WAW edge router using NixOS. This replaces our
previous Ubuntu installation.
Change-Id: Ibd72bde66ec413164401da407c5b268ad83fd3af
diff --git a/bgpwtf/machines/tests/edge01-waw.nix b/bgpwtf/machines/tests/edge01-waw.nix
new file mode 100644
index 0000000..e0298d2
--- /dev/null
+++ b/bgpwtf/machines/tests/edge01-waw.nix
@@ -0,0 +1,288 @@
+# Smoke test edge01.waw in a multi-VM NixOS test.
+#
+# This brings up three VMs:
+# - dut/edge01
+# - bgpspeaker, which simulates bgp upstreams
+# - customs, which simulates customs.hackerspace.pl.
+#
+# We use EoIP to build up virtual ethernet links between the machines, and
+# to run VLANs on that. We don't just use plain 'vlans' from NixOS tests as
+# we actually want to run 802.1q ourselves from the edge01 config.
+#
+# Everything else is pretty much straightforward. Bring up everything, ping
+# stuff. We don't really test much else than internet routing.
+#
+# To run this:
+# nix-build -A bgpwtf.machines.tests.edge01-waw
+#
+# To debug this:
+# nix-build -A bgpwtf.machines.tests.edge01-waw.driver && result/bin/nixos-test-driver
+# >>> start_all()
+
+{ hscloud, pkgsSrc, pkgs, lib, ... }:
+
+with lib;
+
+let
+
+mkBGPSpeaker = let
+in { config, pkgs, ... }: {
+ networking.hostName = "bgpspeaker";
+ virtualisation.memorySize = 1024;
+ virtualisation.vlans = [ 1 ];
+ imports = [
+ ../modules/eoip.nix
+ ];
+
+ hscloud.eoip.interfaces."nnet" = {
+ parent = "eth1";
+ localV4 = "192.168.1.3";
+ remoteV4 = "192.168.1.2";
+ id = 100;
+ };
+ networking.interfaces."nnet" = {
+ virtual = true;
+ virtualType = "tap";
+ };
+ networking.vlans = {
+ "vl-globalmix" = { interface = "nnet"; id = 466; };
+ };
+ networking.interfaces."vl-globalmix" = {
+ ipv4.addresses = [{ address = "185.235.70.44"; prefixLength = 31; }];
+ ipv6.addresses = [{ address = "2001:67c:778:fd40::b9eb:462c"; prefixLength = 127; }];
+ };
+
+ services.bird2 = {
+ enable = true;
+ config = ''
+ log syslog all;
+ debug protocols { states, interfaces, events }
+ router id 185.235.70.44;
+
+ protocol device {
+ scan time 10;
+ };
+ protocol kernel kernel_v4 {
+ ipv4 {
+ import none;
+ export all;
+ };
+ }
+ protocol kernel kernel_v6 {
+ ipv6 {
+ import none;
+ export all;
+ };
+ }
+ ipv4 table globalmix4;
+ ipv6 table globalmix6;
+
+ protocol pipe pipe_globalmix4 {
+ table master4;
+ peer table globalmix4;
+ import all;
+ export none;
+ };
+ protocol pipe pipe_globalmix6 {
+ table master6;
+ peer table globalmix6;
+ import all;
+ export none;
+ };
+
+ protocol static static_globalmix_originate_v4 {
+ ipv4 {
+ table globalmix4;
+ import all;
+ };
+ route 8.8.8.0/24 blackhole;
+ }
+ protocol static static_globalmix_originate_v6 {
+ ipv6 {
+ table globalmix6;
+ import all;
+ };
+ route 2a00:1450:4016::/48 blackhole;
+ }
+ protocol bgp bgp_globalmix_v4 {
+ ipv4 {
+ table globalmix4;
+ export all;
+ import all;
+ };
+ local 185.235.70.44 as 62081;
+ neighbor 185.235.70.45 as 204880;
+ };
+ protocol bgp bgp_globalmix_v6 {
+ ipv6 {
+ table globalmix6;
+ export all;
+ import all;
+ };
+ local 2001:67c:778:fd40::b9eb:462c as 62081;
+ neighbor 2001:67c:778:fd40::b9eb:462d as 204880;
+ };
+ '';
+ };
+ networking.firewall.enable = false;
+ networking.useDHCP = false;
+ networking.interfaces.lo.ipv4.addresses = [ { address = "8.8.8.1"; prefixLength = 32; } ];
+ networking.interfaces.lo.ipv6.addresses = [ { address = "2a00:1450:4016:801::200e"; prefixLength = 128; } ];
+ environment.systemPackages = with pkgs; [
+ tcpdump htop dstat file
+ ];
+
+};
+
+
+test = import "${pkgsSrc}/nixos/tests/make-test-python.nix" ({ pkgs, libs, ... }: {
+ name = "test-edge01-waw-e2e";
+
+ nodes = {
+ dut = { config, pkgs, ... }: {
+ imports = [
+ ../edge01.waw.bgp.wtf.nix
+ ../modules/eoip.nix
+ ];
+ virtualisation.memorySize = 1024;
+ virtualisation.vlans = [
+ 1 2
+ ];
+
+ hscloud.eoip.interfaces = {
+ "e1-nnet" = { parent = "eth1"; localV4 = "192.168.1.2"; remoteV4 = "192.168.1.3"; id = 100; };
+ "e2-customs" = { parent = "eth2"; localV4 = "192.168.2.2"; remoteV4 = "192.168.2.1"; id = 200; };
+ "e3-mgmt" = { parent = "eth2"; localV4 = "192.168.2.2"; remoteV4 = "192.168.2.111"; id = 300; }; # not connected
+ "e4-oob" = { parent = "eth2"; localV4 = "192.168.2.2"; remoteV4 = "192.168.2.112"; id = 400; }; # not connected
+ "e7-dcsw" = { parent = "eth2"; localV4 = "192.168.2.2"; remoteV4 = "192.168.2.113"; id = 500; }; # not connected
+ };
+ networking.interfaces = {
+ "e1-nnet" = { virtual = true; virtualType = "tap"; };
+ "e2-customs" = { virtual = true; virtualType = "tap"; };
+ "e3-mgmt" = { virtual = true; virtualType = "tap"; };
+ "e4-oob" = { virtual = true; virtualType = "tap"; };
+ "e7-dcsw" = { virtual = true; virtualType = "tap"; };
+ };
+ };
+
+ speaker = mkBGPSpeaker;
+
+ customs = { config, pkgs, ... }: {
+ imports = [
+ ../modules/eoip.nix
+ ];
+ environment.systemPackages = with pkgs; [
+ tcpdump htop dstat file dhcpcd
+ ];
+ virtualisation.memorySize = 1024;
+ virtualisation.vlans = [
+ 2
+ ];
+ networking.firewall.enable = false;
+ networking.useDHCP = false;
+ networking.defaultGateway = "185.236.240.4";
+ networking.defaultGateway6 = "2a0d:eb00:2137:1::2";
+ networking.interfaces."edge" = {
+ virtual = true;
+ virtualType = "tap";
+ ipv4.addresses = [{ address = "185.236.240.5"; prefixLength = 31; }];
+ ipv6.addresses = [{ address = "2a0d:eb00:2137:1::3"; prefixLength = 127; }];
+ };
+ hscloud.eoip.interfaces."edge" = {
+ parent = "eth2";
+ localV4 = "192.168.2.1";
+ remoteV4 = "192.168.2.2";
+ id = 200;
+ };
+ networking.bridges."lan".interfaces = [];
+ networking.interfaces."lan" = {
+ ipv4.addresses = [{ address = "10.8.1.2"; prefixLength = 23; }];
+ ipv6.addresses = [{ address = "2a0d:eb00:4242::1"; prefixLength = 64; }];
+ };
+ services.bird2 = {
+ enable = true;
+ config = ''
+ log syslog all;
+ debug protocols { states, interfaces, events }
+ router id 185.236.240.5;
+
+ protocol device {
+ scan time 10;
+ };
+ protocol kernel kernel_v4 {
+ ipv4 {
+ import none;
+ export all;
+ };
+ }
+ protocol kernel kernel_v6 {
+ ipv6 {
+ import none;
+ export all;
+ };
+ }
+
+ protocol ospf v3 ospf_hswaw {
+ ipv6 {
+ import all;
+ export all;
+ };
+ area 0.0.0.0 {
+ interface "edge" {
+ cost 10;
+ type bcast;
+ };
+ interface "lan" {
+ cost 10;
+ stub yes;
+ type bcast;
+ check link no;
+ };
+ };
+ }
+ '';
+ };
+ };
+ };
+
+ testScript = ''
+ start_all()
+
+ edge01.wait_for_unit("bird2.service")
+ # Wait for BGP to settle.
+ edge01.wait_until_succeeds("ping 185.235.70.44 -c 1 -w 2")
+ edge01.wait_until_succeeds("birdc show route for 8.8.8.1 table all | grep via")
+ edge01.wait_until_succeeds(
+ "birdc show route for 2a00:1450:4016:801::200e table all | grep via"
+ )
+ edge01.succeed("ping 8.8.8.1 -c 1 -w 2")
+
+ # ping from customs to globalmix must succeed.
+ customs.succeed("ping 8.8.8.1 -c 1 -w 2")
+ customs.succeed("ping 2a00:1450:4016:801::200e -c 1 -w 2")
+
+ # edge01 must announce exactly one v4 prefix.
+ bgpspeaker.succeed("birdc show route protocol bgp_globalmix_v4 | grep unicast")
+ bgpspeaker.fail(
+ "birdc show route protocol bgp_globalmix_v4 | grep unicast | grep -v 185.236.240.0/23"
+ )
+
+ # edge01 must announce exactly one v6 prefix.
+ bgpspeaker.succeed("birdc show route protocol bgp_globalmix_v6 | grep unicast")
+ bgpspeaker.fail(
+ "birdc show route protocol bgp_globalmix_v6 | grep unicast | grep -v 2a0d:eb00::/32"
+ )
+
+ # customer networks must be reachable from globalmix
+ bgpspeaker.succeed("ping 185.236.240.10 -c 1 -w 2")
+ bgpspeaker.succeed("ping 2a0d:eb00:8000::1 -c 1 -w 2")
+ bgpspeaker.succeed("ping 185.236.240.12 -c 1 -w 2")
+ bgpspeaker.succeed("ping 185.236.240.105 -c 1 -w 2")
+ bgpspeaker.succeed("ping 2a0d:eb00:8003::1 -c 1 -w 2")
+
+ # dhcp agent must be reachable
+ customs.succeed("ping 185.236.240.18 -c 1 -w 2")
+ '';
+});
+
+in test { inherit pkgs; inherit (pkgs) libs; }