From c8613de03a610acfcbfa55bec040dcc7c424ad25 Mon Sep 17 00:00:00 2001 From: kurogeek Date: Tue, 4 Aug 2026 14:24:36 +0700 Subject: [PATCH] mob next [ci-skip] [ci skip] [skip ci] lastFile:modules/clan/gw-router/default.nix --- modules/clan/gw-router/default.nix | 78 ++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 9 deletions(-) diff --git a/modules/clan/gw-router/default.nix b/modules/clan/gw-router/default.nix index 8dea8d3..0a5beea 100644 --- a/modules/clan/gw-router/default.nix +++ b/modules/clan/gw-router/default.nix @@ -136,10 +136,17 @@ }; accessPorts = lib.mkOption { - type = lib.types.listOf lib.types.str; + type = lib.types.attrsOf lib.types.submodule { + options = { + vlanId = lib.mkOption { + type = lib.types.int; + description = "Untagged traffic in from the device gets tagged VLANs inside the bridge, and VLANs traffic going back out to the device gets untagged, so the device itself never has to know VLANs exist."; + }; + }; + }; description = '' Ports acting as untagged access ports on a single VLAN (port name -> - VLAN name). Frames are untagged on the wire; the bridge tags them with + VLAN id). Frames are untagged on the wire; the bridge tags them with the VLAN's PVID. Use for an always-available on-site mgmt port. ''; }; @@ -177,7 +184,7 @@ }; } // lib.optionalAttrs (settings.wan.vlanId != null) { - "15-wan-vlan" = { + "15-wan-lan" = { netdevConfig = { Name = "wan-vlan"; Kind = "vlan"; @@ -196,12 +203,65 @@ } ) settings.vlans; - systemd.network.networks = { - "10-wan" = { - matchConfig.Name = settings.wan.interface; - networkConfig.LinkLocalAddressing = "no"; - }; - }; + systemd.network.networks = + let + allVLANs = lib.mapAttrsToList (_: vlan: { VLAN = vlan.id; }) settings.vlans; + in + { + "10-wan" = { + matchConfig.Name = settings.wan.interface; + networkConfig.LinkLocalAddressing = "no"; + vlan = lib.optional (settings.wan.vlanId != null) "wan-wlan"; + linkConfig = { + RequiredForOnline = "carrier"; + } + // lib.optionalAttrs (settings.wan.macAddress != null) { + MACAddress = settings.wan.macAddress; + }; + }; + } + // lib.optionalAttrs (settings.wan.vlanId != null) { + "15-wan-lan" = { + matchConfig.Name = "wan-vlan"; + networkConfig.LinkLocalAddressing = "no"; + linkConfig.RequiredForOnline = "no"; + }; + } + // { + "20-br0" = { + matchConfig.Name = "br0"; + networkConfig.LinkLocalAddressing = "no"; + vlan = lib.mapAttrsToList (name: _: vlanIf name) settings.vlans; + bridgeVLANs = allVLANs; + linkConfig.RequiredForOnline = "no"; + }; + } + // lib.listToAttrs ( + map (port: { + name = "25-trunk-${port}"; + value = { + matchConfig.Name = port; + networkConfig.Bridge = "br0"; + bridgeVLANs = allVLANs; + linkConfig.RequiredForOnline = "no"; + }; + }) settings.trunkPorts + ) + // lib.mapAttrs' ( + iface: port: + lib.nameValuePair "20-access-${iface}" { + matchConfig.Name = port; + networkConfig.Bridge = "br0"; + bridgeVLANs = [ + { + VLAN = port.vlanId; + PVID = port.vlanId; + EgressUntagged = port.vlanId; + } + ]; + linkConfig.RequiredForOnline = "no"; + } + ) settings.accessPorts; environment.systemPackages = with pkgs; [ tcpdump