From c779d123692956badec1686df1d9ff1c4d86828e Mon Sep 17 00:00:00 2001
From: Matthias Schiffer <mschiffer@universe-factory.net>
Date: Sun, 23 Jan 2022 14:43:35 +0100
Subject: [PATCH] treewide: use interface roles as basis for network
 configuration

With the new role-based interface configuration, it would be better to
rename the wan/wan6 interfaces to uplink/uplink6, but that would cause
unnecessary churn for the firewall configuration, so it is left for a
later update.

As all interfaces with the 'uplink' role are in the br-wan bridge, it is
not possible to assign these to the 'mesh' role independently - instead,
br-wan is added as a mesh interface as soon as a single interface has
both the 'uplink' and 'mesh' roles. The UCI section for this
configuration is now called 'mesh_uplink' instead of 'mesh_wan'.

For all interfaces that have the 'mesh', but not the 'uplink' role a
second configuration 'mesh_other' is created. If there is more than one
such interface, all these interfaces are bridged as well (creating a
bridge 'br-mesh_other'). This replaces the 'mesh_lan' section with its
optional 'br-mesh_lan' bridge, but can also include interfaces that were
not considered "LAN" when interfaces roles are modified (via site.conf
or manually).
---
 .../upgrade/300-gluon-client-bridge-network   |  8 +---
 .../luasrc/lib/gluon/upgrade/110-network      |  4 +-
 .../lib/gluon/upgrade/210-interface-mesh      | 48 +++++++++++++++++++
 .../lib/gluon/upgrade/210-interface-wan       | 25 ----------
 .../lib/gluon/upgrade/220-interface-lan       | 38 ---------------
 .../lib/gluon/upgrade/300-firewall-rules      |  4 +-
 .../luasrc/usr/lib/lua/gluon/util.lua         | 28 +++++++++++
 .../330-gluon-mesh-batman-adv-mac-addresses   |  4 +-
 8 files changed, 85 insertions(+), 74 deletions(-)
 create mode 100755 package/gluon-core/luasrc/lib/gluon/upgrade/210-interface-mesh
 delete mode 100755 package/gluon-core/luasrc/lib/gluon/upgrade/210-interface-wan
 delete mode 100755 package/gluon-core/luasrc/lib/gluon/upgrade/220-interface-lan

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 b344b2b32..3d4dbac38 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,12 +6,8 @@ local util = require 'gluon.util'
 local uci = require('simple-uci').cursor()
 
 
-local interfaces = { 'local-port' }
-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:section('network', 'interface', 'client', {
 	type = 'bridge',
diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/110-network b/package/gluon-core/luasrc/lib/gluon/upgrade/110-network
index 8903c126a..ac084e6a0 100755
--- a/package/gluon-core/luasrc/lib/gluon/upgrade/110-network
+++ b/package/gluon-core/luasrc/lib/gluon/upgrade/110-network
@@ -1,7 +1,7 @@
 #!/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 {}
@@ -18,7 +18,7 @@ uci:section('network', 'interface', 'wan', {
 	ipaddr = wan.ipaddr,
 	netmask = wan.netmask,
 	gateway = wan.gateway,
-	ifname = sysconfig.wan_ifname,
+	ifname = util.get_role_interfaces(uci, 'uplink'),
 	type = 'bridge',
 	igmp_snooping = true,
 	multicast_querier = false,
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 000000000..7e2f84718
--- /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 4f24cbc43..000000000
--- 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()
-
-local disabled = uci:get('network_gluon-old', 'mesh_wan', 'disabled')
-if disabled == nil then
-	disabled = not site.mesh_on_wan(false)
-end
-
-local transitive = uci:get('network_gluon-old', 'mesh_wan', 'transitive')
-if transitive == nil then
-	transitive = true
-end
-
-uci:section('network', 'interface', 'mesh_wan', {
-	ifname = 'br-wan',
-	proto = 'gluon_wired',
-	index = 0,
-	vxlan = site.mesh.vxlan(true),
-	disabled = disabled,
-	transitive = transitive,
-})
-
-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 cd38f804a..000000000
--- a/package/gluon-core/luasrc/lib/gluon/upgrade/220-interface-lan
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/lua
-
-local site = require 'gluon.site'
-local sysconfig = require 'gluon.sysconfig'
-
-local uci = require('simple-uci').cursor()
-
-if not sysconfig.lan_ifname then
-	os.exit(0)
-end
-
-local type
-if sysconfig.lan_ifname:match(' ') then
-	type = 'bridge'
-end
-
-local disabled = uci:get('network_gluon-old', 'mesh_lan', 'disabled')
-if disabled == nil then
-	disabled = not site.mesh_on_lan(false)
-end
-
-local transitive = uci:get('network_gluon-old', 'mesh_lan', 'transitive')
-if transitive == nil then
-	transitive = true
-end
-
-uci:section('network', 'interface', 'mesh_lan', {
-	ifname = sysconfig.lan_ifname,
-	type = type,
-	igmp_snooping = false,
-	proto = 'gluon_wired',
-	index = 4,
-	vxlan = site.mesh.vxlan(true),
-	disabled = disabled,
-	transitive = transitive,
-})
-
-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 605f6684a..ef616aef7 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/usr/lib/lua/gluon/util.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua
index 48b8340ee..7152bc4d9 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-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 61153e103..09639e343 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
@@ -9,5 +9,7 @@ local uci = require('simple-uci').cursor()
 if not site.mesh.vxlan(true) then
 	uci:set('network', 'wan', 'macaddr', util.generate_mac(0))
 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')
-- 
GitLab