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).
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)

View File

@ -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")"

View File

@ -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

View File

@ -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

View File

@ -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')

View File

@ -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(),
})