Skip to content
Snippets Groups Projects
Commit c73a12e0 authored by lemoer's avatar lemoer Committed by Matthias Schiffer
Browse files

Change MAC schema generation (#715)

While ath9k/ath10k devices can supprt VIFs with any combination of MAC addresses, there are also adapters which have a hardware MAC filter which only allows a few bits to differ. This commit changes the addresses of all VIFs to ony differ in the last 3 bits, which is required to support many Ralink/Mediatek based WLAN adapters.

Technically, the new addresses are generated by calculating an MD5 hash of the primary MAC address and using a part of this hash as a prefix for the MAC addresses.

The addresses (BSSIDs) of the AP VIFs are also reused for the LAN and WAN interfaces in mesh-on-LAN/WAN mode to reduce the number of needed addresses, and thus reduce the chance of collisions. This is not a problem as the MAC addresses of the AP VIFs are never used except as BSSID, and thus not seen by routing protocols like batman-adv.

Fixes #648

[Matthias Schiffer: rewrote commit message]
parent 82b5b5a8
No related branches found
No related tags found
No related merge requests found
...@@ -21,14 +21,16 @@ local function configure_client(config, radio, index, suffix) ...@@ -21,14 +21,16 @@ local function configure_client(config, radio, index, suffix)
uci:delete('wireless', name) uci:delete('wireless', name)
if config then macaddr = util.generate_mac(3*index)
if config and macaddr then
uci:section('wireless', 'wifi-iface', name, uci:section('wireless', 'wifi-iface', name,
{ {
device = radio, device = radio,
network = 'client', network = 'client',
mode = 'ap', mode = 'ap',
ssid = config.ssid, ssid = config.ssid,
macaddr = util.generate_mac(2, index), macaddr = macaddr,
ifname = suffix and 'client' .. suffix, ifname = suffix and 'client' .. suffix,
disabled = disabled, disabled = disabled,
} }
......
...@@ -12,7 +12,7 @@ define Package/gluon-core ...@@ -12,7 +12,7 @@ define Package/gluon-core
SECTION:=gluon SECTION:=gluon
CATEGORY:=Gluon CATEGORY:=Gluon
TITLE:=Base files of Gluon TITLE:=Base files of Gluon
DEPENDS:=+gluon-site +libgluonutil +lua-platform-info +luci-base +luci-lib-jsonc +odhcp6c +firewall DEPENDS:=+gluon-site +libgluonutil +lua-platform-info +lua-hash +luci-base +luci-lib-jsonc +odhcp6c +firewall
endef endef
......
...@@ -30,6 +30,7 @@ local ipairs = ipairs ...@@ -30,6 +30,7 @@ local ipairs = ipairs
local table = table local table = table
local nixio = require 'nixio' local nixio = require 'nixio'
local hash = require 'hash'
local sysconfig = require 'gluon.sysconfig' local sysconfig = require 'gluon.sysconfig'
local site = require 'gluon.site_config' local site = require 'gluon.site_config'
local uci = require('luci.model.uci').cursor() local uci = require('luci.model.uci').cursor()
...@@ -71,22 +72,37 @@ function node_id() ...@@ -71,22 +72,37 @@ function node_id()
end end
-- Generates a (hopefully) unique MAC address -- Generates a (hopefully) unique MAC address
-- The first parameter defines the function and the second -- The parameter defines the ID to add to the mac addr
-- parameter an ID to add to the MAC address --
-- Functions and IDs defined so far: -- IDs defined so far:
-- (1, 0): WAN (for mesh-on-WAN) -- 0: client0; mesh-vpn
-- (1, 1): LAN (for mesh-on-LAN) -- 1: mesh0
-- (2, n): client interface for the n'th radio -- 2: ibss0
-- (3, n): adhoc interface for n'th radio -- 3: client1; mesh-on-wan
-- (4, 0): mesh VPN -- 4: mesh1
-- (5, n): mesh interface for n'th radio (802.11s) -- 5: ibss1
function generate_mac(f, i) -- 6: mesh-on-lan
local m1, m2, m3, m4, m5, m6 = string.match(sysconfig.primary_mac, '(%x%x):(%x%x):(%x%x):(%x%x):(%x%x):(%x%x)') -- 7: unused
m1 = nixio.bit.bor(tonumber(m1, 16), 0x02) function generate_mac(i)
m2 = (tonumber(m2, 16)+f) % 0x100 if i > 7 or i < 0 then return nil end -- max allowed id (0b111)
m3 = (tonumber(m3, 16)+i) % 0x100
local hashed = string.sub(hash.md5(sysconfig.primary_mac), 0, 12)
return string.format('%02x:%02x:%02x:%s:%s:%s', m1, m2, m3, m4, m5, m6) local m1, m2, m3, m4, m5, m6 = string.match(hashed, '(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)')
m1 = tonumber(m1, 16)
m6 = tonumber(m6, 16)
m1 = nixio.bit.bor(m1, 0x02) -- set locally administered bit
m1 = nixio.bit.band(m1, 0xFE) -- unset the multicast bit
-- It's necessary that the first 45 bits of the mac do
-- not vary on a single hardware interface, since some chips are using
-- a hardware mac filter. (e.g 'ramips-rt305x')
m6 = nixio.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)
end end
-- Iterate over all radios defined in UCI calling -- Iterate over all radios defined in UCI calling
......
...@@ -5,6 +5,6 @@ local uci = require('luci.model.uci').cursor() ...@@ -5,6 +5,6 @@ local uci = require('luci.model.uci').cursor()
-- fix up duplicate mac addresses (for mesh-on-WAN) -- fix up duplicate mac addresses (for mesh-on-WAN)
uci:set('network', 'wan', 'macaddr', util.generate_mac(1, 0)) uci:set('network', 'wan', 'macaddr', util.generate_mac(3))
uci:save('network') uci:save('network')
...@@ -29,7 +29,9 @@ local function configure_ibss(config, radio, index, suffix, disabled) ...@@ -29,7 +29,9 @@ local function configure_ibss(config, radio, index, suffix, disabled)
uci:delete('network', name .. '_vlan') uci:delete('network', name .. '_vlan')
uci:delete('wireless', name) uci:delete('wireless', name)
if config then macaddr = util.generate_mac(3*index+2)
if config and macaddr then
if config.vlan then if config.vlan then
uci:section('network', 'interface', name, uci:section('network', 'interface', name,
{ {
...@@ -60,7 +62,7 @@ local function configure_ibss(config, radio, index, suffix, disabled) ...@@ -60,7 +62,7 @@ local function configure_ibss(config, radio, index, suffix, disabled)
mode = 'adhoc', mode = 'adhoc',
ssid = config.ssid, ssid = config.ssid,
bssid = config.bssid, bssid = config.bssid,
macaddr = util.generate_mac(3, index), macaddr = macaddr,
mcast_rate = config.mcast_rate, mcast_rate = config.mcast_rate,
ifname = suffix and 'ibss' .. suffix, ifname = suffix and 'ibss' .. suffix,
disabled = disabled and 1 or 0, disabled = disabled and 1 or 0,
...@@ -77,7 +79,9 @@ local function configure_mesh(config, radio, index, suffix, disabled) ...@@ -77,7 +79,9 @@ local function configure_mesh(config, radio, index, suffix, disabled)
uci:delete('network', name) uci:delete('network', name)
uci:delete('wireless', name) uci:delete('wireless', name)
if config then macaddr = util.generate_mac(3*index+1)
if config and macaddr then
uci:section('network', 'interface', name, uci:section('network', 'interface', name,
{ {
proto = 'batadv', proto = 'batadv',
...@@ -92,7 +96,7 @@ local function configure_mesh(config, radio, index, suffix, disabled) ...@@ -92,7 +96,7 @@ local function configure_mesh(config, radio, index, suffix, disabled)
mode = 'mesh', mode = 'mesh',
mesh_id = config.id, mesh_id = config.id,
mesh_fwding = 0, mesh_fwding = 0,
macaddr = util.generate_mac(5, index), macaddr = macaddr,
mcast_rate = config.mcast_rate, mcast_rate = config.mcast_rate,
ifname = suffix and 'mesh' .. suffix, ifname = suffix and 'mesh' .. suffix,
disabled = disabled and 1 or 0, disabled = disabled and 1 or 0,
......
...@@ -28,7 +28,7 @@ if sysconfig.lan_ifname and not uci:get('network', 'mesh_lan') then ...@@ -28,7 +28,7 @@ if sysconfig.lan_ifname and not uci:get('network', 'mesh_lan') then
, proto = 'batadv' , proto = 'batadv'
, mesh = 'bat0' , mesh = 'bat0'
, mesh_no_rebroadcast = '1' , mesh_no_rebroadcast = '1'
, macaddr = util.generate_mac(1, 1) , macaddr = util.generate_mac(6)
, auto = enable and 1 or 0 , auto = enable and 1 or 0
}) })
......
...@@ -127,7 +127,7 @@ uci:section('network', 'interface', 'mesh_vpn', ...@@ -127,7 +127,7 @@ uci:section('network', 'interface', 'mesh_vpn',
proto = 'batadv', proto = 'batadv',
mesh = 'bat0', mesh = 'bat0',
mesh_no_rebroadcast = 1, mesh_no_rebroadcast = 1,
macaddr = util.generate_mac(4, 0), macaddr = util.generate_mac(0),
} }
) )
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment