hostapd: update to version 2014-04-24, fixes some dfs related issues
[openwrt/svn-archive/archive.git] / package / network / services / hostapd / patches / 440-dynamic_20_40_mhz.patch
1 --- a/hostapd/config_file.c
2 +++ b/hostapd/config_file.c
3 @@ -2648,6 +2648,10 @@ static int hostapd_config_fill(struct ho
4 line);
5 return 1;
6 }
7 + } else if (os_strcmp(buf, "dynamic_ht40") == 0) {
8 + conf->dynamic_ht40 = atoi(pos);
9 + if (conf->dynamic_ht40 == 1)
10 + conf->dynamic_ht40 = 1500;
11 } else if (os_strcmp(buf, "require_ht") == 0) {
12 conf->require_ht = atoi(pos);
13 } else if (os_strcmp(buf, "obss_interval") == 0) {
14 --- a/src/ap/ap_config.h
15 +++ b/src/ap/ap_config.h
16 @@ -580,6 +580,7 @@ struct hostapd_config {
17 int ieee80211n;
18 int secondary_channel;
19 int require_ht;
20 + int dynamic_ht40;
21 int obss_interval;
22 u32 vht_capab;
23 int ieee80211ac;
24 --- a/src/ap/hostapd.c
25 +++ b/src/ap/hostapd.c
26 @@ -22,6 +22,7 @@
27 #include "beacon.h"
28 #include "iapp.h"
29 #include "ieee802_1x.h"
30 +#include "ieee802_11.h"
31 #include "ieee802_11_auth.h"
32 #include "vlan_init.h"
33 #include "wpa_auth.h"
34 @@ -328,6 +329,7 @@ static void hostapd_cleanup(struct hosta
35 static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
36 {
37 wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
38 + hostapd_deinit_ht(iface);
39 hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
40 iface->hw_features = NULL;
41 os_free(iface->current_rates);
42 --- a/src/ap/hostapd.h
43 +++ b/src/ap/hostapd.h
44 @@ -330,6 +330,9 @@ struct hostapd_iface {
45 /* Overlapping BSS information */
46 int olbc_ht;
47
48 + int force_20mhz;
49 + struct os_time last_20mhz_trigger;
50 +
51 u16 ht_op_mode;
52
53 /* surveying helpers */
54 --- a/src/ap/ieee802_11.c
55 +++ b/src/ap/ieee802_11.c
56 @@ -1556,6 +1556,9 @@ static void handle_beacon(struct hostapd
57 sizeof(mgmt->u.beacon)), &elems,
58 0);
59
60 + if (!elems.ht_capabilities)
61 + hostapd_trigger_20mhz(hapd->iface);
62 +
63 ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
64 }
65
66 --- a/src/ap/ieee802_11.h
67 +++ b/src/ap/ieee802_11.h
68 @@ -83,4 +83,17 @@ int hostapd_update_time_adv(struct hosta
69 void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr);
70 u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid);
71
72 +#ifdef CONFIG_IEEE80211N
73 +void hostapd_trigger_20mhz(struct hostapd_iface *iface);
74 +void hostapd_deinit_ht(struct hostapd_iface *iface);
75 +
76 +#else
77 +static inline void hostapd_deinit_ht(struct hostapd_iface *iface)
78 +{
79 +}
80 +static inline void hostapd_trigger_20mhz(struct hostapd_iface *iface)
81 +{
82 +}
83 +#endif /* CONFIG_IEEE80211N */
84 +
85 #endif /* IEEE802_11_H */
86 --- a/src/ap/ieee802_11_ht.c
87 +++ b/src/ap/ieee802_11_ht.c
88 @@ -13,9 +13,11 @@
89 #include "common/ieee802_11_defs.h"
90 #include "hostapd.h"
91 #include "ap_config.h"
92 +#include "ap_drv_ops.h"
93 #include "sta_info.h"
94 #include "beacon.h"
95 #include "ieee802_11.h"
96 +#include "utils/eloop.h"
97
98
99 u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
100 @@ -92,6 +94,9 @@ u8 * hostapd_eid_ht_operation(struct hos
101
102 oper->primary_chan = hapd->iconf->channel;
103 oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode);
104 + if (hapd->iface->force_20mhz)
105 + goto skip;
106 +
107 if (hapd->iconf->secondary_channel == 1)
108 oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
109 HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
110 @@ -99,6 +104,7 @@ u8 * hostapd_eid_ht_operation(struct hos
111 oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
112 HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
113
114 +skip:
115 pos += sizeof(*oper);
116
117 return pos;
118 @@ -288,3 +294,84 @@ void hostapd_get_ht_capab(struct hostapd
119
120 neg_ht_cap->ht_capabilities_info = host_to_le16(cap);
121 }
122 +
123 +static void hostapd_set_force_20mhz(struct hostapd_iface *iface);
124 +
125 +static void hostapd_restore_40mhz(void *eloop_data, void *user_ctx)
126 +{
127 + struct hostapd_iface *iface = eloop_data;
128 + struct os_time time;
129 + int timeout;
130 +
131 + if (!iface->last_20mhz_trigger.sec)
132 + return;
133 +
134 + os_get_time(&time);
135 + timeout = iface->last_20mhz_trigger.sec + iface->conf->dynamic_ht40 -
136 + time.sec;
137 +
138 + if (timeout > 0) {
139 + eloop_register_timeout(timeout, 0, hostapd_restore_40mhz,
140 + iface, NULL);
141 + return;
142 + }
143 +
144 + iface->last_20mhz_trigger.sec = 0;
145 + iface->last_20mhz_trigger.usec = 0;
146 +
147 + iface->force_20mhz = 0;
148 + hostapd_set_force_20mhz(iface);
149 +}
150 +
151 +static void hostapd_set_force_20mhz(struct hostapd_iface *iface)
152 +{
153 + int secondary_channel;
154 + int i;
155 +
156 + ieee802_11_set_beacons(iface);
157 +
158 + for (i = 0; i < iface->num_bss; i++) {
159 + struct hostapd_data *hapd = iface->bss[i];
160 +
161 + if (iface->force_20mhz)
162 + secondary_channel = 0;
163 + else
164 + secondary_channel = hapd->iconf->secondary_channel;
165 +
166 + if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
167 + hapd->iconf->channel,
168 + hapd->iconf->ieee80211n,
169 + hapd->iconf->ieee80211ac,
170 + secondary_channel,
171 + hapd->iconf->vht_oper_chwidth,
172 + hapd->iconf->vht_oper_centr_freq_seg0_idx,
173 + hapd->iconf->vht_oper_centr_freq_seg1_idx)) {
174 + wpa_printf(MSG_ERROR, "Could not set channel for "
175 + "kernel driver");
176 + }
177 + }
178 +}
179 +
180 +void hostapd_deinit_ht(struct hostapd_iface *iface)
181 +{
182 + eloop_cancel_timeout(hostapd_restore_40mhz, iface, NULL);
183 +}
184 +
185 +void hostapd_trigger_20mhz(struct hostapd_iface *iface)
186 +{
187 + if (!iface->conf->dynamic_ht40)
188 + return;
189 +
190 + if (!iface->force_20mhz) {
191 + iface->force_20mhz = 1;
192 + hostapd_set_force_20mhz(iface);
193 + }
194 +
195 + if (!iface->last_20mhz_trigger.sec) {
196 + eloop_cancel_timeout(hostapd_restore_40mhz, iface, NULL);
197 + eloop_register_timeout(iface->conf->dynamic_ht40, 0,
198 + hostapd_restore_40mhz, iface, NULL);
199 + }
200 +
201 + os_get_time(&iface->last_20mhz_trigger);
202 +}