add swconfig support

Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
John Crispin
2023-07-10 08:28:16 +02:00
parent 2c8fb4aeb6
commit 00d0403a55
6 changed files with 134 additions and 11 deletions

View File

@@ -101,10 +101,16 @@ function discover_ports() {
for (let role, spec in capab.network) {
for (let i, ifname in spec) {
role = uc(role);
push(roles[role] = roles[role] || [], {
netdev: ifname,
let netdev = split(ifname, ':');
let port = {
netdev: netdev[0],
index: i
});
};
if (netdev[1]) {
port.swconfig = netdev[1];
port.swdev = split(ifname, ':')[0];
}
push(roles[role] = roles[role] || [], port);
}
}
@@ -132,7 +138,6 @@ function discover_ports() {
return rv;
}
/**
* @class uCentral.wiphy
* @classdesc
@@ -335,7 +340,7 @@ let ethernet = {
return matched;
},
lookup_by_interface_vlan: function(interface) {
lookup_by_interface_vlan: function(interface, raw) {
// Gather the glob patterns in all `ethernet: [ { select-ports: ... }]` specs,
// dedup them and turn them into one global regular expression pattern, then
// match this pattern against all known system ethernet ports, remember the
@@ -343,7 +348,47 @@ let ethernet = {
let globs = {};
map(interface.ethernet, eth => map(eth.select_ports, glob => globs[glob] = eth.vlan_tag));
return this.lookup(globs);
let lookup = this.lookup(globs);
if (raw)
return lookup;
let rv = {};
for (let k, v in lookup) {
/* tagged swconfig downstream ports are not allowed */
if (interface.role == 'downstream') {
if (this.swconfig && this.swconfig[k].switch && v == 'tagged')
warn('%s:%d - vlan tagging on downstream swconfig ports is not supported', this.swconfig[k].switch.name, this.swconfig[k].swconfig);
else
rv[k] = v;
continue;
}
/* resolve upstream vlans on swconfig ports */
if (this.swconfig && interface.role == 'upstream' && interface.vlan.id && this.swconfig[k].switch && v != 'un-tagged') {
rv[split(k, '.')[0] + '.' + interface.vlan.id] = 'un-tagged';
continue;
}
rv[k] = v;
}
return rv;
},
switch_by_interface_vlan: function(interface, raw) {
let ports = this.lookup_by_interface_vlan(interface, true);
let rv = { ports: "" };
let cpu_port = 0;
for (let port, tag in ports) {
if (!this.swconfig || !this.swconfig[port]?.switch) continue;
rv.name = this.swconfig[port].switch.name;
cpu_port = this.swconfig[port].switch.port;
rv.ports += ' ' + this.swconfig[port].swconfig;
if (tag != 'un-tagged')
rv.ports += 't';
}
if (!rv.name)
return null;
rv.ports = cpu_port + 't' + rv.ports;
return rv;
},
lookup_by_interface_spec: function(interface) {

View File

@@ -40,3 +40,18 @@ add network device
set network.@device[-1].name={{ s(k) }}
set network.@device[-1].macaddr={{ s(v) }}
{% endfor %}
{% for (let k, v in capab.switch): %}
add network switch
set network.@switch[-1].name={{ s(v.name) }}
set network.@switch[-1].reset={{ b(v.reset) }}
set network.@switch[-1].enable_vlan={{ b(v.enable) }}
{% endfor %}
{% for (let k, port in ethernet.ports): %}
{% if (!port.switch) continue; %}
add network switch_vlan
set network.@switch_vlan[-1].device={{ s(port.switch.name) }}
set network.@switch_vlan[-1].vlan={{ s(port.vlan) }}
set network.@switch_vlan[-1].ports={{s(port.switch.port + 't ' + port.swconfig)}}
{% endfor %}

View File

@@ -93,6 +93,9 @@
// Gather related BSS modes and ethernet ports.
let bss_modes = map(interface.ssids, ssid => ssid.bss_mode);
let eth_ports = ethernet.lookup_by_interface_vlan(interface);
let swconfig;
if (interface.role == 'upstream')
swconfig = ethernet.switch_by_interface_vlan(interface);
// If at least one station mode SSID is part of this interface then we must
// not bridge at all. Having any other SSID or any number of matching ethernet
@@ -133,7 +136,7 @@
//
if (interface.broad_band) {
include("interface/broadband.uc", { interface, name, location, eth_ports });
include("interface/broadband.uc", { interface, name, location, eth_ports, raw_ports });
return;
}
@@ -150,7 +153,7 @@
interface.type = 'bridge';
} else if (tunnel_proto != 'gre' && tunnel_proto != 'gre6')
// anything else requires a bridge-vlan
include("interface/bridge-vlan.uc", { interface, name, eth_ports, this_vid, bridgedev });
include("interface/bridge-vlan.uc", { interface, name, eth_ports, this_vid, bridgedev, swconfig });
if (interface.role == "downstream" && "wireguard-overlay" in interface.services)
dest = 'unet';

