1
0

Compare commits

...

8 Commits

Author SHA1 Message Date
44c1fb7632 delete now-unused (pkgs.liminix.network) interface address 2023-08-31 18:30:22 +01:00
e577caa15f extneder: use bridge module 2023-08-31 18:29:45 +01:00
7faf620c0b move loopback config from base to netowrk module 2023-08-31 18:28:35 +01:00
b094220466 mt300a: use module-based network services for lan/wan 2023-08-31 18:27:07 +01:00
f1dfb1f976 BRIDGE_VLAN_FILTERING depends on bridge _and_ vlan
I'm half-pleased with this. It demonstrates how we can have complex
conditional kernel config, but the way we detect if vlan exists is
tacky.
2023-08-31 18:24:09 +01:00
333327be75 make a module for vlan
Acked-by: Daniel Barlow <<dan@telent.net>>
2023-08-30 23:26:44 +01:00
efa1919e04 move squashfs kernel options into module 2023-08-30 22:59:28 +01:00
de77635490 move bridge-related kernel config to the module 2023-08-30 17:29:42 +01:00
14 changed files with 166 additions and 131 deletions

View File

@ -204,8 +204,6 @@
PARTITION_ADVANCED = "y";
PRINTK_TIME = "y";
SQUASHFS = "y";
SQUASHFS_XZ = "y";
};
};
};

View File

@ -55,28 +55,41 @@
"${openwrt.src}/target/linux/ramips/dts"
];
};
networkInterfaces = rec {
# lan and wan ports are both behind a switch on eth0
eth = interface { device = "eth0"; };
lan = interface {
type = "vlan";
device = "eth0.1";
link = "eth0";
id = "1";
dependencies = [eth];
networkInterfaces =
let
inherit (config.system.service.network) link;
inherit (config.system.service) vlan;
inherit (pkgs.liminix.services) oneshot;
swconfig = oneshot {
name = "swconfig";
up = ''
PATH=${pkgs.swconfig}/bin:$PATH
swconfig dev switch0 set reset
swconfig dev switch0 set enable_vlan 1
swconfig dev switch0 vlan 1 set ports '1 2 3 4 6t'
swconfig dev switch0 vlan 2 set ports '0 6t'
swconfig dev switch0 set apply
'';
down = "swconfig dev switch0 set reset";
};
in rec {
eth = link.build { ifname = "eth0"; dependencies = [swconfig]; };
# lan and wan ports are both behind a switch on eth0
lan = vlan.build {
ifname = "eth0.1";
primary = eth;
vid = "1";
};
wan = vlan.build {
ifname = "eth0.2";
primary = eth;
vid = "2";
};
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
};
wan = interface {
type = "vlan";
device = "eth0.2";
id = "2";
link = "eth0";
dependencies = [eth];
};
wlan = interface {
device = "wlan0";
dependencies = [ mac80211 ];
};
};
};
boot.tftp = {
loadAddress = "0x00A00000";
@ -115,6 +128,7 @@
NET_RALINK_MDIO = "y";
NET_RALINK_MDIO_MT7620 = "y";
NET_RALINK_MT7620 = "y";
SWPHY = "y";
SPI = "y";
MTD_SPI_NOR = "y";
@ -123,18 +137,6 @@
SPI_MASTER= "y";
SPI_MEM= "y";
# both the ethernet ports on this device (lan and wan)
# are behind a switch, so we need VLANs to do anything
# useful with them
VLAN_8021Q = "y";
SWCONFIG = "y";
SWPHY = "y";
BRIDGE = "y";
BRIDGE_VLAN_FILTERING = "y";
BRIDGE_IGMP_SNOOPING = "y";
MTD = "y";
MTD_CMDLINE_PARTS = "y";
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_devs
@ -149,8 +151,6 @@
PARTITION_ADVANCED = "y";
PRINTK_TIME = "y";
SQUASHFS = "y";
SQUASHFS_XZ = "y";
};
};
};

View File

