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:
parent
6042f5256a
commit
92af7c80a6
@ -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)
|
||||
|
@ -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")"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
@ -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(),
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user