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.
This commit is contained in:
David Bauer 2020-04-11 15:08:50 +02:00
parent 6042f5256a
commit 92af7c80a6
6 changed files with 45 additions and 27 deletions

View File

@ -6,13 +6,19 @@ Many devices don't have enough unique MAC addresses assigned by the vendor
mesh-wide). mesh-wide).
Gluon tries to solve this issue by using a hash of the primary MAC address as a 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 The remaining 3 bits are assigned to the following interfaces / VAPs:
* 1: mesh0
* 2: owe0 IDs for non-radio interfaces defined so far:
* 3: wan_radio0 (private WLAN); batman-adv primary address * 0: WAN
* 4: client1; LAN * 3: batman-adv primary address
* 5: mesh1 * 4: LAN
* 6: owe1 * 7: mesh VPN
* 7: wan_radio1 (private WLAN); mesh VPN
IDs for radio interfaces defined so far:
* 0: client
* 1: mesh
* 2: owe
* 3: wan_radio (private WLAN)

View File

@ -41,7 +41,7 @@ proto_gluon_wired_setup() {
json_init json_init
json_add_string name "$meshif" 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 proto 'vxlan6'
json_add_string tunlink "$config" json_add_string tunlink "$config"
json_add_string ip6addr "$(interface_linklocal "$ifname")" json_add_string ip6addr "$(interface_linklocal "$ifname")"

View File

@ -176,18 +176,23 @@ local function get_addresses(radio)
end end
-- Generates a (hopefully) unique MAC address -- 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: -- IDs for non-radio interfaces defined so far:
-- 0: client0; WAN -- 0: WAN
-- 1: mesh0 -- 3: batman-adv primary address
-- 2: owe0 -- 4: LAN
-- 3: wan_radio0 (private WLAN); batman-adv primary address -- 7: mesh VPN
-- 4: client1; LAN --
-- 5: mesh1 -- IDs for radio interfaces defined so far:
-- 6: owe1 -- 0: client
-- 7: wan_radio1 (private WLAN); mesh VPN -- 1: mesh
function M.generate_mac(i) -- 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) 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) 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.bor(m1, 0x02) -- set locally administered bit
m1 = bit.band(m1, 0xFE) -- unset the multicast 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 -- 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 -- vary on a single hardware interface, since some chips are using
-- a hardware MAC filter. (e.g 'rt305x') -- 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 = bit.band(m6, 0xF8) -- zero the last three bits (space needed for counting)
m6 = m6 + i -- add virtual interface id 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 end
local function get_wlan_mac_from_driver(radio, vif) local function get_wlan_mac_from_driver(radio, vif)
@ -237,7 +249,7 @@ function M.get_wlan_mac(_, radio, index, vif)
return addr return addr
end end
return M.generate_mac(4*(index-1) + (vif-1)) return M.generate_mac(index, (vif-1))
end end
-- Iterate over all radios defined in UCI calling -- Iterate over all radios defined in UCI calling

View File

@ -62,7 +62,7 @@ proto_gluon_bat0_setup() {
esac 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 ip link add primary0 type dummy
echo 1 > /proc/sys/net/ipv6/conf/primary0/disable_ipv6 echo 1 > /proc/sys/net/ipv6/conf/primary0/disable_ipv6

View File

@ -5,6 +5,6 @@ local uci = require('simple-uci').cursor()
-- fix up potentially duplicate MAC addresses (for meshing) -- fix up potentially duplicate MAC addresses (for meshing)
uci:set('network', 'wan', 'macaddr', util.generate_mac(0)) uci:set('network', 'wan', 'macaddr', util.generate_mac(0, 0))
uci:set('network', 'mesh_lan', 'macaddr', util.generate_mac(4)) uci:set('network', 'mesh_lan', 'macaddr', util.generate_mac(0, 4))
uci:save('network') uci:save('network')

View File

@ -13,7 +13,7 @@ uci:section('network', 'interface', 'mesh_vpn', {
proto = 'gluon_mesh', proto = 'gluon_mesh',
transitive = true, transitive = true,
fixed_mtu = true, fixed_mtu = true,
macaddr = util.generate_mac(7), macaddr = util.generate_mac(0, 7),
mtu = site.mesh_vpn.mtu(), mtu = site.mesh_vpn.mtu(),
}) })