From 13c1080a3f6cbe4e8a999e77a7688b2367b8adf9 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 6 Sep 2023 16:58:09 +0200 Subject: [PATCH] hostapd: move mac address allocation from mac80211.sh to wdev.uc Preparation for upcoming hostapd reload improvements Signed-off-by: Felix Fietkau --- .../files/lib/netifd/wireless/mac80211.sh | 46 +------- .../network/services/hostapd/files/common.uc | 84 ++++++++++++++- .../network/services/hostapd/files/wdev.uc | 100 ++++++++++++------ 3 files changed, 154 insertions(+), 76 deletions(-) diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index 3b88af4679..1d7f733cad 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -533,47 +533,7 @@ mac80211_generate_mac() { local phy="$1" local id="${macidx:-0}" - local ref="$(cat /sys/class/ieee80211/${phy}/macaddress)" - local mask="$(cat /sys/class/ieee80211/${phy}/address_mask)" - - [ "$mask" = "00:00:00:00:00:00" ] && { - mask="ff:ff:ff:ff:ff:ff"; - - [ "$(wc -l < /sys/class/ieee80211/${phy}/addresses)" -gt $id ] && { - addr="$(mac80211_get_addr "$phy" "$id")" - [ -n "$addr" ] && { - echo "$addr" - return - } - } - } - - local oIFS="$IFS"; IFS=":"; set -- $mask; IFS="$oIFS" - - local mask1=$1 - local mask6=$6 - - local oIFS="$IFS"; IFS=":"; set -- $ref; IFS="$oIFS" - - macidx=$(($id + 1)) - [ "$((0x$mask1))" -gt 0 ] && { - b1="0x$1" - [ "$id" -gt 0 ] && \ - b1=$(($b1 ^ ((($id - !($b1 & 2)) << 2)) | 0x2)) - printf "%02x:%s:%s:%s:%s:%s" $b1 $2 $3 $4 $5 $6 - return - } - - [ "$((0x$mask6))" -lt 255 ] && { - printf "%s:%s:%s:%s:%s:%02x" $1 $2 $3 $4 $5 $(( 0x$6 ^ $id )) - return - } - - off2=$(( (0x$6 + $id) / 0x100 )) - printf "%s:%s:%s:%s:%02x:%02x" \ - $1 $2 $3 $4 \ - $(( (0x$5 + $off2) % 0x100 )) \ - $(( (0x$6 + $id) % 0x100 )) + wdev_tool "$phy" get_macaddr id=$id } get_board_phy_name() ( @@ -1070,7 +1030,7 @@ mac80211_reset_config() { hostapd_conf_file="/var/run/hostapd-$phy.conf" ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null - wdev_tool "$phy" '{}' + wdev_tool "$phy" set_config '{}' } drv_mac80211_setup() { @@ -1174,7 +1134,7 @@ drv_mac80211_setup() { [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_start "$phy" json_set_namespace wdev_uc prev - wdev_tool "$phy" "$(json_dump)" $active_ifnames + wdev_tool "$phy" set_config "$(json_dump)" $active_ifnames json_set_namespace "$prev" for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower diff --git a/package/network/services/hostapd/files/common.uc b/package/network/services/hostapd/files/common.uc index 74c07855c9..f37804c8c6 100644 --- a/package/network/services/hostapd/files/common.uc +++ b/package/network/services/hostapd/files/common.uc @@ -94,6 +94,88 @@ function wdev_create(phy, name, data) return null; } +function phy_sysfs_file(phy, name) +{ + return trim(readfile(`/sys/class/ieee80211/${phy}/${name}`)); +} + +function macaddr_split(str) +{ + return map(split(str, ":"), (val) => hex(val)); +} + +function macaddr_join(addr) +{ + return join(":", map(addr, (val) => sprintf("%02x", val))); +} + +function wdev_generate_macaddr(phy, data) +{ + let idx = int(data.id ?? 0); + let mbssid = int(data.mbssid ?? 0) > 0; + let num_global = int(data.num_global ?? 1); + let use_global = !mbssid && idx < num_global; + + let base_addr = phy_sysfs_file(phy, "macaddress"); + if (!base_addr) + return null; + + if (!idx && !mbssid) + return base_addr; + + let base_mask = phy_sysfs_file(phy, "address_mask"); + if (!base_mask) + return null; + + if (base_mask == "00:00:00:00:00:00" && idx >= num_global) { + let addrs = split(phy_sysfs_file(phy, "addresses"), "\n"); + + if (idx < length(addrs)) + return addrs[idx]; + + base_mask = "ff:ff:ff:ff:ff:ff"; + } + + let addr = macaddr_split(base_addr); + let mask = macaddr_split(base_mask); + let type; + + if (mbssid) + type = "b5"; + else if (use_global) + type = "add"; + else if (mask[0] > 0) + type = "b1"; + else if (mask[5] < 0xff) + type = "b5"; + else + type = "add"; + + switch (type) { + case "b1": + if (!(addr[0] & 2)) + idx--; + addr[0] |= 2; + addr[0] ^= idx << 2; + break; + case "b5": + if (mbssid) + addr[0] |= 2; + addr[5] ^= idx; + break; + default: + for (let i = 5; i > 0; i--) { + addr[i] += idx; + if (addr[i] < 256) + break; + addr[i] %= 256; + } + break; + } + + return macaddr_join(addr); +} + const vlist_proto = { update: function(values, arg) { let data = this.data; @@ -165,4 +247,4 @@ function vlist_new(cb) { }, vlist_proto); } -export { wdev_remove, wdev_create, is_equal, vlist_new, phy_is_fullmac }; +export { wdev_remove, wdev_create, wdev_generate_macaddr, is_equal, vlist_new, phy_is_fullmac }; diff --git a/package/network/services/hostapd/files/wdev.uc b/package/network/services/hostapd/files/wdev.uc index 78037a9d27..8db245cdb7 100644 --- a/package/network/services/hostapd/files/wdev.uc +++ b/package/network/services/hostapd/files/wdev.uc @@ -1,11 +1,11 @@ #!/usr/bin/env ucode 'use strict'; -import { vlist_new, is_equal, wdev_create, wdev_remove } from "/usr/share/hostap/common.uc"; +import { vlist_new, is_equal, wdev_create, wdev_remove, wdev_generate_macaddr } from "/usr/share/hostap/common.uc"; import { readfile, writefile, basename, readlink, glob } from "fs"; let keep_devices = {}; let phy = shift(ARGV); -let new_config = shift(ARGV); + const mesh_params = [ "mesh_retry_timeout", "mesh_confirm_timeout", "mesh_holding_timeout", "mesh_max_peer_links", "mesh_max_retries", "mesh_ttl", "mesh_element_ttl", "mesh_hwmp_max_preq_retries", @@ -114,43 +114,79 @@ function add_existing(phy, config) } } +function usage() +{ + warn(`Usage: ${basename(sourcepath())} [] -let statefile = `/var/run/wdev-${phy}.json`; - -for (let dev in ARGV) - keep_devices[dev] = true; - -if (!phy || !new_config) { - warn(`Usage: ${basename(sourcepath())} [ [ - get phy MAC address for vif index +`); exit(1); } -if (!readfile(`/sys/class/ieee80211/${phy}/index`)) { - warn(`PHY ${phy} does not exist\n`); - exit(1); -} +const commands = { + set_config: function(args) { + let statefile = `/var/run/wdev-${phy}.json`; -new_config = json(new_config); -if (!new_config) { - warn("Invalid configuration\n"); - exit(1); -} + let new_config = shift(args); + for (let dev in ARGV) + keep_devices[dev] = true; + + if (!new_config) + usage(); + + new_config = json(new_config); + if (!new_config) { + warn("Invalid configuration\n"); + exit(1); + } -let old_config = readfile(statefile); -if (old_config) - old_config = json(old_config); + let old_config = readfile(statefile); + if (old_config) + old_config = json(old_config); -let config = vlist_new(iface_cb); -if (type(old_config) == "object") - config.data = old_config; + let config = vlist_new(iface_cb); + if (type(old_config) == "object") + config.data = old_config; -add_existing(phy, config.data); -add_ifname(config.data); -drop_inactive(config.data); + add_existing(phy, config.data); + add_ifname(config.data); + drop_inactive(config.data); -add_ifname(new_config); -config.update(new_config); + add_ifname(new_config); + config.update(new_config); + + drop_inactive(config.data); + delete_ifname(config.data); + writefile(statefile, sprintf("%J", config.data)); + }, + get_macaddr: function(args) { + let data = {}; + + for (let arg in args) { + arg = split(arg, "=", 2); + data[arg[0]] = arg[1]; + } + + let macaddr = wdev_generate_macaddr(phy, data); + if (!macaddr) { + warn(`Could not get MAC address for phy ${phy}\n`); + exit(1); + } + + print(macaddr + "\n"); + }, +}; + +let command = shift(ARGV); + +if (!phy || !command | !commands[command]) + usage(); + +if (!readfile(`/sys/class/ieee80211/${phy}/index`)) { + warn(`PHY ${phy} does not exist\n`); + exit(1); +} -drop_inactive(config.data); -delete_ifname(config.data); -writefile(statefile, sprintf("%J", config.data)); +commands[command](ARGV); -- 2.30.2