X-Git-Url: https://git.archive.openwrt.org/?a=blobdiff_plain;f=package%2Fnetwork%2Fservices%2Fhostapd%2Fpatches%2F440-dynamic_20_40_mhz.patch;fp=package%2Fnetwork%2Fservices%2Fhostapd%2Fpatches%2F440-dynamic_20_40_mhz.patch;h=f2d7795e81cd5878720a60fa7143b35c1c4e2698;hb=b6634a523b6cfba060ee31c3d5247c46f4dd07c4;hp=0000000000000000000000000000000000000000;hpb=01c04c225c7c6562251b1ea5a6224c19e3b0e5b4;p=openwrt.git diff --git a/package/network/services/hostapd/patches/440-dynamic_20_40_mhz.patch b/package/network/services/hostapd/patches/440-dynamic_20_40_mhz.patch new file mode 100644 index 0000000000..f2d7795e81 --- /dev/null +++ b/package/network/services/hostapd/patches/440-dynamic_20_40_mhz.patch @@ -0,0 +1,206 @@ +--- a/hostapd/config_file.c ++++ b/hostapd/config_file.c +@@ -2422,6 +2422,10 @@ static int hostapd_config_fill(struct ho + "ht_capab", line); + errors++; + } ++ } else if (os_strcmp(buf, "dynamic_ht40") == 0) { ++ conf->dynamic_ht40 = atoi(pos); ++ if (conf->dynamic_ht40 == 1) ++ conf->dynamic_ht40 = 1500; + } else if (os_strcmp(buf, "require_ht") == 0) { + conf->require_ht = atoi(pos); + } else if (os_strcmp(buf, "obss_interval") == 0) { +--- a/src/ap/ap_config.h ++++ b/src/ap/ap_config.h +@@ -531,6 +531,7 @@ struct hostapd_config { + int ieee80211n; + int secondary_channel; + int require_ht; ++ int dynamic_ht40; + int obss_interval; + u32 vht_capab; + int ieee80211ac; +--- a/src/ap/hostapd.c ++++ b/src/ap/hostapd.c +@@ -23,6 +23,7 @@ + #include "beacon.h" + #include "iapp.h" + #include "ieee802_1x.h" ++#include "ieee802_11.h" + #include "ieee802_11_auth.h" + #include "vlan_init.h" + #include "wpa_auth.h" +@@ -329,6 +330,7 @@ static void hostapd_cleanup(struct hosta + static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface) + { + wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); ++ hostapd_deinit_ht(iface); + hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); + iface->hw_features = NULL; + os_free(iface->current_rates); +--- a/src/ap/hostapd.h ++++ b/src/ap/hostapd.h +@@ -326,6 +326,9 @@ struct hostapd_iface { + /* Overlapping BSS information */ + int olbc_ht; + ++ int force_20mhz; ++ struct os_time last_20mhz_trigger; ++ + u16 ht_op_mode; + + /* surveying helpers */ +--- a/src/ap/ieee802_11.c ++++ b/src/ap/ieee802_11.c +@@ -1538,6 +1538,9 @@ static void handle_beacon(struct hostapd + sizeof(mgmt->u.beacon)), &elems, + 0); + ++ if (!elems.ht_capabilities) ++ hostapd_trigger_20mhz(hapd->iface); ++ + ap_list_process_beacon(hapd->iface, mgmt, &elems, fi); + } + +--- a/src/ap/ieee802_11.h ++++ b/src/ap/ieee802_11.h +@@ -82,4 +82,17 @@ int hostapd_update_time_adv(struct hosta + void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr); + u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid); + ++#ifdef CONFIG_IEEE80211N ++void hostapd_trigger_20mhz(struct hostapd_iface *iface); ++void hostapd_deinit_ht(struct hostapd_iface *iface); ++ ++#else ++static inline void hostapd_deinit_ht(struct hostapd_iface *iface) ++{ ++} ++static inline void hostapd_trigger_20mhz(struct hostapd_iface *iface) ++{ ++} ++#endif /* CONFIG_IEEE80211N */ ++ + #endif /* IEEE802_11_H */ +--- a/src/ap/ieee802_11_ht.c ++++ b/src/ap/ieee802_11_ht.c +@@ -20,9 +20,11 @@ + #include "drivers/driver.h" + #include "hostapd.h" + #include "ap_config.h" ++#include "ap_drv_ops.h" + #include "sta_info.h" + #include "beacon.h" + #include "ieee802_11.h" ++#include "utils/eloop.h" + + + u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid) +@@ -86,12 +88,15 @@ u8 * hostapd_eid_ht_operation(struct hos + + oper->control_chan = hapd->iconf->channel; + oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode); +- if (hapd->iconf->secondary_channel == 1) +- oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE | +- HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH; +- if (hapd->iconf->secondary_channel == -1) +- oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW | +- HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH; ++ ++ if (!hapd->iface->force_20mhz) { ++ if (hapd->iconf->secondary_channel == 1) ++ oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE | ++ HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH; ++ if (hapd->iconf->secondary_channel == -1) ++ oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW | ++ HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH; ++ } + + pos += sizeof(*oper); + +@@ -286,3 +291,84 @@ void hostapd_get_ht_capab(struct hostapd + + neg_ht_cap->ht_capabilities_info = host_to_le16(cap); + } ++ ++static void hostapd_set_force_20mhz(struct hostapd_iface *iface); ++ ++static void hostapd_restore_40mhz(void *eloop_data, void *user_ctx) ++{ ++ struct hostapd_iface *iface = eloop_data; ++ struct os_time time; ++ int timeout; ++ ++ if (!iface->last_20mhz_trigger.sec) ++ return; ++ ++ os_get_time(&time); ++ timeout = iface->last_20mhz_trigger.sec + iface->conf->dynamic_ht40 - ++ time.sec; ++ ++ if (timeout > 0) { ++ eloop_register_timeout(timeout, 0, hostapd_restore_40mhz, ++ iface, NULL); ++ return; ++ } ++ ++ iface->last_20mhz_trigger.sec = 0; ++ iface->last_20mhz_trigger.usec = 0; ++ ++ iface->force_20mhz = 0; ++ hostapd_set_force_20mhz(iface); ++} ++ ++static void hostapd_set_force_20mhz(struct hostapd_iface *iface) ++{ ++ int secondary_channel; ++ int i; ++ ++ ieee802_11_set_beacons(iface); ++ ++ for (i = 0; i < iface->num_bss; i++) { ++ struct hostapd_data *hapd = iface->bss[i]; ++ ++ if (iface->force_20mhz) ++ secondary_channel = 0; ++ else ++ secondary_channel = hapd->iconf->secondary_channel; ++ ++ if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq, ++ hapd->iconf->channel, ++ hapd->iconf->ieee80211n, ++ hapd->iconf->ieee80211ac, ++ secondary_channel, ++ hapd->iconf->vht_oper_chwidth, ++ hapd->iconf->vht_oper_centr_freq_seg0_idx, ++ hapd->iconf->vht_oper_centr_freq_seg1_idx)) { ++ wpa_printf(MSG_ERROR, "Could not set channel for " ++ "kernel driver"); ++ } ++ } ++} ++ ++void hostapd_deinit_ht(struct hostapd_iface *iface) ++{ ++ eloop_cancel_timeout(hostapd_restore_40mhz, iface, NULL); ++} ++ ++void hostapd_trigger_20mhz(struct hostapd_iface *iface) ++{ ++ if (!iface->conf->dynamic_ht40) ++ return; ++ ++ if (!iface->force_20mhz) { ++ iface->force_20mhz = 1; ++ hostapd_set_force_20mhz(iface); ++ } ++ ++ if (!iface->last_20mhz_trigger.sec) { ++ eloop_cancel_timeout(hostapd_restore_40mhz, iface, NULL); ++ eloop_register_timeout(iface->conf->dynamic_ht40, 0, ++ hostapd_restore_40mhz, iface, NULL); ++ } ++ ++ os_get_time(&iface->last_20mhz_trigger); ++}