@ -52,44 +52,40 @@
"${openwrt.src}/target/linux/ramips/dts"
];
};
networkInterfaces = rec {
# lan and wan ports are both behind a switch on eth0
eth =
let swconfig = oneshot {
name = "swconfig";
up = ''
PATH=${pkgs.swconfig}/bin:$PATH
swconfig dev switch0 set reset
swconfig dev switch0 set enable_vlan 1
swconfig dev switch0 vlan 1 set ports '1 2 3 4 6t'
swconfig dev switch0 vlan 2 set ports '0 6t'
swconfig dev switch0 set apply
'';
down = "swconfig dev switch0 set reset";
};
in interface {
device = "eth0";
dependencies = [swconfig];
networkInterfaces =
let
inherit (config.system.service.network) link;
inherit (config.system.service) vlan;
swconfig = oneshot {
name = "swconfig";
up = ''
PATH=${pkgs.swconfig}/bin:$PATH
swconfig dev switch0 set reset
swconfig dev switch0 set enable_vlan 1
swconfig dev switch0 vlan 1 set ports '1 2 3 4 6t'
swconfig dev switch0 vlan 2 set ports '0 6t'
swconfig dev switch0 set apply
'';
down = "swconfig dev switch0 set reset";
};
in rec {
eth = link.build { ifname = "eth0"; dependencies = [swconfig]; };
# lan and wan ports are both behind a switch on eth0
lan = vlan.build {
ifname = "eth0.1";
primary = eth;
vid = "1";
};
wan = vlan.build {
ifname = "eth0.2";
primary = eth;
vid = "2";
};
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
lan = interface {
type = "vlan";
device = "eth0.1";
link = "eth0";
id = "1";
dependencies = [eth];
};
wan = interface {
type = "vlan";
device = "eth0.2";
id = "2";
link = "eth0";
dependencies = [eth];
};
wlan = interface {
device = "wlan0";
dependencies = [ mac80211 ];
};
};
};
boot.tftp = {
# 20MB seems to give enough room to uncompress the kernel
@ -148,19 +144,8 @@
NET_VENDOR_RALINK = "y";
NET_RALINK_RT3050 = "y";
NET_RALINK_SOC="y";
# both the ethernet ports on this device (lan and wan)
# are behind a switch, so we need VLANs to do anything
# useful with them
VLAN_8021Q = "y";
SWCONFIG = "y";
SWPHY = "y";
BRIDGE = "y";
BRIDGE_VLAN_FILTERING = "y";
BRIDGE_IGMP_SNOOPING = "y";
WATCHDOG = "y";
RALINK_WDT = "y"; # watchdog
MT7621_WDT = "y"; # or it might be this one
@ -175,8 +160,6 @@
PARTITION_ADVANCED = "y";
PRINTK_TIME = "y";
SQUASHFS = "y";
SQUASHFS_XZ = "y";
};
};
};

View File

@ -30,9 +30,6 @@
MTD_BLKDEVS = "y";
MTD_BLOCK = "y";
SQUASHFS = "y";
SQUASHFS_XZ = "y";
VIRTIO_MENU = "y";
PCI = "y";
VIRTIO_PCI = "y";

View File

@ -31,6 +31,7 @@ in rec {
../modules/standard.nix
../modules/wlan.nix
../modules/network
../modules/vlan
];
hostname = "arhcive";

View File

@ -31,6 +31,7 @@ in rec {
imports = [
../modules/wlan.nix
../modules/vlan
../modules/network
../modules/hostapd
../modules/bridge
@ -88,9 +89,8 @@ in rec {
};
};
services.int = interface {
type = "bridge";
device = "int";
services.int = svc.bridge.primary.build {
ifname = "int";
};
services.dhcpc = svc.network.dhcp.client.build {

View File

@ -80,18 +80,6 @@ in {
defaultProfile.packages = with pkgs;
[ s6 s6-init-bin execline s6-linux-init s6-rc ];
hardware.networkInterfaces = {
lo =
let iface = interface { type = "loopback"; device = "lo";};
in bundle {
name = "loopback";
contents = [
(address iface { family = "inet4"; address ="127.0.0.1"; prefixLength = 8;})
(address iface { family = "inet6"; address ="::1"; prefixLength = 128;})
];
};
};
boot.commandLine = [
"console=ttyS0,115200 panic=10 oops=panic init=/bin/init loglevel=8"
"root=${config.hardware.rootDevice}"

View File

@ -39,5 +39,13 @@ in
};
};
};
config.kernel.config.BRIDGE = "y";
config.kernel.config = {
BRIDGE = "y";
BRIDGE_IGMP_SNOOPING = "y";
} // lib.optionalAttrs (config.system.service ? vlan) {
# depends on bridge _and_ vlan. I would like there to be
# a better way to test for the existence of vlan config:
# maybe the module should set an `enabled` attribute?
BRIDGE_VLAN_FILTERING = "y";
};
}

