diff --git a/docs/dev/wan.rst b/docs/dev/uplink.rst similarity index 86% rename from docs/dev/wan.rst rename to docs/dev/uplink.rst index ec9d942b22502e327e29e0842a17e047f731f107..4d48168d3de863f76b01d6536aca85cd888b3899 100644 --- a/docs/dev/wan.rst +++ b/docs/dev/uplink.rst @@ -1,5 +1,5 @@ -WAN support -=========== +Uplink support +============== As the WAN port of a node will be connected to a user's private network, it is essential that the node only uses the WAN when it is absolutely necessary. @@ -11,11 +11,12 @@ There are two cases in which the WAN port is used: After the VPN connection has been established, the node should be able to reach the mesh's DNS servers and use these for all other name resolution. -If the device does not feature a WAN port, the LAN port is configured as WAN port. -In case such a device has multiple LAN ports, all these can be used as WAN. -Devices, which feature a "hybrid" port (labelled as WAN/LAN), this port is used as WAN. - -This behavior can be reversed using the ``single_as_lan`` site.conf option. +If a device has only a single Ethernet port (or group of ports), it will be +used as an uplink port even when it is not labelled as "WAN" by default. This +behavior can be controlled using the ``interfaces.single.default_roles`` +site.conf option. It is also possible to alter the interface assignment after +installation by modifying ``/etc/config/gluon`` and running +``gluon-reconfigure``. Routing tables ~~~~~~~~~~~~~~ diff --git a/docs/features/multidomain.rst b/docs/features/multidomain.rst index 80cae0de7bda4b0bf134623a428f797fe95bca28..43f343bbb604959691caa5ea8275ef3dcd0a671a 100644 --- a/docs/features/multidomain.rst +++ b/docs/features/multidomain.rst @@ -130,9 +130,7 @@ site.conf only variables - authorized_keys - default_domain - poe_passthrough - - mesh_on_wan - - mesh_on_lan - - single_as_lan + - interfaces.*.default_roles - setup_mode.skip - autoupdater.branch - mesh_vpn.enabled diff --git a/docs/features/private-wlan.rst b/docs/features/private-wlan.rst index 3c26c8f8ec1d4a4073c1564353c2842709ceee37..41664b73b0704b70b7e54feeea8d22b3e5e4dd3c 100644 --- a/docs/features/private-wlan.rst +++ b/docs/features/private-wlan.rst @@ -1,8 +1,8 @@ Private WLAN ============ -It is possible to set up a private WLAN that bridges the WAN port and is separated from the mesh network. -Please note that you should not enable ``mesh_on_wan`` simultaneously. +It is possible to set up a private WLAN that bridges the uplink port and is separated from the mesh network. +Please note that you should not enable Wired Mesh on the uplink port at the same time. The private WLAN is encrypted using WPA2 by default. On devices with enough flash and a supported radio, WPA3 or WPA2/WPA3 mixed-mode can be used instead of WPA2. For this to work, the ``wireless-encryption-wpa3`` diff --git a/docs/features/wired-mesh.rst b/docs/features/wired-mesh.rst index 7f99c3c01362c570c8e2b8dedc2b3bab3880ed62..b48ec07260750d0895a39e17e757c60aaef75328 100644 --- a/docs/features/wired-mesh.rst +++ b/docs/features/wired-mesh.rst @@ -50,8 +50,8 @@ Configuration Both Mesh-on-WAN and Mesh-on-LAN can be configured on the "Network" page of the *Advanced settings* (if the package ``gluon-web-network`` is installed). -It is also possible to enable Mesh-on-WAN and Mesh-on-LAN by default by -adding ``mesh_on_wan = true`` and ``mesh_on_lan = true`` to ``site.conf``. +It is also possible to enable Mesh-on-WAN and Mesh-on-LAN by default by adding +the ``mesh`` role to the ``interfaces.*.default_roles`` options in site.conf. Commandline =========== diff --git a/docs/index.rst b/docs/index.rst index d8e394652d59b010934edb473ae155aa7aec7a55..72648a9afba96d071321b48f4273f1275f5de552 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -39,7 +39,7 @@ Several Freifunk communities in Germany use Gluon as the foundation of their Fre dev/hardware dev/packages dev/upgrade - dev/wan + dev/uplink dev/mac_addresses dev/site_library dev/build diff --git a/docs/user/site.rst b/docs/user/site.rst index 79e7ca1e53161f3c675608285be6fb2f62225b41..5b2e0eeb04878ecd659453930a27f05de2b877a0 100644 --- a/docs/user/site.rst +++ b/docs/user/site.rst @@ -399,17 +399,49 @@ mesh_vpn }, } -mesh_on_wan \: optional - Enables the mesh on the WAN port (``true`` or ``false``). +interfaces \: optional + Default setup for Ethernet ports. :: - mesh_on_wan = true, + interfaces = { + lan = { + default_roles = { 'client', 'mesh' }, + }, + wan = { + default_roles = { 'uplink', 'mesh' }, + }, + single = { + default_roles = { 'uplink', 'mesh' }, + }, + }, -mesh_on_lan \: optional - Enables the mesh on the LAN port (``true`` or ``false``). - :: + For devices that have two distinct Ethernet ports or port groups (often + labelled WAN and LAN), the ``lan`` and ``wan`` sections are used. When there + is only one port (group), ``single`` is used instead. + + Available interface roles: + + - ``client``: Port allows regular clients to connect to the mesh + - ``uplink``: Port is used to establish Mesh VPN connections + - ``mesh``: Wired meshing to another Gluon or Gluon-compatible node + + The ``client`` role requires exclusive control over an interface. When + the ``client`` role is assigned to an interface at the same time as other + roles (like ``'client', 'mesh'`` in the above example), the other roles take + precedence (enabling ``mesh``, but not ``client`` in the example). + + Such a default configuration still fulfills a purpose (and is in fact the + recommended way to enable "Mesh-on-LAN" by default): The "LAN interface + meshing" checkbox in the advanced network settings will only add or remove + the ``mesh`` role, so the ``client`` role must already be in the configuration + to make the LAN port a regular client interface when the checkbox is disabled. + + All interface settings are optional. If unset, the following defaults are + used: - mesh_on_lan = true, + - ``lan``: ``{ 'client' }`` + - ``wan``: ``{ 'uplink' }`` + - ``single``: Same as ``wan`` poe_passthrough \: optional Enable PoE passthrough by default on hardware with such a feature. diff --git a/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/300-gluon-client-bridge-network b/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/300-gluon-client-bridge-network index 490325cfd841c6588cf05098b0ceb9c5a8ccc8ba..3d4dbac38903fb6c24c86bd7084d22cf251837f2 100755 --- a/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/300-gluon-client-bridge-network +++ b/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/300-gluon-client-bridge-network @@ -6,26 +6,9 @@ local util = require 'gluon.util' local uci = require('simple-uci').cursor() -local interfaces = uci:get('network', 'client', 'ifname') or {} - -if type(interfaces) == 'string' then - local ifname = interfaces - interfaces = {} - for iface in ifname:gmatch('%S+') do - util.add_to_set(interfaces, iface) - end -end - -if sysconfig.lan_ifname and uci:get_bool('network', 'mesh_lan', 'disabled') then - for lanif in sysconfig.lan_ifname:gmatch('%S+') do - util.add_to_set(interfaces, lanif) - end -end - +local interfaces = util.get_role_interfaces(uci, 'client', true) util.add_to_set(interfaces, 'local-port') - -uci:delete('network', 'client') uci:section('network', 'interface', 'client', { type = 'bridge', ifname = interfaces, diff --git a/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/310-gluon-client-bridge-local-node b/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/310-gluon-client-bridge-local-node index 824d8d40e15a6d8b26bbae66bc0f5f64f549661a..e67dc7d52b2128ec7afc521412cb09c9d68162c0 100755 --- a/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/310-gluon-client-bridge-local-node +++ b/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/310-gluon-client-bridge-local-node @@ -10,7 +10,6 @@ local uci = require('simple-uci').cursor() local next_node = site.next_node({}) -uci:delete('network', 'local_node_dev') uci:section('network', 'device', 'local_node_dev', { type = 'veth', name = 'local-node', @@ -31,7 +30,6 @@ if next_node.ip6 then ip6 = next_node.ip6 .. '/128' end -uci:delete('network', 'local_node') uci:section('network', 'interface', 'local_node', { ifname = 'local-node', proto = 'static', diff --git a/package/gluon-core/check_site.lua b/package/gluon-core/check_site.lua index 4cb44d5bf8598f43e85b5dbb47458cd2abc792f9..103cb929da8304c8ae4f1bd2afcc10713678b332 100644 --- a/package/gluon-core/check_site.lua +++ b/package/gluon-core/check_site.lua @@ -74,6 +74,11 @@ need_string_match(in_domain({'next_node', 'ip4'}), '^%d+.%d+.%d+.%d+$', false) need_boolean(in_domain({'mesh', 'vxlan'}), false) -need_boolean(in_site({'mesh_on_wan'}), false) -need_boolean(in_site({'mesh_on_lan'}), false) -need_boolean(in_site({'single_as_lan'}), false) +local interfaces_roles = {'client', 'uplink', 'mesh'} +for _, config in ipairs({'wan', 'lan', 'single'}) do + need_array_of(in_site({'interfaces', config, 'default_roles'}), interfaces_roles, false) +end + +obsolete({'mesh_on_wan'}, 'Use interfaces.wan.default_roles.') +obsolete({'mesh_on_lan'}, 'Use interfaces.lan.default_roles.') +obsolete({'single_as_lan'}, 'Use interfaces.single.default_roles.') diff --git a/package/gluon-core/files/lib/gluon/upgrade/001-reset-uci b/package/gluon-core/files/lib/gluon/upgrade/001-reset-uci new file mode 100755 index 0000000000000000000000000000000000000000..4981390d74fbbddd75c1248cb9d04d886b1dac70 --- /dev/null +++ b/package/gluon-core/files/lib/gluon/upgrade/001-reset-uci @@ -0,0 +1,23 @@ +#!/bin/sh + +NETWORK_CFG='/etc/config/network' +NETWORK_SAVED="${NETWORK_CFG}_gluon-old" + +SYSTEM_CFG='/etc/config/system' +SYSTEM_SAVED="${SYSTEM_CFG}_gluon-old" + +# Make sure everything is saved before we move away the config files +uci commit + +# Save old configs (unless there is already a saved config, +# which means that the previous upgrade was interrupted) +if [ -s "$NETWORK_CFG" ] && ! [ -s "$NETWORK_SAVED" ]; then + mv -f "$NETWORK_CFG" "$NETWORK_SAVED" +fi +if [ -s "$SYSTEM_CFG" ] && ! [ -s "$SYSTEM_SAVED" ]; then + mv -f "$SYSTEM_CFG" "$SYSTEM_SAVED" +fi + +# Generate a new network config +rm -f /etc/board.json "$NETWORK_CFG" "$SYSTEM_CFG" +config_generate diff --git a/package/gluon-core/files/lib/gluon/upgrade/998-commit b/package/gluon-core/files/lib/gluon/upgrade/998-commit index 8b4be6a9d4dfafe7831d309a8d40fdd211696311..9e781f3490b2065d6a8d27ea6eeb8c8827b66045 100755 --- a/package/gluon-core/files/lib/gluon/upgrade/998-commit +++ b/package/gluon-core/files/lib/gluon/upgrade/998-commit @@ -4,3 +4,6 @@ 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 diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/002-migrate-system b/package/gluon-core/luasrc/lib/gluon/upgrade/002-migrate-system new file mode 100755 index 0000000000000000000000000000000000000000..b08dc8a3b25efabc73ea279ae7247f257469343c --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/002-migrate-system @@ -0,0 +1,31 @@ +#!/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') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/020-interfaces b/package/gluon-core/luasrc/lib/gluon/upgrade/020-interfaces index 6371cc6103d242a2a4d98d78f229a0c2fadd1a54..b56a1e26620a38f4f933acd8cded599175861d28 100755 --- a/package/gluon-core/luasrc/lib/gluon/upgrade/020-interfaces +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/020-interfaces @@ -1,15 +1,7 @@ #!/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 site = require 'gluon.site' +local sysconfig = require 'gluon.sysconfig' local json = require 'jsonc' local uci = require('simple-uci').cursor() @@ -69,19 +61,15 @@ end if wan_ifname and lan_ifname then sysconfig.wan_ifname = wan_ifname sysconfig.lan_ifname = lan_ifname + sysconfig.single_ifname = nil else - local single_ifname = lan_ifname or wan_ifname - if site.single_as_lan(false) then - sysconfig.lan_ifname = single_ifname - else - sysconfig.wan_ifname = single_ifname - end + sysconfig.wan_ifname = nil + sysconfig.lan_ifname = nil + sysconfig.single_ifname = lan_ifname or wan_ifname end -uci:delete('network', 'lan') -uci:delete('network', 'wan') - uci:delete_all('network', 'device') +uci:delete_all('network', 'interface') uci:save('network') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/021-interface-roles b/package/gluon-core/luasrc/lib/gluon/upgrade/021-interface-roles new file mode 100755 index 0000000000000000000000000000000000000000..182c8903464c94ba2eb920df2587c43d97ef90ce --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/021-interface-roles @@ -0,0 +1,66 @@ +#!/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.roles({'client'}), + wan = site.interfaces.wan.roles({'uplink'}), +} +roles.single = site.interfaces.single.roles(roles.wan) + +-- Migration of Mesh-on-WAN/LAN setting from Gluon 2021.1 and older (to be removed in 2024) +-- +-- Wired meshing is enabled for single interfaces if either of the settings +-- was previously enabled +local mesh_lan_disabled = uci:get('network_gluon-old', 'mesh_lan', 'disabled') +local mesh_wan_disabled = uci:get('network_gluon-old', 'mesh_wan', 'disabled') +if mesh_wan_disabled == '0' then + util.add_to_set(roles.wan, 'mesh') + util.add_to_set(roles.single, 'mesh') +elseif mesh_wan_disabled == '1' then + util.remove_from_set(roles.wan, 'mesh') + util.remove_from_set(roles.single, 'mesh') +end +if mesh_lan_disabled == '0' then + util.add_to_set(roles.lan, 'mesh') + util.add_to_set(roles.single, 'mesh') +elseif mesh_lan_disabled == '1' then + util.remove_from_set(roles.lan, 'mesh') + util.remove_from_set(roles.single, 'mesh') +end + +-- 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') +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 + +uci:save('gluon') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/110-network b/package/gluon-core/luasrc/lib/gluon/upgrade/110-network index 79c50d279ec5d722f3bda4b3983d1b56f92d04d0..ac084e6a0354bb6488cace6e477684e74a108981 100755 --- a/package/gluon-core/luasrc/lib/gluon/upgrade/110-network +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/110-network @@ -1,11 +1,24 @@ #!/usr/bin/lua local uci = require('simple-uci').cursor() -local sysconfig = require 'gluon.sysconfig' +local util = require 'gluon.util' +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', +}) uci:section('network', 'interface', 'wan', { - ifname = sysconfig.wan_ifname, + proto = wan.proto or 'dhcp', + ipaddr = wan.ipaddr, + netmask = wan.netmask, + gateway = wan.gateway, + ifname = util.get_role_interfaces(uci, 'uplink'), type = 'bridge', igmp_snooping = true, multicast_querier = false, @@ -13,12 +26,10 @@ uci:section('network', 'interface', 'wan', { auto = true, }) -if not uci:get('network', 'wan', 'proto') then - uci:set('network', 'wan', 'proto', 'dhcp') -end - - uci:section('network', 'interface', 'wan6', { + proto = wan6.proto or 'dhcpv6', + ip6addr = wan6.ip6addr, + ip6gw = wan6.ip6gw, ifname = 'br-wan', peerdns = false, ip6table = 1, @@ -26,11 +37,6 @@ uci:section('network', 'interface', 'wan6', { reqprefix = 'no', }) -if not uci:get('network', 'wan6', 'proto') then - uci:set('network', 'wan6', 'proto', 'dhcpv6') -end - - uci:section('network', 'rule6', 'wan6_lookup', { mark = '0x01/0x01', lookup = 1, diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/200-wireless b/package/gluon-core/luasrc/lib/gluon/upgrade/200-wireless index b0a5485fd3580f42d45ba13d183629bc35301721..604e33a8f9d080a7a01d92f9db8b92e705167391 100755 --- a/package/gluon-core/luasrc/lib/gluon/upgrade/200-wireless +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/200-wireless @@ -106,8 +106,6 @@ end local function delete_ibss(radio_name) local name = 'ibss_' .. radio_name - uci:delete('network', name) - uci:delete('network', name .. '_vlan') uci:delete('wireless', name) end @@ -118,8 +116,6 @@ local function configure_mesh(config, radio, index, suffix, disabled) local macfilter = uci:get('wireless', name, 'macfilter') local maclist = uci:get('wireless', name, 'maclist') - uci:delete('network', name) - uci:delete('network', name .. '_vlan') uci:delete('wireless', name) if not config then diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/210-interface-mesh b/package/gluon-core/luasrc/lib/gluon/upgrade/210-interface-mesh new file mode 100755 index 0000000000000000000000000000000000000000..7e2f84718c589ba9c955741e897966af3f0cfb09 --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/210-interface-mesh @@ -0,0 +1,48 @@ +#!/usr/bin/lua + +local site = require 'gluon.site' +local uci = require('simple-uci').cursor() +local util = require 'gluon.util' + +local mesh_interfaces = util.get_role_interfaces(uci, 'mesh') +local uplink_interfaces = util.get_role_interfaces(uci, 'uplink') + +local mesh_interfaces_uplink = {} +local mesh_interfaces_other = {} +for _, iface in ipairs(mesh_interfaces) do + if util.contains(uplink_interfaces, iface) then + table.insert(mesh_interfaces_uplink, iface) + else + table.insert(mesh_interfaces_other, iface) + end +end + +if #mesh_interfaces_uplink > 0 then + uci:section('network', 'interface', 'mesh_uplink', { + ifname = 'br-wan', + proto = 'gluon_wired', + index = 0, + vxlan = site.mesh.vxlan(true), + }) +end + +if #mesh_interfaces_other > 0 then + local iftype, ifname + if #mesh_interfaces_other == 1 then + ifname = mesh_interfaces_other[1] + else + iftype = 'bridge' + ifname = mesh_interfaces_other + end + + uci:section('network', 'interface', 'mesh_other', { + ifname = ifname, + type = iftype, + igmp_snooping = false, + proto = 'gluon_wired', + index = 4, + vxlan = site.mesh.vxlan(true), + }) +end + +uci:save('network') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/210-interface-wan b/package/gluon-core/luasrc/lib/gluon/upgrade/210-interface-wan deleted file mode 100755 index cf6eff711282b85cc9914b60a4b5d95d7888b839..0000000000000000000000000000000000000000 --- a/package/gluon-core/luasrc/lib/gluon/upgrade/210-interface-wan +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site' -local uci = require('simple-uci').cursor() - -uci:section('network', 'interface', 'mesh_wan', { - ifname = 'br-wan', - proto = 'gluon_wired', - index = 0, - vxlan = site.mesh.vxlan(true), -}) - -local enable = site.mesh_on_wan(false) -local old_auto = uci:get('network', 'mesh_wan', 'auto') -local old_disabled = uci:get('network', 'mesh_wan', 'disabled') -if old_auto ~= nil or old_disabled ~= nil then - enable = old_auto ~= '0' and old_disabled ~= '1' -end -uci:set('network', 'mesh_wan', 'disabled', not enable) - -if uci:get('network', 'mesh_wan', 'transitive') == nil then - uci:set('network', 'mesh_wan', 'transitive', true) -end - -uci:save('network') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/220-interface-lan b/package/gluon-core/luasrc/lib/gluon/upgrade/220-interface-lan deleted file mode 100755 index 55586435f8756c70b99c52ff9815d7ee9f8833ff..0000000000000000000000000000000000000000 --- a/package/gluon-core/luasrc/lib/gluon/upgrade/220-interface-lan +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site' -local util = require 'gluon.util' -local sysconfig = require 'gluon.sysconfig' - -local uci = require('simple-uci').cursor() - -if not sysconfig.lan_ifname then - os.exit(0) -end - -uci:section('network', 'interface', 'mesh_lan', { - ifname = sysconfig.lan_ifname, - igmp_snooping = false, - proto = 'gluon_wired', - index = 4, - vxlan = site.mesh.vxlan(true), -}) - -if sysconfig.lan_ifname:match(' ') then - uci:set('network', 'mesh_lan', 'type', 'bridge') -else - uci:delete('network', 'mesh_lan', 'type') -end - -local enable = site.mesh_on_lan(false) -local old_auto = uci:get('network', 'mesh_lan', 'auto') -local old_disabled = uci:get('network', 'mesh_lan', 'disabled') -if old_auto ~= nil or old_disabled ~= nil then - enable = old_auto ~= '0' and old_disabled ~= '1' -end - -if enable then - local interfaces = uci:get_list('network', 'client', 'ifname') - - if interfaces then - for lanif in sysconfig.lan_ifname:gmatch('%S+') do - if util.contains(interfaces, lanif) then - enable = false - break - end - end - end -end - -uci:set('network', 'mesh_lan', 'disabled', not enable) - -if uci:get('network', 'mesh_lan', 'transitive') == nil then - uci:set('network', 'mesh_lan', 'transitive', true) -end - -uci:save('network') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/300-firewall-rules b/package/gluon-core/luasrc/lib/gluon/upgrade/300-firewall-rules index 605f6684acedb7a450ec77c991cb94195d517f26..ef616aef71fab1b0ca4668c0929b91559e3cfec9 100755 --- a/package/gluon-core/luasrc/lib/gluon/upgrade/300-firewall-rules +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/300-firewall-rules @@ -86,9 +86,9 @@ local wired_mesh_ifaces = {} uci:foreach('network', 'interface', function(iface) -- Select all interfaces with proto gluon_wired except for - -- mesh_wan into this zone, as mesh_wan is the same + -- mesh_uplink into this zone, as mesh_uplink is the same -- interface as wan, which has its own zone - if iface['proto'] == 'gluon_wired' and iface['.name'] ~= 'mesh_wan' then + if iface['proto'] == 'gluon_wired' and iface['.name'] ~= 'mesh_uplink' then table.insert(wired_mesh_ifaces, iface['.name']) end end diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/997-migrate-preserved b/package/gluon-core/luasrc/lib/gluon/upgrade/997-migrate-preserved new file mode 100755 index 0000000000000000000000000000000000000000..c40bbc9f5ccafa9379afec1f04f9e9615d153603 --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/997-migrate-preserved @@ -0,0 +1,19 @@ +#!/usr/bin/lua + +local uci = require('simple-uci').cursor() + +for _, config in ipairs({'system', 'network'}) do + uci:foreach(config .. '_gluon-old', nil, function(s) + if s.gluon_preserve ~= '1' then return end + + -- Unnamed sections can't be preserved + if s['.anonymous'] then return end + + -- We don't allow overwriting existing sections + if uci:get(config, s['.name']) then return end + + uci:section(config, s['.type'], s['.name'], s) + end) + + uci:save(config) +end diff --git a/package/gluon-core/luasrc/usr/lib/lua/gluon/sysconfig.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/sysconfig.lua index 93eb6ed161e8df5b22b5e7720f5734e6f6f089a5..7caf05c6a416ebc22fe786b10ef20605ae350290 100644 --- a/package/gluon-core/luasrc/usr/lib/lua/gluon/sysconfig.lua +++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/sysconfig.lua @@ -11,6 +11,10 @@ local function get(_, name) end local function set(_, name, val) + if val == get(nil, name) then + return + end + if val then local f = io.open(sysconfigdir .. name, 'w+') f:write(val, '\n') diff --git a/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua index 48b8340ee8ee11135e8de59e1ae9f3ecd52043f1..7152bc4d99920ab69f49faf12fc4f55dcb556a68 100644 --- a/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua +++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua @@ -138,6 +138,34 @@ function M.get_mesh_devices(uconn) return devices end +-- Returns a list of all interfaces with a given role +-- +-- If exclusive is set to true, only interfaces that have no other role +-- are returned; this is used to ensure that the client role is not active +-- at the same time as any other role +function M.get_role_interfaces(uci, role, exclusive) + local ret = {} + + local function add(name) + -- Interface names with a / prefix refer to sysconfig interfaces + -- (lan_ifname/wan_ifname/single_ifname) + if string.sub(name, 1, 1) == '/' then + name = sysconfig[string.sub(name, 2) .. '_ifname'] or '' + end + for iface in string.gmatch(name, '%S+') do + M.add_to_set(ret, iface) + end + end + + uci:foreach('gluon', 'interface', function(s) + if M.contains(s.role, role) and (not exclusive or #s.role == 1) then + add(s.name) + end + end) + + return ret +end + -- Safe glob: returns an empty table when the glob fails because of -- a non-existing path function M.glob(pattern) diff --git a/package/gluon-mesh-babel/luasrc/lib/gluon/upgrade/430-gluon-mesh-babel-add-mmfd-interface b/package/gluon-mesh-babel/luasrc/lib/gluon/upgrade/430-gluon-mesh-babel-add-mmfd-interface index 47807d954b0b9af49b57bb3d5a123e7f52aed01a..073d288e8f6375abbe037699258a517d5345a938 100755 --- a/package/gluon-mesh-babel/luasrc/lib/gluon/upgrade/430-gluon-mesh-babel-add-mmfd-interface +++ b/package/gluon-mesh-babel/luasrc/lib/gluon/upgrade/430-gluon-mesh-babel-add-mmfd-interface @@ -2,7 +2,6 @@ local uci = require('simple-uci').cursor() -uci:delete('network', 'mmfd') uci:section('network', 'interface', 'mmfd', { proto = 'static', ifname = 'mmfd0', diff --git a/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/310-gluon-mesh-batman-adv-mesh b/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/310-gluon-mesh-batman-adv-mesh index 40943207fc8f093d160d5134a9629335f5b08715..977b44d157ff18451c4c4524dc23fe3c85c68ffa 100755 --- a/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/310-gluon-mesh-batman-adv-mesh +++ b/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/310-gluon-mesh-batman-adv-mesh @@ -9,14 +9,12 @@ local uci = require('simple-uci').cursor() uci:delete('batman-adv', 'bat0') uci:save('batman-adv') -local gw_mode = uci:get('network', 'gluon_bat0', 'gw_mode') or 'client' -uci:delete('network', 'gluon_bat0') +local gw_mode = uci:get('network_gluon-old', 'gluon_bat0', 'gw_mode') or 'client' uci:section('network', 'interface', 'gluon_bat0', { proto = 'gluon_bat0', gw_mode = gw_mode, }) -uci:delete('network', 'bat0') uci:section('network', 'interface', 'bat0', { ifname = 'bat0', proto = 'none', diff --git a/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/320-gluon-mesh-batman-adv-client-bridge b/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/320-gluon-mesh-batman-adv-client-bridge index fc14a6e60c365514ade73186478bf477749a94b8..1ea64049bf9a9b0e18c8f89117c8cd76eeeba88e 100755 --- a/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/320-gluon-mesh-batman-adv-client-bridge +++ b/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/320-gluon-mesh-batman-adv-client-bridge @@ -21,7 +21,6 @@ uci:section('network', 'interface', 'client', { query_response_interval = 500, }) -uci:delete('network', 'local_node_route6') uci:section('network', 'route6', 'local_node_route6', { interface = 'client', target = site.prefix6(), diff --git a/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/330-gluon-mesh-batman-adv-mac-addresses b/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/330-gluon-mesh-batman-adv-mac-addresses index d323c86337be01834512ce9fe4638d1083d8fc79..09639e34308a6286b641feab4d70a122ceee2748 100755 --- a/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/330-gluon-mesh-batman-adv-mac-addresses +++ b/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/330-gluon-mesh-batman-adv-mac-addresses @@ -8,8 +8,8 @@ local uci = require('simple-uci').cursor() -- fix up potentially duplicate MAC addresses (for meshing) if not site.mesh.vxlan(true) then uci:set('network', 'wan', 'macaddr', util.generate_mac(0)) -else - uci:delete('network', 'wan', 'macaddr') end -uci:set('network', 'mesh_lan', 'macaddr', util.generate_mac(4)) +if uci:get('network', 'mesh_other') then + uci:set('network', 'mesh_other', 'macaddr', util.generate_mac(4)) +end uci:save('network') diff --git a/package/gluon-mesh-vpn-wireguard/luasrc/lib/gluon/upgrade/400-mesh-vpn-wireguard b/package/gluon-mesh-vpn-wireguard/luasrc/lib/gluon/upgrade/400-mesh-vpn-wireguard index dfadc95bd5b0b45245ec3da3287f5ec4edc078e4..05e1d9e95a6b63cf0e4138d41cf5663c529a4c62 100755 --- a/package/gluon-mesh-vpn-wireguard/luasrc/lib/gluon/upgrade/400-mesh-vpn-wireguard +++ b/package/gluon-mesh-vpn-wireguard/luasrc/lib/gluon/upgrade/400-mesh-vpn-wireguard @@ -3,7 +3,7 @@ local uci = require('simple-uci').cursor() local site = require 'gluon.site' -local private_key = uci:get("network", 'wg_mesh', "private_key") +local private_key = uci:get("network_gluon-old", 'wg_mesh', "private_key") if not private_key or not private_key:match("^" .. ("[%a%d+/]"):rep(42) .. "[AEIMQUYcgkosw480]=$") then private_key = "generate" diff --git a/package/gluon-setup-mode/luasrc/lib/gluon/upgrade/320-setup-ifname b/package/gluon-setup-mode/luasrc/lib/gluon/upgrade/320-setup-ifname index 53d60d1c666c865c60be4ed94070773ac66d9f5f..145d371ee43bb4e2157192c035a2ec57d1c954a7 100755 --- a/package/gluon-setup-mode/luasrc/lib/gluon/upgrade/320-setup-ifname +++ b/package/gluon-setup-mode/luasrc/lib/gluon/upgrade/320-setup-ifname @@ -3,13 +3,8 @@ local platform = require 'gluon.platform' local sysconfig = require 'gluon.sysconfig' - -if sysconfig.setup_ifname then - os.exit(0) -end - if platform.is_outdoor_device() then - sysconfig.setup_ifname = sysconfig.wan_ifname or sysconfig.lan_ifname + sysconfig.setup_ifname = sysconfig.single_ifname or sysconfig.wan_ifname else - sysconfig.setup_ifname = sysconfig.lan_ifname or sysconfig.wan_ifname + sysconfig.setup_ifname = sysconfig.single_ifname or sysconfig.lan_ifname end diff --git a/package/gluon-web-network/i18n/de.po b/package/gluon-web-network/i18n/de.po index 4a6bc8b5edca5325499baf4b07af818c37c2f4e9..77b3a6a3509edd72307bd85a3f1151f220ec39d6 100644 --- a/package/gluon-web-network/i18n/de.po +++ b/package/gluon-web-network/i18n/de.po @@ -28,6 +28,9 @@ msgstr "PoE-Passthrough aktivieren" msgid "Enable PoE Power Port %s" msgstr "PoE-Ausgabe auf Port %s aktivieren" +msgid "Enable meshing on the Ethernet interface" +msgstr "Mesh auf dem Ethernet-Port aktivieren" + msgid "Enable meshing on the LAN interface" msgstr "Mesh auf dem LAN-Port aktivieren" diff --git a/package/gluon-web-network/i18n/fr.po b/package/gluon-web-network/i18n/fr.po index 292d6e25bca8fa09e3e153e8418a14a989543c6e..97067343dfb86425f88d325ae634567ca35179d1 100644 --- a/package/gluon-web-network/i18n/fr.po +++ b/package/gluon-web-network/i18n/fr.po @@ -28,6 +28,9 @@ msgstr "" msgid "Enable PoE Power Port %s" msgstr "" +msgid "Enable meshing on the Ethernet interface" +msgstr "" + msgid "Enable meshing on the LAN interface" msgstr "Activer le réseau MESH sur le port LAN" diff --git a/package/gluon-web-network/i18n/gluon-web-network.pot b/package/gluon-web-network/i18n/gluon-web-network.pot index 913b78b3a7310af42cd391b9e7b2c2fdd80d6d2f..a75929dfe6c1f08b18128cb1028f5c1c57c395ea 100644 --- a/package/gluon-web-network/i18n/gluon-web-network.pot +++ b/package/gluon-web-network/i18n/gluon-web-network.pot @@ -19,6 +19,9 @@ msgstr "" msgid "Enable PoE Power Port %s" msgstr "" +msgid "Enable meshing on the Ethernet interface" +msgstr "" + msgid "Enable meshing on the LAN interface" msgstr "" diff --git a/package/gluon-web-network/luasrc/lib/gluon/config-mode/model/admin/network.lua b/package/gluon-web-network/luasrc/lib/gluon/config-mode/model/admin/network.lua index dab31ec014d745be31ac55ec4660e30322e04b9a..df92c965902b68b2551fd6403ed5927ea6264e08 100644 --- a/package/gluon-web-network/luasrc/lib/gluon/config-mode/model/admin/network.lua +++ b/package/gluon-web-network/luasrc/lib/gluon/config-mode/model/admin/network.lua @@ -76,36 +76,37 @@ end s = f:section(Section) -local mesh_wan = s:option(Flag, "mesh_wan", translate("Enable meshing on the WAN interface")) -mesh_wan.default = not uci:get_bool("network", "mesh_wan", "disabled") - -function mesh_wan:write(data) - uci:set("network", "mesh_wan", "disabled", not data) -end - -if sysconfig.lan_ifname then - s = f:section(Section) - - local mesh_lan = s:option(Flag, "mesh_lan", translate("Enable meshing on the LAN interface")) - mesh_lan.default = not uci:get_bool("network", "mesh_lan", "disabled") - - function mesh_lan:write(data) - uci:set("network", "mesh_lan", "disabled", not data) - - local interfaces = uci:get_list("network", "client", "ifname") - - for lanif in sysconfig.lan_ifname:gmatch('%S+') do - if data then - util.remove_from_set(interfaces, lanif) - else - util.add_to_set(interfaces, lanif) - end +local wired_mesh_help = { + single = translate('Enable meshing on the Ethernet interface'), + wan = translate('Enable meshing on the WAN interface'), + lan = translate('Enable meshing on the LAN interface'), +} + +local function wired_mesh(iface) + if not sysconfig[iface .. '_ifname'] then return end + local iface_roles = uci:get_list('gluon', 'iface_' .. iface, 'role') + + local option = s:option(Flag, 'mesh_' .. iface, wired_mesh_help[iface]) + option.default = util.contains(iface_roles, 'mesh') ~= false + + function option:write(data) + local roles = uci:get_list('gluon', 'iface_' .. iface, 'role') + if data then + util.add_to_set(roles, 'mesh') + else + util.remove_from_set(roles, 'mesh') end + uci:set_list('gluon', 'iface_' .. iface, 'role', roles) - uci:set_list("network", "client", "ifname", interfaces) + -- Reconfigure on next reboot + uci:set('gluon', 'core', 'reconfigure', true) end end +wired_mesh('single') +wired_mesh('wan') +wired_mesh('lan') + local section uci:foreach("system", "gpio_switch", function(si) if si[".name"]:match("poe") then @@ -160,7 +161,7 @@ function f:write() uci:delete("network", "wan6", "ip6gw") end - + uci:commit('gluon') uci:commit("network") uci:commit('system') end