From 28a5dec7dd31834394748c9b19411715eeddc43c Mon Sep 17 00:00:00 2001 From: Daniel Barlow Date: Sat, 16 Mar 2024 20:41:13 +0000 Subject: [PATCH] implement ifwait trigger service and use in bridge should we convert all ifwait uses to this trigger too? seems reasonable --- modules/bridge/default.nix | 6 +++-- modules/bridge/members.nix | 21 ++++++++++++------ modules/ifwait/default.nix | 18 +++++++++++++++ modules/ifwait/ifwait.nix | 15 +++++++++++++ tests/updown/script.expect | 45 +++++++++++++++++++++++++++++++++----- 5 files changed, 91 insertions(+), 14 deletions(-) create mode 100644 modules/ifwait/default.nix create mode 100644 modules/ifwait/ifwait.nix diff --git a/modules/bridge/default.nix b/modules/bridge/default.nix index 48fdb12..32df4a5 100644 --- a/modules/bridge/default.nix +++ b/modules/bridge/default.nix @@ -14,6 +14,8 @@ let inherit (pkgs) liminix; in { + imports = [ ../ifwait ]; + options = { system.service.bridge = { primary = mkOption { type = liminix.lib.types.serviceDefn; }; @@ -27,7 +29,7 @@ in description = "bridge interface name to create"; }; }; - members = liminix.callService ./members.nix { + members = config.system.callService ./members.nix { primary = mkOption { type = liminix.lib.types.interface; description = "primary bridge interface"; @@ -47,5 +49,5 @@ in # a better way to test for the existence of vlan config: # maybe the module should set an `enabled` attribute? BRIDGE_VLAN_FILTERING = "y"; - }; + }; } diff --git a/modules/bridge/members.nix b/modules/bridge/members.nix index ca1989e..a278730 100644 --- a/modules/bridge/members.nix +++ b/modules/bridge/members.nix @@ -2,6 +2,7 @@ liminix , ifwait , lib +, svc }: { members, primary } : @@ -10,14 +11,20 @@ let inherit (liminix.services) bundle oneshot; inherit (lib) mkOption types; addif = member : - oneshot { - name = "${primary.name}.member.${member.name}"; - up = '' - dev=$(output ${member} ifname) - ${ifwait}/bin/ifwait $dev running && ip link set dev $dev master $(output ${primary} ifname) - ''; - down = "ip link set dev $(output ${member} ifname) nomaster"; + # how do we get sight of services from here? maybe we need to + # implement ifwait as a regualr derivation instead of a + # servicedefinition + svc.ifwait.build { + state = "running"; + interface = member; dependencies = [ primary member ]; + service = oneshot { + name = "${primary.name}.member.${member.name}"; + up = '' + ip link set dev $(output ${member} ifname) master $(output ${primary} ifname) + ''; + down = "ip link set dev $(output ${member} ifname) nomaster"; + }; }; in bundle { name = "${primary.name}.members"; diff --git a/modules/ifwait/default.nix b/modules/ifwait/default.nix new file mode 100644 index 0000000..501f317 --- /dev/null +++ b/modules/ifwait/default.nix @@ -0,0 +1,18 @@ +{ config, pkgs, lib, ... } : +let + inherit (pkgs) liminix; + inherit (lib) mkOption types; +in { + options.system.service.ifwait = + mkOption { type = liminix.lib.types.serviceDefn; }; + + config.system.service.ifwait = config.system.callService ./ifwait.nix { + state = mkOption { type = types.str; }; + interface = mkOption { + type = liminix.lib.types.interface; + }; + service = mkOption { + type = liminix.lib.types.service; + }; + }; +} diff --git a/modules/ifwait/ifwait.nix b/modules/ifwait/ifwait.nix new file mode 100644 index 0000000..4c28b52 --- /dev/null +++ b/modules/ifwait/ifwait.nix @@ -0,0 +1,15 @@ +{ ifwait, liminix } : +{ + state +, interface +, service +}: +let + inherit (liminix.services) longrun; +in longrun { + name = "ifwait.${interface.name}"; + buildInputs = [ service ]; + run = '' + ${ifwait}/bin/ifwait -s ${service.name} $(output ${interface} ifname) ${state} + ''; +} diff --git a/tests/updown/script.expect b/tests/updown/script.expect index 89e60c1..232f49a 100644 --- a/tests/updown/script.expect +++ b/tests/updown/script.expect @@ -13,9 +13,14 @@ spawn socat unix-connect:vm/console - set console_id $spawn_id expect "BusyBox" -expect "#" { send "PS1=RE\\ADY_\\ \r" } -expect "READY_" { send "sleep 3\r" } -expect "READY_" { send "ip link\r" } +expect "#" { send "PS1=RE\\ADY_\\ ; stty -echo \r" } +expect "READY_" { send "s6-rc -b -a list\r" } ; # -b waits for s6-rc lock +expect "READY_" { send "ls /sys/class/net/lan/master\r" } +expect { + "No such file or directory" { } + timeout { exit 1 } +} + expect "READY_" { send "cat /sys/class/net/lan/operstate\r" } expect { "down" { } @@ -24,6 +29,36 @@ expect { expect "READY_" { send "s6-rc -a -u change\r" } expect { "unable to take locks" { exit 1 } - "READY_" { send "hostname\r" } + "READY_" { send "\r" } } -expect "updown" + +set spawn_id $monitor_id +send "\r" +expect "(qemu)" +send "set_link virtio-net-pci.1 on\n" +expect "(qemu)" +send "set_link virtio-net-pci.0 on\n" +expect "(qemu)" +set spawn_id $console_id + +expect "entered forwarding state" +send "\r" +expect "READY_" { send "cat /sys/class/net/lan/operstate\r" } +expect { + "down" { exit 1 } + "up" { } +} + +expect "READY_" { send "cat /sys/class/net/lan/master/uevent\r" } +expect { + "INTERFACE=int" { } + timeout { exit 1 } +} + +expect "READY_" { send "s6-rc listall int.link.a.10.8.0.1.member.lan.link ; hostname\r" } + +expect { + "updown" {} + timeout { exit 1 } +} +