madwifi: make sure that minstrel rc updates still work after a jiffies wraparound
[openwrt.git] / package / madwifi / patches / 451-ibss_race_fix.patch
1 --- a/net80211/ieee80211_input.c
2 +++ b/net80211/ieee80211_input.c
3 @@ -294,10 +294,10 @@ ieee80211_input(struct ieee80211vap * va
4                         break;
5                 case IEEE80211_M_IBSS:
6                 case IEEE80211_M_AHDEMO:
7 -                       if (!IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid) ||
8 +                       if ((!IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid) ||
9                             (!IEEE80211_ADDR_EQ(wh->i_addr1, vap->iv_myaddr) &&
10 -                            !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
11 -                            (subtype != IEEE80211_FC0_SUBTYPE_BEACON))) {
12 +                            !IEEE80211_IS_MULTICAST(wh->i_addr1))) &&
13 +                            (type == IEEE80211_FC0_TYPE_DATA)) {
14                                 if (!(vap->iv_dev->flags & IFF_PROMISC)) {
15                                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
16                                                 bssid, NULL, "%s", "not to bss");
17 @@ -322,22 +322,15 @@ ieee80211_input(struct ieee80211vap * va
18                         }
19                         /* Do not try to find a node reference if the packet really did come from the BSS */
20                         if (type == IEEE80211_FC0_TYPE_DATA && ni == vap->iv_bss &&
21 -                                       !IEEE80211_ADDR_EQ(vap->iv_bss->ni_macaddr, wh->i_addr2) &&
22                                         IEEE80211_ADDR_EQ(vap->iv_bssid, wh->i_addr3)) {
23                                 /* Try to find sender in local node table. */
24 -                               ni = ieee80211_find_node(&ic->ic_sta, wh->i_addr2);
25 +                               if (!ni_or_null) {
26 +                                       ieee80211_unref_node(&ni);
27 +                                       ni = ieee80211_find_txnode(vap, wh->i_addr2);
28 +                               }
29                                 if (ni == NULL) {
30 -                                       /*
31 -                                        * Fake up a node for this newly discovered
32 -                                        * member of the IBSS.  This should probably
33 -                                        * done after an ACL check.
34 -                                        */
35 -                                       ni = ieee80211_fakeup_adhoc_node(vap,
36 -                                                       wh->i_addr2);
37 -                                       if (ni == NULL) {
38 -                                               /* NB: stat kept for alloc failure */
39 -                                               goto err;
40 -                                       }
41 +                                       /* NB: stat kept for alloc failure */
42 +                                       goto discard;
43                                 }
44                         }
45                         iwspy_event(vap, ni, rssi);
46 @@ -3553,8 +3546,8 @@ ieee80211_recv_mgmt(struct ieee80211vap 
47                                 (((vap->iv_opmode == IEEE80211_M_HOSTAP) ||
48                                  (vap->iv_opmode == IEEE80211_M_WDS)) &&
49                                 (scan.capinfo & IEEE80211_CAPINFO_ESS))) {
50 +                       struct ieee80211_node *tni = NULL;
51                         struct ieee80211vap *avp = NULL;
52 -                       int do_unref = 0;
53                         int found = 0;
54  
55                         IEEE80211_LOCK_IRQ(vap->iv_ic);
56 @@ -3570,14 +3563,12 @@ ieee80211_recv_mgmt(struct ieee80211vap 
57                                         }
58                                 }
59                                 if (found)
60 -                                       ni = ni_or_null = avp->iv_wdsnode;
61 +                                       tni = ieee80211_ref_node(avp->iv_wdsnode);
62                         } else if ((vap->iv_opmode == IEEE80211_M_WDS) && vap->iv_wdsnode) {
63                                 found = 1;
64 -                               ni = ni_or_null = vap->iv_wdsnode;
65 -                       } else if (vap->iv_opmode == IEEE80211_M_IBSS) {
66 -                               ni_or_null = ieee80211_find_node(&ic->ic_sta, wh->i_addr2);
67 -                               if (ni_or_null)
68 -                                       ni = ni_or_null;
69 +                               tni = ieee80211_ref_node(vap->iv_wdsnode);
70 +                       } else if ((vap->iv_opmode == IEEE80211_M_IBSS) && (vap->iv_state == IEEE80211_S_RUN)) {
71 +                               tni = ieee80211_find_node(&ic->ic_sta, wh->i_addr2);
72                                 found = 1;
73                         }
74                         IEEE80211_UNLOCK_IRQ(vap->iv_ic);
75 @@ -3585,20 +3576,21 @@ ieee80211_recv_mgmt(struct ieee80211vap 
76                         if (!found)
77                                 break;
78  
79 -                       if (ni_or_null == NULL) {
80 +                       memcpy(&SKB_CB(skb)->beacon_tsf, scan.tstamp, sizeof(u_int64_t));
81 +
82 +                       if (tni == NULL) {
83                                 if (avp) {
84                                         IEEE80211_LOCK_IRQ(ic);
85 -                                       ni = ieee80211_add_neighbor(avp, wh, &scan);
86 +                                       tni = ieee80211_add_neighbor(avp, wh, &scan);
87                                         /* force assoc */
88 -                                       ni->ni_associd |= 0xc000;
89 -                                       avp->iv_wdsnode = ieee80211_ref_node(ni);
90 +                                       tni->ni_associd |= 0xc000;
91 +                                       avp->iv_wdsnode = ieee80211_ref_node(tni);
92                                         IEEE80211_UNLOCK_IRQ(ic);
93                                 } else if ((vap->iv_opmode == IEEE80211_M_IBSS) &&
94                                            IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid)) {
95                                         /* Create a new entry in the neighbor table. */
96 -                                       ni = ieee80211_add_neighbor(vap, wh, &scan);
97 +                                       tni = ieee80211_add_neighbor(vap, wh, &scan);
98                                 }
99 -                               do_unref = 1;
100                         } else {
101                                 /*
102                                  * Copy data from beacon to neighbor table.
103 @@ -3606,39 +3598,38 @@ ieee80211_recv_mgmt(struct ieee80211vap 
104                                  * ieee80211_add_neighbor(), so we just copy
105                                  * everything over to be safe.
106                                  */
107 -                               ni->ni_esslen = scan.ssid[1];
108 -                               memcpy(ni->ni_essid, scan.ssid + 2, scan.ssid[1]);
109 -                               IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
110 -                               memcpy(ni->ni_tstamp.data, scan.tstamp,
111 -                                       sizeof(ni->ni_tstamp));
112 -                               ni->ni_inact = ni->ni_inact_reload;
113 -                               ni->ni_intval = 
114 +                               tni->ni_esslen = scan.ssid[1];
115 +                               memcpy(tni->ni_essid, scan.ssid + 2, scan.ssid[1]);
116 +                               IEEE80211_ADDR_COPY(tni->ni_bssid, wh->i_addr3);
117 +                               memcpy(tni->ni_tstamp.data, scan.tstamp,
118 +                                       sizeof(tni->ni_tstamp));
119 +                               tni->ni_inact = tni->ni_inact_reload;
120 +                               tni->ni_intval =
121                                         IEEE80211_BINTVAL_SANITISE(scan.bintval);
122 -                               ni->ni_capinfo = scan.capinfo;
123 -                               ni->ni_chan = ic->ic_curchan;
124 -                               ni->ni_fhdwell = scan.fhdwell;
125 -                               ni->ni_fhindex = scan.fhindex;
126 -                               ni->ni_erp = scan.erp;
127 -                               ni->ni_timoff = scan.timoff;
128 +                               tni->ni_capinfo = scan.capinfo;
129 +                               tni->ni_chan = ic->ic_curchan;
130 +                               tni->ni_fhdwell = scan.fhdwell;
131 +                               tni->ni_fhindex = scan.fhindex;
132 +                               tni->ni_erp = scan.erp;
133 +                               tni->ni_timoff = scan.timoff;
134                                 if (scan.wme != NULL)
135 -                                       ieee80211_saveie(&ni->ni_wme_ie, scan.wme);
136 +                                       ieee80211_saveie(&tni->ni_wme_ie, scan.wme);
137                                 if (scan.wpa != NULL)
138 -                                       ieee80211_saveie(&ni->ni_wpa_ie, scan.wpa);
139 +                                       ieee80211_saveie(&tni->ni_wpa_ie, scan.wpa);
140                                 if (scan.rsn != NULL)
141 -                                       ieee80211_saveie(&ni->ni_rsn_ie, scan.rsn);
142 +                                       ieee80211_saveie(&tni->ni_rsn_ie, scan.rsn);
143                                 if (scan.ath != NULL)
144 -                                       ieee80211_saveath(ni, scan.ath);
145 +                                       ieee80211_saveath(tni, scan.ath);
146  
147                                 /* NB: must be after ni_chan is setup */
148 -                               ieee80211_setup_rates(ni, scan.rates,
149 +                               ieee80211_setup_rates(tni, scan.rates,
150                                         scan.xrates, IEEE80211_F_DOSORT);
151                         }
152 -                       if (ni != NULL) {
153 -                               ni->ni_rssi = rssi;
154 -                               ni->ni_rtsf = rtsf;
155 -                               ni->ni_last_rx = jiffies;
156 -                               if (do_unref)
157 -                                       ieee80211_unref_node(&ni);
158 +                       if (tni != NULL) {
159 +                               tni->ni_rssi = rssi;
160 +                               tni->ni_rtsf = rtsf;
161 +                               tni->ni_last_rx = jiffies;
162 +                               ieee80211_unref_node(&tni);
163                         }
164                 }
165                 break;
166 --- a/net80211/ieee80211_node.c
167 +++ b/net80211/ieee80211_node.c
168 @@ -53,6 +53,7 @@
169  
170  #include <net80211/ieee80211_var.h>
171  #include <net80211/if_athproto.h>
172 +#include <net80211/ieee80211_node.h>
173  
174  /*
175   * Association IDs are managed with a bit vector.
176 @@ -317,16 +318,11 @@ ieee80211_create_ibss(struct ieee80211va
177         /* Check to see if we already have a node for this mac
178          * NB: we gain a node reference here
179          */
180 -       ni = ieee80211_find_txnode(vap, vap->iv_myaddr);
181 +       ieee80211_node_table_reset(&ic->ic_sta, vap);
182 +       ni = ieee80211_alloc_node_table(vap, vap->iv_myaddr);
183         if (ni == NULL) {
184 -               ni = ieee80211_alloc_node_table(vap, vap->iv_myaddr);
185 -               IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
186 -                                 "%s: ni:%p allocated for " MAC_FMT "\n",
187 -                                 __func__, ni, MAC_ADDR(vap->iv_myaddr));
188 -               if (ni == NULL) {
189 -                       /* XXX recovery? */
190 -                       return;
191 -               }
192 +               /* XXX recovery? */
193 +               return;
194         }
195  
196         IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_myaddr);
197 @@ -647,7 +643,7 @@ ieee80211_sta_join1(struct ieee80211_nod
198                 (vap->iv_state == IEEE80211_S_RUN) && bssid_equal(obss, selbs)); */
199         vap->iv_bss = selbs;
200         IEEE80211_ADDR_COPY(vap->iv_bssid, selbs->ni_bssid);
201 -       if (obss != NULL) {
202 +       if ((obss != NULL) && (obss != selbs)) {
203                 if (obss->ni_table)
204                         ieee80211_node_leave(obss);
205                 ieee80211_unref_node(&obss);
206 --- a/ath/if_ath.c
207 +++ b/ath/if_ath.c
208 @@ -6625,14 +6625,6 @@ ath_recv_mgmt(struct ieee80211vap * vap,
209  
210         sc->sc_recv_mgmt(vap, ni_or_null, skb, subtype, rssi, rtsf);
211  
212 -       /* Lookup the new node if any (this grabs a reference to it) */
213 -       ni = ieee80211_find_rxnode(vap->iv_ic, vap,
214 -                (const struct ieee80211_frame_min *)skb->data);
215 -       if (ni == NULL) {
216 -               DPRINTF(sc, ATH_DEBUG_BEACON, "Dropping; node unknown.\n");
217 -               return;
218 -       }
219 -
220         switch (subtype) {
221         case IEEE80211_FC0_SUBTYPE_BEACON:
222                 /* update RSSI statistics for use by the HAL */
223 @@ -6654,11 +6646,9 @@ ath_recv_mgmt(struct ieee80211vap * vap,
224                          * we do the IBSS merging in software. Also do not merge
225                          * if the difference it too small. Otherwise we are playing
226                          * tsf-pingpong with other vendors drivers */
227 -                       beacon_tsf = le64_to_cpu(ni->ni_tstamp.tsf);
228 -                       if (beacon_tsf > rtsf + 0xffff) {
229 +                       beacon_tsf = le64_to_cpu(SKB_CB(skb)->beacon_tsf);
230 +                       if (beacon_tsf > rtsf + 0xffff)
231                                 ath_hal_settsf64(sc->sc_ah, beacon_tsf - rtsf);
232 -                               ieee80211_ibss_merge(ni);
233 -                       }
234                         break;
235                 }
236                 /* NB: Fall Through */
237 @@ -6680,13 +6670,21 @@ ath_recv_mgmt(struct ieee80211vap * vap,
238                         hw_tsf = ath_hal_gettsf64(sc->sc_ah);
239                         hw_tu  = hw_tsf >> 10;
240  
241 -                       beacon_tsf = le64_to_cpu(ni->ni_tstamp.tsf);
242 +                       beacon_tsf = le64_to_cpu(SKB_CB(skb)->beacon_tsf);
243                         beacon_tu  = beacon_tsf >> 10;
244  
245 +                       if (!beacon_tsf)
246 +                               break;
247 +
248 +                       if (IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid))
249 +                               break;
250 +
251                         DPRINTF(sc, ATH_DEBUG_BEACON,
252 -                                       "Beacon transmitted at %10llx, "
253 +                                       "Beacon transmitted from "MAC_FMT" ("MAC_FMT") at %10llx, "
254                                         "received at %10llx(%lld), hw TSF "
255                                         "%10llx(%lld)\n",
256 +                                       MAC_ADDR(wh->i_addr3),
257 +                                       MAC_ADDR(vap->iv_bssid),
258                                         beacon_tsf,
259                                         rtsf, rtsf - beacon_tsf,
260                                         hw_tsf, hw_tsf - beacon_tsf);
261 @@ -6699,39 +6697,13 @@ ath_recv_mgmt(struct ieee80211vap * vap,
262                                 do_merge = 1;
263                         }
264  
265 -                       /* Check sc_nexttbtt */
266 -                       if (sc->sc_nexttbtt < hw_tu) {
267 -                               DPRINTF(sc, ATH_DEBUG_BEACON,
268 -                                       "sc_nexttbtt (%8x TU) is in the past "
269 -                                       "(tsf %8x TU), updating timers\n",
270 -                                       sc->sc_nexttbtt, hw_tu);
271 -                               do_merge = 1;
272 -                       }
273 -
274 -                       intval = ni->ni_intval & HAL_BEACON_PERIOD;
275 -#if 0
276 -                       /* This code is disabled since it would produce
277 -                        * unwanted merge. For instance, in a two nodes network
278 -                        * A & B, A can merge to B and at the same time, B will
279 -                        * merge to A, still having a split */
280 -                       if (intval != 0) {
281 -                               if ((sc->sc_nexttbtt % intval) !=
282 -                                               (beacon_tu % intval)) {
283 -                                       DPRINTF(sc, ATH_DEBUG_BEACON,
284 -                                                       "ibss merge: "
285 -                                                       "sc_nexttbtt %10x TU "
286 -                                                       "(%3d) beacon %10x TU "
287 -                                                       "(%3d)\n",
288 -                                                       sc->sc_nexttbtt,
289 -                                                       sc->sc_nexttbtt % intval,
290 -                                                       beacon_tu,
291 -                                                       beacon_tu % intval);
292 -                                       do_merge = 1;
293 -                               }
294 -                       }
295 -#endif
296 -                       if (do_merge)
297 +                       if (do_merge) {
298 +                               /* Lookup the new node if any (this grabs a reference to it) */
299 +                               ni = ieee80211_find_txnode(vap, wh->i_addr2);
300 +                               memcpy(ni->ni_bssid, wh->i_addr3, IEEE80211_ADDR_LEN);
301                                 ieee80211_ibss_merge(ni);
302 +                               ieee80211_unref_node(&ni);
303 +                       }
304  
305                         if ((sc->sc_opmode == HAL_M_IBSS) &&
306                                         ath_hw_check_atim(sc, 1, vap->iv_bss->ni_intval))
307 @@ -6739,8 +6711,6 @@ ath_recv_mgmt(struct ieee80211vap * vap,
308                 }
309                 break;
310         }
311 -
312 -       ieee80211_unref_node(&ni);
313  }
314  
315  static void
316 --- a/net80211/ieee80211_linux.h
317 +++ b/net80211/ieee80211_linux.h
318 @@ -411,7 +411,7 @@ typedef spinlock_t acl_lock_t;
319   *     8 bytes so we reserve/avoid it.
320   */
321         struct ieee80211_cb {
322 -       u_int8_t vlan[8];                       /* reserve for vlan tag info */
323 +       u_int64_t beacon_tsf;
324         struct ieee80211_node *ni;
325         u_int32_t flags;
326  #define        M_LINK0         0x01                    /* frame needs WEP encryption */
327 --- a/net80211/ieee80211_scan_sta.c
328 +++ b/net80211/ieee80211_scan_sta.c
329 @@ -1125,11 +1125,8 @@ adhoc_default_action(struct ieee80211vap
330         u_int8_t zeroMacAddr[IEEE80211_ADDR_LEN];
331  
332         memset(&zeroMacAddr, 0, IEEE80211_ADDR_LEN);
333 -       if (IEEE80211_ADDR_EQ(se->se_bssid, &zeroMacAddr[0])) {
334 -               ieee80211_create_ibss(vap, se->se_chan);
335 -               return 1;
336 -       } else
337 -               return ieee80211_sta_join(vap, se);
338 +       ieee80211_create_ibss(vap, se->se_chan);
339 +       return 1;
340  }
341  
342  static const struct ieee80211_scanner adhoc_default = {