hostapd: support dynamic reload of vlan files when renaming interfaces

Avoids unnecessary AP restart on ifname changes when wifi-vlan sections
are present.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Felix Fietkau 2023-09-15 14:25:23 +02:00
parent 99515fbc36
commit 50e16efd41
2 changed files with 94 additions and 5 deletions

View File

@ -215,6 +215,7 @@ function bss_remove_file_fields(config)
for (let key in config.hash)
new_cfg.hash[key] = config.hash[key];
delete new_cfg.hash.wpa_psk_file;
delete new_cfg.hash.vlan_file;
return new_cfg;
}
@ -475,11 +476,12 @@ function iface_reload_config(phydev, config, old_config)
bss_remove_file_fields(bss_list_cfg[i]))) {
hostapd.printf(`Update config data files for bss ${ifname}`);
if (bss.set_config(config_inline, i, true) < 0) {
hostapd.printf(`Failed to update config data files for bss ${ifname}`);
hostapd.printf(`Could not update config data files for bss ${ifname}`);
return false;
} else {
bss.ctrl("RELOAD_WPA_PSK");
continue;
}
bss.ctrl("RELOAD_WPA_PSK");
continue;
}
bss_reload_psk(bss, config.bss[i], bss_list_cfg[i]);
@ -487,8 +489,6 @@ function iface_reload_config(phydev, config, old_config)
continue;
hostapd.printf(`Reload config for bss '${config.bss[0].ifname}' on phy '${phy}'`);
hostapd.printf(`old: ${bss_remove_file_fields(bss_list_cfg[i])}`);
hostapd.printf(`new: ${bss_remove_file_fields(config.bss[i])}`);
if (bss.set_config(config_inline, i) < 0) {
hostapd.printf(`Failed to set config for bss ${ifname}`);
return false;

View File

@ -111,6 +111,94 @@ uc_hostapd_remove_iface(uc_vm_t *vm, size_t nargs)
return NULL;
}
static struct hostapd_vlan *
bss_conf_find_vlan(struct hostapd_bss_config *bss, int id)
{
struct hostapd_vlan *vlan;
for (vlan = bss->vlan; vlan; vlan = vlan->next)
if (vlan->vlan_id == id)
return vlan;
return NULL;
}
static int
bss_conf_rename_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
const char *ifname)
{
if (!strcmp(ifname, vlan->ifname))
return 0;
hostapd_drv_if_rename(hapd, WPA_IF_AP_VLAN, vlan->ifname, ifname);
os_strlcpy(vlan->ifname, ifname, sizeof(vlan->ifname));
return 0;
}
static int
bss_reload_vlans(struct hostapd_data *hapd, struct hostapd_bss_config *bss)
{
struct hostapd_bss_config *old_bss = hapd->conf;
struct hostapd_vlan *vlan, *vlan_new, *wildcard;
char ifname[IFNAMSIZ + 1], vlan_ifname[IFNAMSIZ + 1], *pos;
int ret;
vlan = bss_conf_find_vlan(old_bss, VLAN_ID_WILDCARD);
wildcard = bss_conf_find_vlan(bss, VLAN_ID_WILDCARD);
if (!!vlan != !!wildcard)
return -1;
if (vlan && wildcard && strcmp(vlan->ifname, wildcard->ifname) != 0)
strcpy(vlan->ifname, wildcard->ifname);
else
wildcard = NULL;
for (vlan = bss->vlan; vlan; vlan = vlan->next) {
if (vlan->vlan_id == VLAN_ID_WILDCARD ||
vlan->dynamic_vlan > 0)
continue;
if (!bss_conf_find_vlan(old_bss, vlan->vlan_id))
return -1;
}
for (vlan = old_bss->vlan; vlan; vlan = vlan->next) {
if (vlan->vlan_id == VLAN_ID_WILDCARD)
continue;
if (vlan->dynamic_vlan == 0) {
vlan_new = bss_conf_find_vlan(bss, vlan->vlan_id);
if (!vlan_new)
return -1;
if (bss_conf_rename_vlan(hapd, vlan, vlan_new->ifname))
return -1;
continue;
}
if (!wildcard)
continue;
os_strlcpy(ifname, wildcard->ifname, sizeof(ifname));
pos = os_strchr(ifname, '#');
if (!pos)
return -1;
*pos++ = '\0';
ret = os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s%d%s",
ifname, vlan->vlan_id, pos);
if (os_snprintf_error(sizeof(vlan_ifname), ret))
return -1;
if (bss_conf_rename_vlan(hapd, vlan, vlan_ifname))
return -1;
}
return 0;
}
static uc_value_t *
uc_hostapd_bss_set_config(uc_vm_t *vm, size_t nargs)
{
@ -150,6 +238,7 @@ uc_hostapd_bss_set_config(uc_vm_t *vm, size_t nargs)
} while (0)
swap_field(ssid.wpa_psk_file);
ret = bss_reload_vlans(hapd, bss);
goto done;
}