From 92af7c80a6c4e6fa805ac12261eee9448b60fc60 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Sat, 11 Apr 2020 15:08:50 +0200 Subject: [PATCH] gluon-core: rewrite MAC-address generation logic This rewrites the MAC address generation logic to distinguish between MAC addresses assigned to a wireless interface or virtual / wired interfaces. Each radio is now assigned a range of SSIDs, allowing for up to 8 SSIDs per radio. Previosuly, there were 8 MAC addresses total for the entire device. To keep compatibility on already deployed nodes, MAC addresses for wired / virtual interfaces stay unchanged. This change is required to support nodes with more than 2 radios. It also allows us to increase the number of VAPs per radio. --- docs/dev/mac_addresses.rst | 24 +++++++----- .../files/lib/netifd/proto/gluon_wired.sh | 2 +- .../luasrc/usr/lib/lua/gluon/util.lua | 38 ++++++++++++------- .../files/lib/netifd/proto/gluon_bat0.sh | 2 +- .../330-gluon-mesh-batman-adv-mac-addresses | 4 +- .../luasrc/lib/gluon/upgrade/500-mesh-vpn | 2 +- 6 files changed, 45 insertions(+), 27 deletions(-) diff --git a/docs/dev/mac_addresses.rst b/docs/dev/mac_addresses.rst index 3121404e..96ddad01 100644 --- a/docs/dev/mac_addresses.rst +++ b/docs/dev/mac_addresses.rst @@ -6,13 +6,19 @@ Many devices don't have enough unique MAC addresses assigned by the vendor mesh-wide). Gluon tries to solve this issue by using a hash of the primary MAC address as a -45 bit MAC address prefix. The resulting 8 addresses are used as follows: +45 bit MAC address prefix per radio. One additional prefix is dedicated to wired +interfaces as well as the mesh-protocol. -* 0: client0; WAN -* 1: mesh0 -* 2: owe0 -* 3: wan_radio0 (private WLAN); batman-adv primary address -* 4: client1; LAN -* 5: mesh1 -* 6: owe1 -* 7: wan_radio1 (private WLAN); mesh VPN +The remaining 3 bits are assigned to the following interfaces / VAPs: + +IDs for non-radio interfaces defined so far: +* 0: WAN +* 3: batman-adv primary address +* 4: LAN +* 7: mesh VPN + +IDs for radio interfaces defined so far: +* 0: client +* 1: mesh +* 2: owe +* 3: wan_radio (private WLAN) diff --git a/package/gluon-core/files/lib/netifd/proto/gluon_wired.sh b/package/gluon-core/files/lib/netifd/proto/gluon_wired.sh index 708e9743..c7b885d3 100755 --- a/package/gluon-core/files/lib/netifd/proto/gluon_wired.sh +++ b/package/gluon-core/files/lib/netifd/proto/gluon_wired.sh @@ -41,7 +41,7 @@ proto_gluon_wired_setup() { json_init json_add_string name "$meshif" - [ -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(0, $index))")" json_add_string proto 'vxlan6' json_add_string tunlink "$config" json_add_string ip6addr "$(interface_linklocal "$ifname")" 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 99544368..39652d98 100644 --- a/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua +++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua @@ -176,18 +176,23 @@ local function get_addresses(radio) end -- Generates a (hopefully) unique MAC address --- The parameter defines the ID to add to the MAC address +-- The range parameter identifies the range the MAC address belongs to +-- Range 0 is reserved for MAC addresses not assigned to a radio +-- Wireless PHYs are assigned starting at range 1 +-- The i parameter defines the ID to add to the MAC address -- --- IDs defined so far: --- 0: client0; WAN --- 1: mesh0 --- 2: owe0 --- 3: wan_radio0 (private WLAN); batman-adv primary address --- 4: client1; LAN --- 5: mesh1 --- 6: owe1 --- 7: wan_radio1 (private WLAN); mesh VPN -function M.generate_mac(i) +-- IDs for non-radio interfaces defined so far: +-- 0: WAN +-- 3: batman-adv primary address +-- 4: LAN +-- 7: mesh VPN +-- +-- IDs for radio interfaces defined so far: +-- 0: client +-- 1: mesh +-- 2: owe +-- 3: wan_radio (private WLAN) +function M.generate_mac(range, i) if i > 7 or i < 0 then return nil end -- max allowed id (0b111) local hashed = string.sub(hash.md5(sysconfig.primary_mac), 0, 12) @@ -199,6 +204,13 @@ function M.generate_mac(i) m1 = bit.bor(m1, 0x02) -- set locally administered bit m1 = bit.band(m1, 0xFE) -- unset the multicast bit + m5 = tonumber(m5, 16) + m5 = m5 + range + + if m5 > 255 then + m5 = m5 - 256 + end + -- It's necessary that the first 45 bits of the MAC address don't -- vary on a single hardware interface, since some chips are using -- a hardware MAC filter. (e.g 'rt305x') @@ -206,7 +218,7 @@ function M.generate_mac(i) m6 = bit.band(m6, 0xF8) -- zero the last three bits (space needed for counting) m6 = m6 + i -- add virtual interface id - return string.format('%02x:%s:%s:%s:%s:%02x', m1, m2, m3, m4, m5, m6) + return string.format('%02x:%s:%s:%s:%02x:%02x', m1, m2, m3, m4, m5, m6) end local function get_wlan_mac_from_driver(radio, vif) @@ -237,7 +249,7 @@ function M.get_wlan_mac(_, radio, index, vif) return addr end - return M.generate_mac(4*(index-1) + (vif-1)) + return M.generate_mac(index, (vif-1)) end -- Iterate over all radios defined in UCI calling diff --git a/package/gluon-mesh-batman-adv/files/lib/netifd/proto/gluon_bat0.sh b/package/gluon-mesh-batman-adv/files/lib/netifd/proto/gluon_bat0.sh index f5c54ea3..58a474cb 100755 --- a/package/gluon-mesh-batman-adv/files/lib/netifd/proto/gluon_bat0.sh +++ b/package/gluon-mesh-batman-adv/files/lib/netifd/proto/gluon_bat0.sh @@ -62,7 +62,7 @@ proto_gluon_bat0_setup() { esac - local primary0_mac="$(lua -e 'print(require("gluon.util").generate_mac(3))')" + local primary0_mac="$(lua -e 'print(require("gluon.util").generate_mac(0, 3))')" ip link add primary0 type dummy echo 1 > /proc/sys/net/ipv6/conf/primary0/disable_ipv6 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 a8e69d78..468d37dd 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 @@ -5,6 +5,6 @@ local uci = require('simple-uci').cursor() -- fix up potentially duplicate MAC addresses (for meshing) -uci:set('network', 'wan', 'macaddr', util.generate_mac(0)) -uci:set('network', 'mesh_lan', 'macaddr', util.generate_mac(4)) +uci:set('network', 'wan', 'macaddr', util.generate_mac(0, 0)) +uci:set('network', 'mesh_lan', 'macaddr', util.generate_mac(0, 4)) uci:save('network') diff --git a/package/gluon-mesh-vpn-core/luasrc/lib/gluon/upgrade/500-mesh-vpn b/package/gluon-mesh-vpn-core/luasrc/lib/gluon/upgrade/500-mesh-vpn index 019b9afb..b3b1596b 100755 --- a/package/gluon-mesh-vpn-core/luasrc/lib/gluon/upgrade/500-mesh-vpn +++ b/package/gluon-mesh-vpn-core/luasrc/lib/gluon/upgrade/500-mesh-vpn @@ -13,7 +13,7 @@ uci:section('network', 'interface', 'mesh_vpn', { proto = 'gluon_mesh', transitive = true, fixed_mtu = true, - macaddr = util.generate_mac(7), + macaddr = util.generate_mac(0, 7), mtu = site.mesh_vpn.mtu(), })