Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
Loading items

Target

Select target project
  • firmware/gluon
  • 0x4A6F/gluon
  • patrick/gluon
3 results
Select Git revision
Loading items
Show changes
Showing
with 836 additions and 304 deletions
#!/bin/sh #!/bin/sh
exec uci commit uci -q batch <<-EOF
delete gluon.core.reconfigure
commit
EOF
# New config is saved, we can delete the old one
rm -f /etc/config/*_gluon-old
#!/bin/sh #!/bin/sh
# shellcheck disable=SC1091
. /lib/functions.sh . /lib/functions.sh
. ../netifd-proto.sh . ../netifd-proto.sh
init_proto "$@" init_proto "$@"
proto_gluon_mesh_init_config() { proto_gluon_mesh_init_config() {
proto_config_add_boolean fixed_mtu proto_config_add_boolean fixed_mtu
proto_config_add_boolean transitive
} }
proto_gluon_mesh_setup() { proto_gluon_mesh_setup() {
export CONFIG="$1" export CONFIG="$1"
export IFNAME="$2" export IFNAME="$2"
local fixed_mtu transitive local fixed_mtu
json_get_vars fixed_mtu transitive json_get_vars fixed_mtu
export FIXED_MTU="${fixed_mtu:-0}" export FIXED_MTU="${fixed_mtu:-0}"
export TRANSITIVE="${transitive:-0}"
for script in /lib/gluon/core/mesh/setup.d/*; do for script in /lib/gluon/core/mesh/setup.d/*; do
[ ! -x "$script" ] || "$script" [ ! -x "$script" ] || "$script"
...@@ -27,7 +27,6 @@ proto_gluon_mesh_setup() { ...@@ -27,7 +27,6 @@ proto_gluon_mesh_setup() {
proto_add_data proto_add_data
json_add_boolean fixed_mtu "$FIXED_MTU" json_add_boolean fixed_mtu "$FIXED_MTU"
json_add_boolean transitive "$TRANSITIVE"
[ "$IFNAME" != 'br-wan' ] && json_add_string zone 'mesh' [ "$IFNAME" != 'br-wan' ] && json_add_string zone 'mesh'
proto_close_data proto_close_data
proto_send_update "$CONFIG" proto_send_update "$CONFIG"
......
#!/bin/sh #!/bin/sh
# shellcheck disable=SC1091
. /lib/functions.sh . /lib/functions.sh
. ../netifd-proto.sh . ../netifd-proto.sh
init_proto "$@" init_proto "$@"
proto_gluon_wired_init_config() { proto_gluon_wired_init_config() {
proto_config_add_boolean transitive
proto_config_add_int index proto_config_add_int index
proto_config_add_boolean vxlan
proto_config_add_string vxpeer6addr
} }
xor2() { xor2() {
...@@ -14,8 +17,27 @@ xor2() { ...@@ -14,8 +17,27 @@ xor2() {
echo -n "${1:1:1}" | tr '0123456789abcdef' '23016745ab89efcd' echo -n "${1:1:1}" | tr '0123456789abcdef' '23016745ab89efcd'
} }
is_layer3_device () {
local addrlen
addrlen="$(cat "/sys/class/net/$1/addr_len")"
test "$addrlen" -eq 0
}
# shellcheck disable=SC2086
interface_linklocal() { interface_linklocal() {
local macaddr="$(ubus call network.device status '{"name": "'"$1"'"}' | jsonfilter -e '@.macaddr')" if is_layer3_device "$1"; then
if ! ubus call network.interface dump | \
jsonfilter -e "@.interface[@.l3_device='$1']['ipv6-address'][*].address" | \
grep -e '^fe[89ab][0-9a-f]' -m 1; then
proto_notify_error "$config" "MISSING_LL_ADDR_ON_LOWER_IFACE"
proto_block_restart "$config"
exit 1
fi
return
fi
local macaddr
macaddr="$(ubus call network.device status '{"name": "'"$1"'"}' | jsonfilter -e '@.macaddr')"
local oldIFS="$IFS"; IFS=':'; set -- $macaddr; IFS="$oldIFS" local oldIFS="$IFS"; IFS=':'; set -- $macaddr; IFS="$oldIFS"
echo "fe80::$(xor2 "$1")$2:$3ff:fe$4:$5$6" echo "fe80::$(xor2 "$1")$2:$3ff:fe$4:$5$6"
...@@ -27,15 +49,17 @@ proto_gluon_wired_setup() { ...@@ -27,15 +49,17 @@ proto_gluon_wired_setup() {
local meshif="$config" local meshif="$config"
local vxlan="$(lua -e 'print(require("gluon.site").mesh.vxlan(true))')" local index vxlan vxpeer6addr
json_get_vars index vxlan vxpeer6addr
local transitive index # default args
json_get_vars transitive index [ -z "$vxlan" ] && vxlan=1
[ -z "$vxpeer6addr" ] && vxpeer6addr='ff02::15c'
proto_init_update "$ifname" 1 proto_init_update "$ifname" 1
proto_send_update "$config" proto_send_update "$config"
if [ "$vxlan" = 'true' ]; then if [ "$vxlan" -eq 1 ]; then
meshif="vx_$config" meshif="vx_$config"
json_init json_init
...@@ -43,8 +67,9 @@ proto_gluon_wired_setup() { ...@@ -43,8 +67,9 @@ proto_gluon_wired_setup() {
[ -n "$index" ] && json_add_string macaddr "$(lua -e "print(require('gluon.util').generate_mac($index))")" [ -n "$index" ] && json_add_string macaddr "$(lua -e "print(require('gluon.util').generate_mac($index))")"
json_add_string proto 'vxlan6' json_add_string proto 'vxlan6'
json_add_string tunlink "$config" json_add_string tunlink "$config"
# ip6addr (the lower interface ip6) is used by the vxlan.sh proto
json_add_string ip6addr "$(interface_linklocal "$ifname")" json_add_string ip6addr "$(interface_linklocal "$ifname")"
json_add_string peer6addr 'ff02::15c' json_add_string peer6addr "$vxpeer6addr"
json_add_int vid "$(lua -e 'print(tonumber(require("gluon.util").domain_seed_bytes("gluon-mesh-vxlan", 3), 16))')" json_add_int vid "$(lua -e 'print(tonumber(require("gluon.util").domain_seed_bytes("gluon-mesh-vxlan", 3), 16))')"
json_add_boolean rxcsum '0' json_add_boolean rxcsum '0'
json_add_boolean txcsum '0' json_add_boolean txcsum '0'
...@@ -57,7 +82,6 @@ proto_gluon_wired_setup() { ...@@ -57,7 +82,6 @@ proto_gluon_wired_setup() {
json_add_string ifname "@${meshif}" json_add_string ifname "@${meshif}"
json_add_string proto 'gluon_mesh' json_add_string proto 'gluon_mesh'
json_add_boolean fixed_mtu 1 json_add_boolean fixed_mtu 1
[ -n "$transitive" ] && json_add_boolean transitive "$transitive"
json_close_object json_close_object
ubus call network add_dynamic "$(json_dump)" ubus call network add_dynamic "$(json_dump)"
} }
......
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"PO-Revision-Date: 2025-06-06 08:00+0200\n"
"Last-Translator: Florian Maurer <fmaurer@disroot.org>\n"
"Language-Team: German\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "Autoupdater branch"
msgstr "Autoupdater-Branch"
msgid "Domain"
msgstr "Domäne"
msgid "Firmware release"
msgstr "Firmware-Release"
msgid "Gluon version"
msgstr "Gluon-Version"
msgid "Hardware model"
msgstr "Hardware-Modell"
msgid "Hostname"
msgstr "Hostname"
msgid "MAC address"
msgstr "MAC-Adresse"
msgid "Public VPN key"
msgstr "Öffentlicher VPN-Schlüssel"
msgid "Site"
msgstr "Site"
msgid "Site version"
msgstr "Site-Version"
msgid "Switch type"
msgstr "Switch-Typ"
msgid "disabled"
msgstr "deaktiviert"
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"PO-Revision-Date: 2015-08-19 20:20+0100\n"
"Last-Translator: Bernot Tobias <tqbs@airmail.cc>\n"
"Language-Team: French\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "Domain"
msgstr ""
msgid "Firmware release"
msgstr "Version de la firmware"
msgid "Gluon version"
msgstr "Version de Gluon"
msgid "Hardware model"
msgstr "Modèle du Matériel"
msgid "Hostname"
msgstr "Nom d'hôte"
msgid "MAC address"
msgstr "Adresse MAC"
msgid "Public VPN key"
msgstr "Clé VPN publique"
msgid "Site"
msgstr "Site"
msgid "Site version"
msgstr "Version de Site"
msgid "Switch type"
msgstr ""
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Autoupdater branch"
msgstr ""
msgid "Domain"
msgstr ""
msgid "Firmware release"
msgstr ""
msgid "Gluon version"
msgstr ""
msgid "Hardware model"
msgstr ""
msgid "Hostname"
msgstr ""
msgid "MAC address"
msgstr ""
msgid "Public VPN key"
msgstr ""
msgid "Site"
msgstr ""
msgid "Site version"
msgstr ""
msgid "Switch type"
msgstr ""
msgid "disabled"
msgstr ""
local cjson = require 'cjson' local json = require 'jsonc'
local function config_error(src, ...) local function config_error(src, ...)
error(src .. ' error: ' .. string.format(...), 0) error(src .. ' error: ' .. string.format(...), 0)
...@@ -7,20 +7,12 @@ end ...@@ -7,20 +7,12 @@ end
local has_domains = (os.execute('ls -d "$IPKG_INSTROOT"/lib/gluon/domains/ >/dev/null 2>&1') == 0) local has_domains = (os.execute('ls -d "$IPKG_INSTROOT"/lib/gluon/domains/ >/dev/null 2>&1') == 0)
local function load_json(filename)
local f = assert(io.open(filename))
local json = cjson.decode(f:read('*a'))
f:close()
return json
end
local function get_domains() local function get_domains()
local domains = {} local domains = {}
local dirs = io.popen("find \"$IPKG_INSTROOT\"/lib/gluon/domains/ -name '*.json'") local dirs = io.popen("find \"$IPKG_INSTROOT\"/lib/gluon/domains/ -name '*.json'")
for filename in dirs:lines() do for filename in dirs:lines() do
local name = string.match(filename, '([^/]+).json$') local name = string.match(filename, '([^/]+).json$')
domains[name] = load_json(filename) domains[name] = assert(json.load(filename))
end end
dirs:close() dirs:close()
...@@ -63,8 +55,20 @@ local function merge(a, b) ...@@ -63,8 +55,20 @@ local function merge(a, b)
return m return m
end end
local function contains(table, val)
for i=1,#table do
if table[i] == val then
return true
end
end
return false
end
local function path_to_string(path) local function path_to_string(path)
if path.is_value then
return path.label
end
return table.concat(path, '.') return table.concat(path, '.')
end end
...@@ -104,6 +108,10 @@ local function domain_src() ...@@ -104,6 +108,10 @@ local function domain_src()
end end
local function conf_src(path) local function conf_src(path)
if path.is_value then
return 'Configuration'
end
local src local src
if has_domains then if has_domains then
...@@ -146,6 +154,14 @@ function M.in_domain(path) ...@@ -146,6 +154,14 @@ function M.in_domain(path)
return path return path
end end
function M.value(label, value)
return {
is_value = true,
label = label,
value = value,
}
end
function M.this_domain() function M.this_domain()
return domain_code return domain_code
end end
...@@ -179,6 +195,10 @@ function loadpath(path, base, c, ...) ...@@ -179,6 +195,10 @@ function loadpath(path, base, c, ...)
end end
local function loadvar(path) local function loadvar(path)
if path.is_value then
return path.value
end
return loadpath({}, conf, unpack(path)) return loadpath({}, conf, unpack(path))
end end
...@@ -289,6 +309,19 @@ function M.need_number(path, required) ...@@ -289,6 +309,19 @@ function M.need_number(path, required)
return need_type(path, 'number', required, 'be a number') return need_type(path, 'number', required, 'be a number')
end end
function M.need_number_range(path, min, max, required)
local val = need_type(path, 'number', required)
if not val then
return nil
end
if val < min or val > max then
var_error(path, val, "be in range [" .. min .. ", " .. max .. "]")
end
return val
end
function M.need_boolean(path, required) function M.need_boolean(path, required)
return need_type(path, 'boolean', required, 'be a boolean') return need_type(path, 'boolean', required, 'be a boolean')
end end
...@@ -345,6 +378,21 @@ function M.need_array_of(path, array, required) ...@@ -345,6 +378,21 @@ function M.need_array_of(path, array, required)
return M.need_array(path, function(e) M.need_one_of(e, array) end, required) return M.need_array(path, function(e) M.need_one_of(e, array) end, required)
end end
function M.need_array_elements_exclusive(path, a, b, required)
local val = need_type(path, 'table', required, 'be an array')
if not val then
return nil
end
if contains(val, a) and contains(val, b) then
config_error(conf_src(path),
'expected %s to contain only one of the elements %s and %s, but not both.',
path_to_string(path), format(a), format(b))
end
return val
end
function M.need_chanlist(path, channels, required) function M.need_chanlist(path, channels, required)
local valid_chanlist = check_chanlist(channels) local valid_chanlist = check_chanlist(channels)
return M.need(path, valid_chanlist, required, return M.need(path, valid_chanlist, required,
...@@ -355,7 +403,7 @@ end ...@@ -355,7 +403,7 @@ end
function M.need_domain_name(path) function M.need_domain_name(path)
M.need_string(path) M.need_string(path)
M.need(path, function(domain_name) M.need(path, function(domain_name)
local f = io.open(os.getenv('IPKG_INSTROOT') .. '/lib/gluon/domains/' .. domain_name .. '.json') local f = io.open((os.getenv('IPKG_INSTROOT') or '') .. '/lib/gluon/domains/' .. domain_name .. '.json')
if not f then return false end if not f then return false end
f:close() f:close()
return true return true
...@@ -378,7 +426,7 @@ end ...@@ -378,7 +426,7 @@ end
local check = setfenv(assert(loadfile()), M) local check = setfenv(assert(loadfile()), M)
site = load_json(os.getenv('IPKG_INSTROOT') .. '/lib/gluon/site.json') site = assert(json.load((os.getenv('IPKG_INSTROOT') or '') .. '/lib/gluon/site.json'))
local ok, err = pcall(function() local ok, err = pcall(function()
if has_domains then if has_domains then
......
#!/usr/bin/lua
local sysconfig = require 'gluon.sysconfig'
local unistd = require 'posix.unistd'
if unistd.access('/lib/gluon/version/core') and not sysconfig.gluon_version then
-- This isn't an initial upgrade, so set gluon_version
sysconfig.gluon_version = ''
end
#!/usr/bin/lua
local uci = require('simple-uci').cursor()
-- Migrate system section
local system = uci:get_all('system_gluon-old', '@system[0]')
if system then
uci:tset('system', '@system[0]', system)
end
-- Migrate ntp section
local ntp = uci:get_all('system_gluon-old', 'ntp')
if ntp then
uci:tset('system', 'ntp', ntp)
end
-- Migrate gpio_switch sections
--
-- Only the value is copied from the old config, so updates to names and
-- pins are preserved
uci:foreach('system', 'gpio_switch', function(s)
local name = s['.name']
local value = uci:get('system_gluon-old', name, 'value')
if value then
uci:set('system', name, 'value', value)
end
end)
-- No other sections are migrated, so updated LED and RSSI configs can take effect
uci:save('system')
#!/usr/bin/lua
local unistd = require 'posix.unistd'
if not unistd.access('/lib/gluon/domains/') then
return
end
local function domain_exists(domain)
return unistd.access('/lib/gluon/domains/' .. domain .. '.json') == 0
end
local uci = require('simple-uci').cursor()
local domain = uci:get('gluon', 'core', 'switch_domain')
if domain and not domain_exists(domain) then
io.stderr:write(
string.format("Warning: invalid mesh domain switch to '%s' configured, not switching\n", domain)
)
domain = nil
end
if not domain then
domain = uci:get('gluon', 'core', 'domain')
end
if domain and not domain_exists(domain) then
io.stderr:write(
string.format("Warning: invalid mesh domain '%s' configured, resetting to default...\n", domain)
)
domain = nil
end
if not domain then
-- We can't use gluon.site yet, as it depends on gluon.core.domain to be set
local json = require 'jsonc'
local site = assert(json.load('/lib/gluon/site.json'))
domain = site.default_domain
end
uci:set('gluon', 'core', 'domain', domain)
uci:delete('gluon', 'core', 'switch_domain')
uci:save('gluon')
#!/usr/bin/lua
local unistd = require 'posix.unistd'
if not unistd.access('/lib/gluon/domains/') then
return
end
local uci = require('simple-uci').cursor()
local domain = uci:get('gluon', 'core', 'domain')
if domain and not unistd.access('/lib/gluon/domains/' .. domain .. '.json') then
io.stderr:write(string.format("Warning: invalid mesh domain '%s' configured, resetting to default...\n", domain))
domain = nil
end
if domain then return end
-- We can't use gluon.site yet, as it depends on gluon.core.domain to be set
local json = require 'jsonc'
local site = assert(json.load('/lib/gluon/site.json'))
uci:set('gluon', 'core', 'domain', site.default_domain)
uci:commit('gluon')
...@@ -8,66 +8,167 @@ if sysconfig.primary_mac then ...@@ -8,66 +8,167 @@ if sysconfig.primary_mac then
end end
local util = require 'gluon.util' local json = require 'jsonc'
local platform = require 'gluon.platform' local platform = require 'gluon.platform'
local util = require 'gluon.util'
local board_data = json.load('/etc/board.json')
local network_data = (board_data or {}).network
local function read(...)
local addr = util.readfile(string.format(...))
if addr then
return util.trim(addr)
end
end
local function get_netdev_addr(ifname)
return read('/sys/class/net/%s/address', ifname)
end
local function strip_vlan(ifname)
return (ifname:gsub('%..*', ''))
end
local function netdev(ifname)
return function()
return get_netdev_addr(ifname)
end
end
local function phy(index)
return function()
return read('/sys/class/ieee80211/phy%d/macaddress', index)
end
end
local function interface(name)
return function()
local ifdata = network_data[name] or {}
if ifdata.macaddr then
return ifdata.macaddr
elseif ifdata.ifname then
return get_netdev_addr(strip_vlan(ifdata.ifname))
end
end
end
local function label_mac()
return function()
local mac = util.exec('/lib/gluon/label_mac.sh')
if mac == nil then return nil end
mac = util.trim(mac)
if string.len(mac) ~= 17 then return nil end
local try_files = { return mac
'/sys/class/net/eth0/address' end
end
-- Entries are matched in the order they are listed
local primary_addrs = {
{interface('lan'), {
{'ath79', 'generic', {
'glinet,gl-ar750s-nor',
'ocedo,raccoon',
'tplink,archer-a7-v5',
'tplink,archer-c2-v3',
'tplink,archer-d50-v1',
}},
{'brcm2708'},
{'ipq40xx', 'generic', {
'avm,fritzbox-4040',
'meraki,mr33',
'plasmacloud,pa1200',
'plasmacloud,pa2200',
}},
{'ipq806x', 'generic', {
'netgear,r7800',
}},
{'lantiq', 'xrx200', {
'arcadyan,vgv7510kw22-nor',
}},
{'lantiq', 'xway', {
'netgear,dgn3500b',
}},
{'mediatek', 'filogic', {
'asus,tuf-ax4200',
'asus,tuf-ax6000',
}},
{'ramips', 'mt7620', {
'netgear,ex3700',
'tplink,archer-c2-v1',
'tplink,archer-c20-v1',
'tplink,archer-c20i',
'tplink,archer-c50-v1',
}},
{'ramips', 'mt76x8', {
'xiaomi,mi-router-4a-100m',
}},
{'rockchip', 'armv8', {
'friendlyarm,nanopi-r2s',
'friendlyarm,nanopi-r3s',
'friendlyarm,nanopi-r4s',
}},
{'x86'},
}},
{interface('wan'), {
{'ipq40xx', 'generic', {
'linksys,ea6350v3',
'openmesh,a42',
'openmesh,a62',
}},
{'kirkwood', 'generic', {
'linksys,e4200-v2',
'linksys,ea4500',
}},
{'mpc85xx', 'p1020', {
'aerohive,hiveap-330',
'ocedo,panda',
}},
{'mpc85xx', 'p1010', {
'enterasys,ws-ap3715i',
}},
{'ramips', 'mt7620', {
'xiaomi,miwifi-mini',
'asus,rt-ac51u',
}},
}},
{phy(1), {
{'ramips', 'mt7621', {
'dlink,dir-860l-b1',
}},
}},
-- label-mac-device default
{label_mac(), {
{}, -- matches everything
}},
-- phy0 default
{phy(0), {
{}, -- matches everything
}},
-- eth0 fallback when phy0 does not exist
{netdev('eth0'), {
{}, -- matches everything
}},
} }
if not (
util.contains({'x86', 'brcm2708'}, platform.get_target()) or
platform.match('ar71xx', 'mikrotik')
) then
table.insert(try_files, 1, '/sys/class/ieee80211/phy0/macaddress')
end
if platform.match('ar71xx', 'generic', {'tl-wdr3600', 'tl-wdr4300',
'tl-wr902ac-v1'}) then
table.insert(try_files, 1, '/sys/class/ieee80211/phy1/macaddress')
elseif platform.match('ar71xx', 'generic', {'a40', 'a60',
'archer-c25-v1',
'archer-c7-v4', 'archer-c7-v5',
'carambola2',
'koala',
'mr600', 'mr600v2',
'mr900', 'mr900v2',
'mr1750', 'mr1750v2',
'om2p', 'om2pv2', 'om2pv4',
'om2p-hs', 'om2p-hsv2', 'om2p-hsv3',
'om2p-hsv4',
'om2p-lc',
'om5p', 'om5p-an',
'om5p-ac', 'om5p-acv2',
'unifi-outdoor-plus',
'unifiac-lite', 'unifiac-pro'}) then
table.insert(try_files, 1, '/sys/class/net/eth0/address')
elseif platform.match('ar71xx', 'generic', {'archer-c5', 'archer-c58-v1',
'archer-c59-v1', 'archer-c60-v1',
'archer-c7'}) then
table.insert(try_files, 1, '/sys/class/net/eth1/address')
elseif platform.match('ar71xx', 'nand', {'hiveap-121'}) then
table.insert(try_files, 1, '/sys/class/net/eth0/address')
elseif platform.match('ipq40xx', nil, {'avm,fritzbox-4040',
'openmesh,a42', 'openmesh,a62'}) then
table.insert(try_files, 1, '/sys/class/net/eth0/address')
elseif platform.match('ipq806x', nil, {'netgear,r7800'}) then
table.insert(try_files, 1, '/sys/class/net/eth1/address')
elseif platform.match('mpc85xx', 'p1020', {'aerohive,hiveap-330'}) then
table.insert(try_files, 1, '/sys/class/net/eth0/address')
elseif platform.match('ramips', 'mt7620', {'miwifi-mini'}) then
table.insert(try_files, 1, '/sys/class/net/eth0/address')
elseif platform.match('ramips', 'mt7621', {'dir-860l-b1'}) then
table.insert(try_files, 1, '/sys/class/ieee80211/phy1/macaddress')
end
for _, file in ipairs(try_files) do
local addr = util.readfile(file)
for _, matcher in ipairs(primary_addrs) do
local f, matches = unpack(matcher)
for _, match in ipairs(matches) do
if platform.match(unpack(match)) then
local addr = f()
if addr then if addr then
sysconfig.primary_mac = util.trim(addr) sysconfig.primary_mac = addr:lower()
break return
end
end end
end end
end
error('no primary MAC address found')
#!/usr/bin/lua #!/usr/bin/lua
local sysconfig = require 'gluon.sysconfig'
-- Are we already set up?
if sysconfig.lan_ifname or sysconfig.wan_ifname then
os.exit(0)
end
local platform = require 'gluon.platform' local platform = require 'gluon.platform'
local site = require 'gluon.site' local sysconfig = require 'gluon.sysconfig'
local json = require 'jsonc'
local uci = require('simple-uci').cursor() local uci = require('simple-uci').cursor()
local unistd = require 'posix.unistd' local unistd = require 'posix.unistd'
local board_data = json.load('/etc/board.json')
local network_data = (board_data or {}).network
local function iface_exists(ifaces) local function iface_exists(ifaces)
if not ifaces then return nil end if not ifaces then return nil end
local ifnames = table.concat(ifaces, ' ')
for iface in ifaces:gmatch('%S+') do for _, iface in ipairs(ifaces) do
if unistd.access('/sys/class/net/' .. iface:gsub('%..*$', '')) then if unistd.access('/sys/class/net/' .. iface:gsub('%..*$', '')) then
return ifaces return ifnames
end end
end end
end end
local lan_data = network_data.lan or {}
local wan_data = network_data.wan or {}
local lan_ifname = iface_exists(uci:get('network', 'lan', 'ifname')) local lan_interfaces = lan_data.ports
local wan_ifname = iface_exists(uci:get('network', 'wan', 'ifname')) local wan_interfaces = wan_data.ports
-- In case we have a single port for either WAN or LAN,
-- add it to the respective empty table, as devices and
-- ports is XOR in board.json
if lan_data.device ~= nil then
lan_interfaces = {lan_data.device}
end
if wan_data.device ~= nil then
wan_interfaces = {wan_data.device}
end
if platform.match('ar71xx', 'generic', { local lan_ifname = iface_exists(lan_interfaces)
'cpe210', local wan_ifname = iface_exists(wan_interfaces)
'cpe510',
'wbs210', if platform.match('ath79', 'generic', {
'wbs510', 'dlink,dap-2695-a1',
'airgateway', 'tplink,cpe210-v1',
'nanostation-m', 'tplink,cpe210-v2',
'nanostation-m-xw', 'tplink,cpe510-v1',
'unifi-outdoor-plus', 'tplink,wbs210-v1',
'uap-pro', 'tplink,wbs210-v2',
'unifiac-pro', 'tplink,wbs510-v1',
'ubnt,nanostation-m-xw',
'ubnt,unifi-ap-pro',
}) then }) then
lan_ifname, wan_ifname = wan_ifname, lan_ifname lan_ifname, wan_ifname = wan_ifname, lan_ifname
elseif platform.match('ath79', 'generic', {
'ubnt,unifi-ap-outdoor-plus',
}) then
-- Temporary solution to separate interfaces in bridged default setup
lan_ifname, wan_ifname = 'eth0', 'eth1'
elseif platform.match('ath79', 'generic', {
'ubnt,unifiac-mesh-pro',
'ubnt,unifiac-pro',
}) then
lan_ifname, wan_ifname = 'eth0.2', 'eth0.1'
elseif platform.match('ipq40xx', 'generic', {
'avm,fritzbox-7530',
}) then
lan_ifname, wan_ifname = 'lan2 lan3 lan4', 'lan1'
elseif platform.match('ipq806x', 'generic', {
'ubnt,unifi-ac-hd',
}) then
lan_ifname, wan_ifname = 'eth1', 'eth0'
elseif platform.match('ramips', 'mt7621', {
'netgear,wac104',
}) then
lan_ifname, wan_ifname = 'lan2 lan3 lan4', 'lan1'
elseif platform.match('ramips', 'mt7621', {
'tplink,eap615-wall-v1',
}) then
lan_ifname, wan_ifname = 'lan1 lan2 lan3', 'lan0'
elseif platform.match('lantiq', 'xrx200', {
'arcadyan,vgv7510kw22-nor',
}) then
lan_ifname, wan_ifname = 'lan1 lan2 lan3 lan4', 'wan'
end end
if wan_ifname and lan_ifname then if wan_ifname and lan_ifname then
sysconfig.wan_ifname = wan_ifname sysconfig.wan_ifname = wan_ifname
sysconfig.lan_ifname = lan_ifname sysconfig.lan_ifname = lan_ifname
sysconfig.single_ifname = nil
else else
local single_ifname = lan_ifname or wan_ifname sysconfig.wan_ifname = nil
if site.single_as_lan(false) then sysconfig.lan_ifname = nil
sysconfig.lan_ifname = single_ifname sysconfig.single_ifname = lan_ifname or wan_ifname
else
sysconfig.wan_ifname = single_ifname
end
end end
-- Delete all UCI device sections of type 'bridge'
-- as well as the ones starting with 'br-'.
-- Preserve all others to apply MAC address stored in UCI
uci:delete_all('network', 'device', function(dev)
return (dev.type == 'bridge' or dev.name:match('^br-'))
end)
uci:delete('network', 'lan') uci:delete_all('network', 'interface')
uci:delete('network', 'wan')
uci:save('network') uci:save('network')
#!/usr/bin/lua
local site = require 'gluon.site'
local sysconfig = require 'gluon.sysconfig'
local uci = require('simple-uci').cursor()
local util = require 'gluon.util'
-- Defaults from site.conf
local roles = {
lan = site.interfaces.lan.default_roles({'client'}),
wan = site.interfaces.wan.default_roles({'uplink'}),
}
roles.single = site.interfaces.single.default_roles({unpack(roles.wan)})
-- Migration of single to WAN/LAN or vice-versa (an interface was added or removed)
-- We identify the WAN with the single interface in this case
--
-- These settings only take effect when the section that is the target of the
-- migration does not exist yet.
if uci:get('gluon', 'iface_wan') then
roles.single = uci:get_list('gluon', 'iface_wan', 'role')
end
if uci:get('gluon', 'iface_single') then
roles.wan = uci:get_list('gluon', 'iface_single', 'role')
roles.lan = uci:get_list('gluon', 'iface_single', 'role')
end
-- Non-existing interfaces are nil, so they will not be added to the table
local interfaces = {
lan = sysconfig.lan_ifname,
wan = sysconfig.wan_ifname,
single = sysconfig.single_ifname,
}
for iface in pairs(interfaces) do
local section_name = 'iface_' .. iface
if not uci:get('gluon', section_name) then
uci:section('gluon', 'interface', section_name, {
-- / prefix refers to sysconfig ifnames
name = '/' .. iface,
role = roles[iface],
})
end
end
-- Fix invalid role configurations
uci:foreach('gluon', 'interface', function(interface)
local function has_role(role)
if interface.role == nil then
return false
end
return util.contains(interface.role, role)
end
if has_role('client') and (has_role('mesh') or has_role('uplink')) then
-- remove 'client' role
util.remove_from_set(interface.role, 'client')
uci:set('gluon', interface['.name'], 'role', interface.role)
end
end)
uci:save('gluon')
#!/usr/bin/lua #!/usr/bin/lua
local uci = require('simple-uci').cursor() local uci = require('simple-uci').cursor()
local sysconfig = require 'gluon.sysconfig' local sysconfig = require 'gluon.sysconfig'
local util = require 'gluon.util'
local json = require 'jsonc'
local function get_network_mac(name)
local board_data = json.load('/etc/board.json')
local network_data = (board_data or {}).network
if network_data == nil then
return nil
end
local ifdata = network_data[name] or {}
return ifdata.macaddr
end
local wan = uci:get_all('network_gluon-old', 'wan') or {}
local wan6 = uci:get_all('network_gluon-old', 'wan6') or {}
uci:section('network', 'interface', 'loopback', {
ifname = 'lo',
proto = 'static',
ipaddr = '127.0.0.1',
netmask = '255.0.0.0',
})
local wan_proto = 'dhcp'
if sysconfig.gluon_version and wan.proto ~= nil then
-- Only restore WAN proto in case this is an upgrade
wan_proto = wan.proto
end
uci:section('network', 'interface', 'wan', { uci:section('network', 'interface', 'wan', {
ifname = sysconfig.wan_ifname, proto = wan_proto,
ipaddr = wan.ipaddr,
netmask = wan.netmask,
gateway = wan.gateway,
macaddr = get_network_mac('wan'),
ifname = util.get_role_interfaces(uci, 'uplink'),
type = 'bridge', type = 'bridge',
igmp_snooping = true, igmp_snooping = true,
multicast_querier = false, multicast_querier = false,
...@@ -13,12 +49,10 @@ uci:section('network', 'interface', 'wan', { ...@@ -13,12 +49,10 @@ uci:section('network', 'interface', 'wan', {
auto = true, auto = true,
}) })
if not uci:get('network', 'wan', 'proto') then
uci:set('network', 'wan', 'proto', 'dhcp')
end
uci:section('network', 'interface', 'wan6', { uci:section('network', 'interface', 'wan6', {
proto = wan6.proto or 'dhcpv6',
ip6addr = wan6.ip6addr,
ip6gw = wan6.ip6gw,
ifname = 'br-wan', ifname = 'br-wan',
peerdns = false, peerdns = false,
ip6table = 1, ip6table = 1,
...@@ -26,11 +60,6 @@ uci:section('network', 'interface', 'wan6', { ...@@ -26,11 +60,6 @@ uci:section('network', 'interface', 'wan6', {
reqprefix = 'no', reqprefix = 'no',
}) })
if not uci:get('network', 'wan6', 'proto') then
uci:set('network', 'wan6', 'proto', 'dhcpv6')
end
uci:section('network', 'rule6', 'wan6_lookup', { uci:section('network', 'rule6', 'wan6_lookup', {
mark = '0x01/0x01', mark = '0x01/0x01',
lookup = 1, lookup = 1,
......
#!/usr/bin/lua
local platform = require 'gluon.platform'
local uci = require('simple-uci').cursor()
local switch_vlans = {
-- device identifier, lan ports, wan ports
["ubnt,unifiac-mesh-pro"] = {"3 0t", "2 0t"},
["ubnt,unifiac-pro"] = {"2 0t", "3 0t"},
}
local board_name = platform.get_board_name()
local assignments = switch_vlans[board_name]
if not platform.match('ath79', 'generic') or not assignments then
return
end
uci:delete_all('network', 'switch_vlan')
for vlan, ports in ipairs(assignments) do
uci:section("network", "switch_vlan", nil, {
device = "switch0",
vlan = vlan,
ports = ports,
})
end
uci:save('network')
...@@ -13,6 +13,7 @@ end ...@@ -13,6 +13,7 @@ end
local sysconfig = require 'gluon.sysconfig' local sysconfig = require 'gluon.sysconfig'
local platform = require 'gluon.platform' local platform = require 'gluon.platform'
local wireless = require 'gluon.wireless'
local config = site.wifi5.outdoors('preset') local config = site.wifi5.outdoors('preset')
local outdoor local outdoor
...@@ -22,7 +23,7 @@ if sysconfig.gluon_version then ...@@ -22,7 +23,7 @@ if sysconfig.gluon_version then
outdoor = false outdoor = false
elseif config == 'preset' then elseif config == 'preset' then
-- enable outdoor mode through presets on new installs -- enable outdoor mode through presets on new installs
outdoor = platform.is_outdoor_device() outdoor = platform.is_outdoor_device() and wireless.device_uses_11a(uci)
else else
-- enable/disable outdoor mode unconditionally on new installs -- enable/disable outdoor mode unconditionally on new installs
outdoor = config outdoor = config
......
#!/usr/bin/lua
local wireless = require 'gluon.wireless'
local uci = require('simple-uci').cursor()
local preserve_channels = wireless.preserve_channels(uci)
uci:section('gluon', 'wireless', 'wireless', {
preserve_channels = preserve_channels or false,
})
uci:save('gluon')
#!/usr/bin/lua #!/usr/bin/lua
local util = require 'gluon.util' local util = require 'gluon.util'
local wireless = require 'gluon.wireless'
local site = require 'gluon.site' local site = require 'gluon.site'
local sysconfig = require 'gluon.sysconfig' local sysconfig = require 'gluon.sysconfig'
local iwinfo = require 'iwinfo' local iwinfo = require 'iwinfo'
...@@ -16,8 +17,8 @@ if not sysconfig.gluon_version then ...@@ -16,8 +17,8 @@ if not sysconfig.gluon_version then
-- capable of operating in the 2.4 GHz and 5 GHz band need -- capable of operating in the 2.4 GHz and 5 GHz band need
-- to be distributed evenly. -- to be distributed evenly.
local radio_band_count = {band24=0, band5=0} local radio_band_count = {band24=0, band5=0}
util.foreach_radio(uci, function(radio) wireless.foreach_radio(uci, function(radio)
local hwmodes = iwinfo.nl80211.hwmodelist(util.find_phy(radio)) local hwmodes = iwinfo.nl80211.hwmodelist(wireless.find_phy(radio))
if hwmodes.g and not (hwmodes.a or hwmodes.ac) then if hwmodes.g and not (hwmodes.a or hwmodes.ac) then
-- 2.4 GHz -- 2.4 GHz
radio_band_count["band24"] = radio_band_count["band24"] + 1 radio_band_count["band24"] = radio_band_count["band24"] + 1
...@@ -29,19 +30,19 @@ if not sysconfig.gluon_version then ...@@ -29,19 +30,19 @@ if not sysconfig.gluon_version then
-- Use the number of all fixed 2.4G GHz and 5 GHz radios to -- Use the number of all fixed 2.4G GHz and 5 GHz radios to
-- distribute dualband radios in this step. -- distribute dualband radios in this step.
util.foreach_radio(uci, function(radio) wireless.foreach_radio(uci, function(radio)
local radio_name = radio['.name'] local radio_name = radio['.name']
local hwmodes = iwinfo.nl80211.hwmodelist(util.find_phy(radio)) local hwmodes = iwinfo.nl80211.hwmodelist(wireless.find_phy(radio))
if (hwmodes.a or hwmodes.ac) and hwmodes.g then if (hwmodes.a or hwmodes.ac) and hwmodes.g then
-- Dualband radio -- Dualband radio
if radio_band_count["band24"] <= radio_band_count["band5"] then if radio_band_count["band24"] <= radio_band_count["band5"] then
-- Assign radio to 2.4GHz band -- Assign radio to 2.4GHz band
radio_band_count["band24"] = radio_band_count["band24"] + 1 radio_band_count["band24"] = radio_band_count["band24"] + 1
uci:set('wireless', radio_name, 'hwmode', '11g') uci:set('wireless', radio_name, 'band', '2g')
else else
-- Assign radio to 5GHz band -- Assign radio to 5GHz band
radio_band_count["band5"] = radio_band_count["band5"] + 1 radio_band_count["band5"] = radio_band_count["band5"] + 1
uci:set('wireless', radio_name, 'hwmode', '11a') uci:set('wireless', radio_name, 'band', '5g')
end end
end end
end) end)
...@@ -52,27 +53,31 @@ local function is_outdoor() ...@@ -52,27 +53,31 @@ local function is_outdoor()
end end
local function get_channel(radio, config) local function get_channel(radio, config)
local channel if radio.band == '5g' and is_outdoor() then
if uci:get_first('gluon-core', 'wireless', 'preserve_channels') then
-- preserved channel always wins
channel = radio.channel
elseif (radio.hwmode == '11a' or radio.hwmode == '11na') and is_outdoor() then
-- actual channel will be picked and probed from chanlist -- actual channel will be picked and probed from chanlist
channel = 'auto' return 'auto'
end end
return channel or config.channel() return config.channel()
end end
local function get_htmode(radio) local function get_htmode(radio)
if (radio.hwmode == '11a' or radio.hwmode == '11na') and is_outdoor() then if wireless.preserve_channels(uci) then
return radio.htmode
end
if radio.band == '5g' and is_outdoor() then
local outdoor_htmode = uci:get('gluon', 'wireless', 'outdoor_' .. radio['.name'] .. '_htmode') local outdoor_htmode = uci:get('gluon', 'wireless', 'outdoor_' .. radio['.name'] .. '_htmode')
if outdoor_htmode ~= nil then if outdoor_htmode ~= nil then
return outdoor_htmode return outdoor_htmode
end end
end end
local phy = util.find_phy(radio) local phy = wireless.find_phy(radio)
if iwinfo.nl80211.hwmodelist(phy).ax then
return 'HE20'
end
if iwinfo.nl80211.hwmodelist(phy).ac then if iwinfo.nl80211.hwmodelist(phy).ac then
return 'VHT20' return 'VHT20'
end end
...@@ -81,66 +86,27 @@ local function get_htmode(radio) ...@@ -81,66 +86,27 @@ local function get_htmode(radio)
end end
local function is_disabled(name) local function is_disabled(name)
if uci:get('wireless', name) then if not uci:get('wireless', name) then
return uci:get_bool('wireless', name, 'disabled') return nil
else
return false
end end
return uci:get_bool('wireless', name, 'disabled')
end end
-- Returns the first argument that is not nil; don't call without any non-nil arguments! -- Returns the first argument that is not nil; don't call without any non-nil arguments!
local function first_non_nil(first, ...) local function first_non_nil(first, ...)
if first ~= nil then if first ~= nil then
return first return first
else
return first_non_nil(...)
end end
return first_non_nil(...)
end end
local function configure_ibss(config, radio, index, suffix, disabled) local function delete_ibss(radio_name)
local radio_name = radio['.name']
local name = 'ibss_' .. radio_name local name = 'ibss_' .. radio_name
uci:delete('network', name)
uci:delete('network', name .. '_vlan')
uci:delete('wireless', name) uci:delete('wireless', name)
if not config then
return
end
local macaddr = util.get_wlan_mac(uci, radio, index, 3)
if not macaddr then
return
end
if config.vlan then
uci:section('network', 'interface', name, {
proto = 'none',
})
uci:section('network', 'interface', name .. '_vlan', {
ifname = '@' .. name .. '.' .. config.vlan,
proto = 'gluon_mesh',
})
else
uci:section('network', 'interface', name, {
proto = 'gluon_mesh',
})
end
uci:section('wireless', 'wifi-iface', name, {
device = radio_name,
network = name,
mode = 'adhoc',
ssid = config.ssid,
bssid = config.bssid,
macaddr = macaddr,
mcast_rate = config.mcast_rate,
ifname = suffix and 'ibss' .. suffix,
disabled = disabled,
})
end end
local function configure_mesh(config, radio, index, suffix, disabled) local function configure_mesh(config, radio, index, suffix, disabled)
...@@ -150,15 +116,13 @@ local function configure_mesh(config, radio, index, suffix, disabled) ...@@ -150,15 +116,13 @@ local function configure_mesh(config, radio, index, suffix, disabled)
local macfilter = uci:get('wireless', name, 'macfilter') local macfilter = uci:get('wireless', name, 'macfilter')
local maclist = uci:get('wireless', name, 'maclist') local maclist = uci:get('wireless', name, 'maclist')
uci:delete('network', name)
uci:delete('network', name .. '_vlan')
uci:delete('wireless', name) uci:delete('wireless', name)
if not config then if not config then
return return
end end
local macaddr = util.get_wlan_mac(uci, radio, index, 2) local macaddr = wireless.get_wlan_mac(uci, radio, index, 2)
if not macaddr then if not macaddr then
return return
end end
...@@ -174,6 +138,7 @@ local function configure_mesh(config, radio, index, suffix, disabled) ...@@ -174,6 +138,7 @@ local function configure_mesh(config, radio, index, suffix, disabled)
mesh_id = config.id, mesh_id = config.id,
mesh_fwding = false, mesh_fwding = false,
macaddr = macaddr, macaddr = macaddr,
basic_rate = { config.mcast_rate },
mcast_rate = config.mcast_rate, mcast_rate = config.mcast_rate,
ifname = suffix and 'mesh' .. suffix, ifname = suffix and 'mesh' .. suffix,
disabled = disabled, disabled = disabled,
...@@ -190,7 +155,7 @@ local function fixup_wan(radio, index) ...@@ -190,7 +155,7 @@ local function fixup_wan(radio, index)
return return
end end
local macaddr = util.get_wlan_mac(uci, radio, index, 4) local macaddr = wireless.get_wlan_mac(uci, radio, index, 4)
if not macaddr then if not macaddr then
return return
end end
...@@ -198,32 +163,38 @@ local function fixup_wan(radio, index) ...@@ -198,32 +163,38 @@ local function fixup_wan(radio, index)
uci:set('wireless', name, 'macaddr', macaddr) uci:set('wireless', name, 'macaddr', macaddr)
end end
local function configure_mesh_wireless(radio, index, config) local function configure_mesh_wireless(radio, index, config, disabled)
local radio_name = radio['.name'] local radio_name = radio['.name']
local suffix = radio_name:match('^radio(%d+)$') local suffix = radio_name:match('^radio(%d+)$')
local ibss_disabled = is_disabled('ibss_' .. radio_name)
local mesh_disabled = is_disabled('mesh_' .. radio_name)
configure_ibss(config.ibss(), radio, index, suffix,
first_non_nil(
ibss_disabled,
mesh_disabled,
config.ibss.disabled(false)
)
)
configure_mesh(config.mesh(), radio, index, suffix, configure_mesh(config.mesh(), radio, index, suffix,
first_non_nil( first_non_nil(
mesh_disabled, disabled,
ibss_disabled, is_disabled('mesh_' .. radio_name),
config.mesh.disabled(false) config.mesh.disabled(false)
) )
) )
end end
util.foreach_radio(uci, function(radio, index, config) local function set_channels(radio, radio_name, config)
if wireless.preserve_channels(uci) then
return
end
local channel = get_channel(radio, config)
uci:set('wireless', radio_name, 'channel', channel)
local chanlist
if radio.band == '5g' and is_outdoor() then
chanlist = config.outdoor_chanlist()
end
uci:set('wireless', radio_name, 'channels', chanlist)
end
wireless.foreach_radio(uci, function(radio, index, config)
local radio_name = radio['.name'] local radio_name = radio['.name']
delete_ibss(radio_name)
if not config() then if not config() then
uci:set('wireless', radio_name, 'disabled', true) uci:set('wireless', radio_name, 'disabled', true)
return return
...@@ -234,55 +205,52 @@ util.foreach_radio(uci, function(radio, index, config) ...@@ -234,55 +205,52 @@ util.foreach_radio(uci, function(radio, index, config)
return return
end end
local channel = get_channel(radio, config)
local htmode = get_htmode(radio) local htmode = get_htmode(radio)
local beacon_interval = config.beacon_interval()
uci:delete('wireless', radio_name, 'disabled') uci:delete('wireless', radio_name, 'disabled')
uci:set('wireless', radio_name, 'channel', channel) set_channels(radio, radio_name, config)
uci:set('wireless', radio_name, 'htmode', htmode) uci:set('wireless', radio_name, 'htmode', htmode)
uci:set('wireless', radio_name, 'country', site.regdom()) uci:set('wireless', radio_name, 'country', site.regdom())
uci:delete('wireless', radio_name, 'supported_rates') uci:delete('wireless', radio_name, 'supported_rates')
uci:delete('wireless', radio_name, 'basic_rate') uci:delete('wireless', radio_name, 'basic_rate')
local hwmode = radio.hwmode local band = radio.band
if hwmode == '11g' or hwmode == '11ng' then if band == '2g' then
uci:set('wireless', radio_name, 'legacy_rates', false) uci:set('wireless', radio_name, 'legacy_rates', false)
configure_mesh_wireless(radio, index, config) configure_mesh_wireless(radio, index, config)
elseif (hwmode == '11a' or hwmode == '11na') then elseif (band == '5g') then
if is_outdoor() then -- ToDo: Remove in v2024.x
uci:set('wireless', radio_name, 'channels', config.outdoor_chanlist())
-- enforce outdoor channels by filtering the regdom for outdoor channels
local hostapd_options = uci:get_list('wireless', radio_name, 'hostapd_options')
util.add_to_set(hostapd_options, 'country3=0x4f')
uci:set_list('wireless', radio_name, 'hostapd_options', hostapd_options)
uci:delete('wireless', 'ibss_' .. radio_name)
uci:delete('wireless', 'mesh_' .. radio_name)
else
uci:delete('wireless', radio_name, 'channels')
local hostapd_options = uci:get_list('wireless', radio_name, 'hostapd_options') local hostapd_options = uci:get_list('wireless', radio_name, 'hostapd_options')
util.remove_from_set(hostapd_options, 'country3=0x4f') util.remove_from_set(hostapd_options, 'country3=0x4f')
uci:set_list('wireless', radio_name, 'hostapd_options', hostapd_options) uci:set_list('wireless', radio_name, 'hostapd_options', hostapd_options)
if is_outdoor() then
-- enforce outdoor channels by filtering the regdom for outdoor channels
uci:set('wireless', radio_name, 'country3', '0x4f')
configure_mesh_wireless(radio, index, config, true)
else
uci:delete('wireless', radio_name, 'country3')
configure_mesh_wireless(radio, index, config) configure_mesh_wireless(radio, index, config)
end end
end end
uci:set('wireless', radio_name, 'beacon_int', beacon_interval)
fixup_wan(radio, index) fixup_wan(radio, index)
end) end)
if uci:get('system', 'rssid_wlan0') then if uci:get('system', 'rssid_wlan0') then
if uci:get('wireless', 'mesh_radio0') then
uci:set('system', 'rssid_wlan0', 'dev', 'mesh0') uci:set('system', 'rssid_wlan0', 'dev', 'mesh0')
else uci:save('system')
uci:set('system', 'rssid_wlan0', 'dev', 'ibss0')
end end
if uci:get('system', 'rssid_wlan1') then
uci:set('system', 'rssid_wlan1', 'dev', 'mesh1')
uci:save('system') uci:save('system')
end end
......
#!/usr/bin/lua
local uci = require('simple-uci').cursor()
local platform = require 'gluon.platform'
-- This is a workaround to result in a configuration where all ports
-- on the DSA switch are connected to the same CPU interface.
--
-- See Gluon issue #3479 for details.
-- https://github.com/freifunk-gluon/gluon/issues/3479
if not platform.match('ipq806x', 'generic', {
'netgear,r7800',
'tplink,c2600',
}) then
return
end
local ports = {
'lan1',
'lan2',
'lan3',
'lan4',
'wan',
}
local cpu_conduit = 'eth0'
for _, port in ipairs(ports) do
local section_name = 'port_' .. port
uci:section('network', 'device', section_name, {
name = port,
conduit = cpu_conduit,
})
end
uci:save('network')