View File

@ -5,7 +5,6 @@
}:
{ ifname } :
let
inherit (liminix.networking) interface;
inherit (liminix.services) bundle oneshot;
inherit (lib) mkOption types;
in oneshot rec {

View File

@ -9,6 +9,7 @@
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
inherit (pkgs.liminix.services) bundle;
in {
options = {
system.service.network = {
@ -31,6 +32,30 @@ in {
};
};
config = {
hardware.networkInterfaces = {
lo =
let
net = config.system.service.network;
iface = net.link.build { ifname = "lo";};
in bundle {
name = "loopback";
contents = [
( net.address.build {
interface = iface;
family = "inet";
address ="127.0.0.1";
prefixLength = 8;
})
( net.address.build {
interface = iface;
family = "inet6";
address = "::1";
prefixLength = 128;
})
];
};
};
system.service.network = {
link = liminix.callService ./link.nix {
ifname = mkOption {

View File

@ -12,5 +12,9 @@ in
config = mkIf (config.rootfsType == "squashfs") {
system.outputs.rootfs =
liminix.builders.squashfs config.filesystem.contents;
kernel.config = {
SQUASHFS = "y";
SQUASHFS_XZ = "y";
};
};
}

41
modules/vlan/default.nix Normal file
View File

@ -0,0 +1,41 @@
## VLAN
## ====
##
## Virtual LANs give you the ability to sub-divide a LAN. Linux can
## accept VLAN tagged traffic and presents each VLAN ID as a
## different network interface (eg: eth0.100 for VLAN ID 100)
##
## Some Liminix devices with multiple ethernet ports are implemented
## using a network switch connecting the physical ports to the CPU,
## and require using VLAN in order to send different traffic to
## different ports (e.g. LAN vs WAN)
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix;
in
{
options = {
system.service.vlan = mkOption { type = liminix.lib.types.serviceDefn; };
};
config.system.service.vlan = liminix.callService ./service.nix {
ifname = mkOption {
type = types.str;
description = "interface name to create";
};
primary = mkOption {
description = "existing physical interface";
type = liminix.lib.types.interface;
};
vid = mkOption {
description = "VLAN identifier (VID) in range 1-4094";
type = types.str;
};
};
config.kernel.config = {
VLAN_8021Q = "y";
SWCONFIG = "y"; # not always appropriate, some devices will use DSA
};
}

15
modules/vlan/service.nix Normal file
View File

@ -0,0 +1,15 @@
{
liminix
, lib
}:
{ ifname, primary, vid } :
let
inherit (liminix.services) oneshot;
in oneshot rec {
name = "${ifname}.link";
up = ''
ip link add link $(output ${primary} ifname) name ${ifname} type vlan id ${vid}
${liminix.networking.ifup name ifname}
'';
down = "ip link set down dev ${ifname}";
}

View File

@ -18,32 +18,8 @@ let
'';
in {
interface = { type ? "hardware", device, link ? null, primary ? null, id ? null, dependencies ? [] } @ args:
let name = "${device}.link";
ups =
[]
++ optional (type == "bridge")
"ip link add name ${device} type bridge"
++ optional (type == "vlan")
"ip link add link ${link} name ${device} type vlan id ${id}"
++ [(ifup name device)]
++ optional (primary != null)
"ip link set dev ${device} master ${primary.device}";
in oneshot {
inherit name;
up = lib.concatStringsSep "\n" ups;
down = "ip link set down dev ${device}";
dependencies = dependencies ++ lib.optional (primary != null) primary;
};
inherit ifup;
address = interface: { family, dependencies ? [], prefixLength, address } @ args:
let inherit (builtins) toString;
in oneshot {
dependencies = [ interface ] ++ dependencies;
name = "${interface.name}.addr.${address}";
up = "ip address add ${address}/${toString prefixLength} dev $(output ${interface} ifname)";
down = "ip address del ${address}/${toString prefixLength} dev $(output ${interface} ifname)";
};
route = { name, target, via, dependencies, dev ? null }:
let with_dev = if dev != null then "dev ${dev}" else "";
in oneshot {