View File

@@ -56,3 +56,10 @@ set udevstats.@device[-1].name={{ s(port) }}
add_list udevstats.@device[-1].vlan={{ s(interface.vlan.id || 0) }}
{% endfor %}
{% endif %}
{% if (interface.vlan.id && swconfig): %}
add network switch_vlan
set network.@switch_vlan[-1].device={{ s(swconfig.name) }}
set network.@switch_vlan[-1].vlan={{ s(this_vid) }}
set network.@switch_vlan[-1].ports={{s(swconfig.ports)}}
{% endif %}

View File

@@ -50,6 +50,26 @@
if (!interface.vlan.id)
interface.vlan.dyn_id = next_free_vid();
/* dynamically assign vlans to all swconfig ports */
let swconfig = false;
for (let k, port in ethernet.ports) {
if (port.swconfig == null)
continue;
port.vlan = next_free_vid();
port.switch = capab.switch_ports[port.netdev];
port.netdev += '.' + port.vlan;
swconfig = true;
}
if (swconfig) {
ethernet.swconfig = {};
for (let k, port in ethernet.ports) {
if (!port.switch)
continue;
ethernet.swconfig[port.netdev] = port;
}
}
include('base.uc');
if (state.unit)

View File

@@ -36,13 +36,48 @@ else if (length(wifi))
else
capa.platform = "unknown";
if (board.switch) {
capa.switch = [];
capa.switch_ports = {};
for (let name, s in board.switch) {
let device = { name, lan: [], wan: [] };
let netdev;
for (let p in s.ports) {
if (p.device) {
netdev = p.device;
device.port = p.num;
} else if (device[p.role]) {
push(device[p.role], p.num)
}
}
if (!length(device.lan))
delete device.lan;
if (!length(device.wan))
delete device.wan;
if (netdev)
capa.switch_ports[netdev] = device;
push(capa.switch, { name, enable: s.enable, reset: s.reset });
}
}
function swconfig_ports(device, role) {
let netdev = split(device, '.')[0];
let switch_dev = capa.switch_ports[netdev];
if (!switch_dev || !switch_dev[role])
return [ device ];
let rv = [];
for (let port in switch_dev[role])
push(rv, netdev + ':' + port);
return rv;
}
capa.network = {};
macs = {};
for (let k, v in board.network) {
if (v.ports)
capa.network[k] = v.ports;
if (v.device)
capa.network[k] = [v.device];
capa.network[k] = swconfig_ports(v.device, k);
if (v.ifname)
capa.network[k] = split(replace(v.ifname, /^ */, ''), " ");
if (v.macaddr)
@@ -58,8 +93,6 @@ if (board.wifi?.country)
if (board.system?.label_macaddr)
capa.label_macaddr = board.system?.label_macaddr;
if (board.switch)
capa.switch = board.switch;
if (length(wifi))
capa.wifi = wifi;