159 lines
4.8 KiB
Nix
159 lines
4.8 KiB
Nix
{ self, openwrt }:
|
|
let
|
|
# the files that contain port definitions
|
|
defFiles = builtins.filter
|
|
(self.lib.hasSuffix "/etc/board.d/02_network")
|
|
(self.lib.filesystem.listFilesRecursive "${openwrt}/target/linux");
|
|
# files contents as one string
|
|
defSource = builtins.concatStringsSep "\n" (
|
|
map builtins.readFile defFiles
|
|
);
|
|
defSourceLines = builtins.filter (s: s != []) (
|
|
builtins.split "\n" (
|
|
builtins.replaceStrings
|
|
[ "\\\n" ] [ "" ] defSource
|
|
));
|
|
|
|
parseCommand = line:
|
|
let
|
|
tokens =
|
|
builtins.concatMap (frag:
|
|
if builtins.isString frag
|
|
then builtins.split "[[:space:]]+" frag
|
|
else frag
|
|
) (
|
|
builtins.split "\"([^\"]*)\"" line
|
|
);
|
|
words =
|
|
builtins.filter (word:
|
|
word != [] && word != ""
|
|
) tokens;
|
|
command = builtins.head words;
|
|
args = builtins.tail words;
|
|
|
|
makeLinkFromArg = port: arg:
|
|
builtins.foldl' (result: interface:
|
|
if port != []
|
|
then result // {
|
|
"${port}" = {
|
|
type = "phys";
|
|
inherit interface port;
|
|
};
|
|
}
|
|
else result
|
|
) {} (builtins.split "[[:space:]]+" arg);
|
|
|
|
commands = {
|
|
ucidef_add_switch.ports = builtins.foldl' (ports: arg:
|
|
let
|
|
switch = builtins.head args;
|
|
m1 = builtins.match "([[:digit:]]+):(.+)" arg;
|
|
m2 = builtins.match "([[:digit:]]+)([ut]?)@(.+)" arg;
|
|
m2flag = builtins.elemAt m2 1;
|
|
port = if m1 != null
|
|
then {
|
|
inherit switch;
|
|
type = "port";
|
|
index = builtins.elemAt m1 0;
|
|
port = builtins.elemAt m1 1;
|
|
}
|
|
else if m2 != null
|
|
then {
|
|
inherit switch;
|
|
type = "host";
|
|
index = builtins.elemAt m2 0;
|
|
interface = builtins.elemAt m2 2;
|
|
} // self.lib.optionalAttrs (m2flag == "u") {
|
|
only = "untagged";
|
|
} // self.lib.optionalAttrs (m2flag == "t") {
|
|
only = "tagged";
|
|
}
|
|
else throw "Unimplemented port scheme: ${arg}";
|
|
in if m1 != null || m2 != null
|
|
then ports // {
|
|
"${port.index}" = port;
|
|
}
|
|
else builtins.trace "Unimplemented port scheme: ${arg}" ports
|
|
) {} (builtins.tail args);
|
|
|
|
ucidef_set_interface_wan.ports = {
|
|
"${builtins.head args}" = {
|
|
type = "phys";
|
|
interface = builtins.head args;
|
|
port = "wan";
|
|
};
|
|
};
|
|
|
|
ucidef_set_interface_lan.ports =
|
|
makeLinkFromArg "lan" (builtins.elemAt args 0);
|
|
|
|
ucidef_set_interfaces_lan_wan.ports =
|
|
makeLinkFromArg "lan" (builtins.elemAt args 0) //
|
|
makeLinkFromArg "wan" (builtins.elemAt args 1);
|
|
};
|
|
in
|
|
if commands ? ${command}
|
|
then commands.${command}
|
|
else {
|
|
unknown."${command}" = args;
|
|
};
|
|
|
|
in (
|
|
builtins.foldl' ({ state, result, models ? null, data ? {} }: line:
|
|
if state == "start"
|
|
then
|
|
if builtins.match "[[:space:]]*case \"?\\$board\"? in" line != null
|
|
then { state = "case"; inherit result; }
|
|
else { inherit state result; }
|
|
|
|
else if state == "case"
|
|
then
|
|
if builtins.match "[[:space:]]*esac" line != null
|
|
then { state = "start"; inherit result; }
|
|
else
|
|
let
|
|
m = builtins.match "[[:space:]]*(.+)\\)" line;
|
|
in
|
|
if m == null
|
|
then { inherit state result; }
|
|
else {
|
|
inherit result;
|
|
state = "model";
|
|
models =
|
|
builtins.filter (m: m != null) (
|
|
map (s:
|
|
let
|
|
m = builtins.split "," s;
|
|
in
|
|
if s != [] &&
|
|
m != null &&
|
|
builtins.length m == 3
|
|
then {
|
|
vendor = builtins.elemAt m 0;
|
|
model = builtins.elemAt m 2;
|
|
}
|
|
else null
|
|
) (
|
|
builtins.split "[[:space:]]*\\|[[:space:]]*" (
|
|
builtins.head m
|
|
)));
|
|
}
|
|
|
|
else if state == "model"
|
|
then
|
|
if builtins.match "[[:space:]]*;;" line != null
|
|
then {
|
|
state = "case";
|
|
result = result ++ [ {
|
|
inherit models data;
|
|
} ];
|
|
}
|
|
else {
|
|
inherit result state models;
|
|
data = self.lib.recursiveUpdate data (parseCommand line);
|
|
}
|
|
|
|
else throw "Invalid state ${state}"
|
|
) { state = "start"; result = []; } defSourceLines
|
|
).result
|