Changeset 2725
- Timestamp:
- 10/05/07 07:58:04 (1 year ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
madwifi/branches/madwifi-dfs/net80211/ieee80211_scan_ap.c
r2530 r2725 53 53 #include <net80211/ieee80211_var.h> 54 54 55 #define AP_PURGE_SCANS 2 /* age for purging entries (scans) */ 56 #define RSSI_LPF_LEN 10 57 #define RSSI_EP_MULTIPLIER (1<<7) /* pow2 to optimize out * and / */ 58 #define RSSI_IN(x) ((x) * RSSI_EP_MULTIPLIER) 59 #define LPF_RSSI(x, y, len) (((x) * ((len) - 1) + (y)) / (len)) 60 #define RSSI_LPF(x, y) do { \ 61 if ((y) >= -20) \ 62 x = LPF_RSSI((x), RSSI_IN((y)), RSSI_LPF_LEN); \ 63 } while (0) 64 #define EP_RND(x, mul) \ 65 ((((x)%(mul)) >= ((mul)/2)) ? howmany(x, mul) : (x)/(mul)) 66 #define RSSI_GET(x) EP_RND(x, RSSI_EP_MULTIPLIER) 67 #define AP_HASHSIZE 32 68 /* simple hash is enough for variation of macaddr */ 69 #define AP_HASH(addr) \ 70 (((const u_int8_t *)(addr))[IEEE80211_ADDR_LEN - 1] % AP_HASHSIZE) 71 #define SCAN_AP_LOCK_INIT(_st, _name) \ 72 spin_lock_init(&(_st)->as_lock) 73 #define SCAN_AP_LOCK_DESTROY(_st) 74 #define SCAN_AP_LOCK_IRQ(_st) do { \ 75 unsigned long __stlockflags; \ 76 spin_lock_irqsave(&(_st)->as_lock, __stlockflags); 77 #define SCAN_AP_UNLOCK_IRQ(_st) \ 78 spin_unlock_irqrestore(&(_st)->as_lock, __stlockflags); \ 79 } while (0) 80 #define SCAN_AP_UNLOCK_IRQ_EARLY(_st) \ 81 spin_unlock_irqrestore(&(_st)->as_lock, __stlockflags); 82 83 #define SCAN_AP_GEN_LOCK_INIT(_st, _name) \ 84 spin_lock_init(&(_st)->as_scanlock) 85 #define SCAN_AP_GEN_LOCK_DESTROY(_st) 86 #define SCAN_AP_GEN_LOCK(_st) spin_lock(&(_st)->as_scanlock); 87 #define SCAN_AP_GEN_UNLOCK(_st) spin_unlock(&(_st)->as_scanlock); 88 89 struct scan_entry { 90 struct ieee80211_scan_entry base; 91 TAILQ_ENTRY(scan_entry) se_list; 92 LIST_ENTRY(scan_entry) se_hash; 93 u_int8_t se_seen; /* seen during current scan */ 94 u_int8_t se_notseen; /* not seen in previous scans */ 95 u_int32_t se_avgrssi; /* LPF rssi state */ 96 unsigned long se_lastupdate; /* time of last update */ 97 unsigned long se_lastfail; /* time of last failure */ 98 unsigned long se_lastassoc; /* time of last association */ 99 u_int se_scangen; /* iterator scan gen# */ 100 }; 101 55 102 struct ap_state { 56 int as_maxrssi[IEEE80211_CHAN_MAX]; 103 unsigned int as_vap_desired_mode; /* Used for channel selection, vap->iv_des_mode */ 104 unsigned int as_required_mode; /* Used for channel selection, filtered version of as_vap_desired_mode */ 105 int as_maxrssi[IEEE80211_CHAN_MAX]; /* Used for channel selection */ 106 107 /* These fields are just for scan caching for returning responses to 108 * wireless extensions. i.e. show peers, APs, etc. */ 109 spinlock_t as_lock; /* on scan table */ 110 int as_newscan; /* trigger for updating seen/not-seen for aging */ 111 TAILQ_HEAD(, scan_entry) as_entry; /* all entries */ 112 ATH_LIST_HEAD(, scan_entry) as_hash[AP_HASHSIZE]; 113 spinlock_t as_scanlock; /* on as_scangen */ 114 u_int as_scangen; /* gen# for iterator */ 115 57 116 struct IEEE80211_TQ_STRUCT as_actiontq; /* tasklet for "action" */ 58 117 struct ieee80211_scan_entry as_selbss; /* selected bss for action tasklet */ … … 62 121 static int ap_flush(struct ieee80211_scan_state *); 63 122 static void action_tasklet(IEEE80211_TQUEUE_ARG); 123 static struct ieee80211_channel *find11gchannel(struct ieee80211com *ic, int i, int freq); 124 125 static const u_int chanflags[] = { 126 IEEE80211_CHAN_B, /* IEEE80211_MODE_AUTO */ 127 IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */ 128 IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */ 129 IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */ 130 IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */ 131 IEEE80211_CHAN_A, /* IEEE80211_MODE_TURBO_A */ /* for turbo mode look for AP in normal channel */ 132 IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_TURBO_G */ 133 IEEE80211_CHAN_ST, /* IEEE80211_MODE_TURBO_STATIC_A */ 134 }; 135 136 static const u_int16_t rcl1[] = /* 8 FCC channel: 52, 56, 60, 64, 36, 40, 44, 48 */ 137 { 5260, 5280, 5300, 5320, 5180, 5200, 5220, 5240 }; 138 static const u_int16_t rcl2[] = /* 4 MKK channels: 34, 38, 42, 46 */ 139 { 5170, 5190, 5210, 5230 }; 140 static const u_int16_t rcl3[] = /* 2.4Ghz ch: 1,6,11,7,13 */ 141 { 2412, 2437, 2462, 2442, 2472 }; 142 static const u_int16_t rcl4[] = /* 5 FCC channel: 149, 153, 161, 165 */ 143 { 5745, 5765, 5785, 5805, 5825 }; 144 static const u_int16_t rcl7[] = /* 11 ETSI channel: 100,104,108,112,116,120,124,128,132,136,140 */ 145 { 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700 }; 146 static const u_int16_t rcl8[] = /* 2.4Ghz ch: 2,3,4,5,8,9,10,12 */ 147 { 2417, 2422, 2427, 2432, 2447, 2452, 2457, 2467 }; 148 static const u_int16_t rcl9[] = /* 2.4Ghz ch: 14 */ 149 { 2484 }; 150 static const u_int16_t rcl10[] = /* Added Korean channels 2312-2372 */ 151 { 2312, 2317, 2322, 2327, 2332, 2337, 2342, 2347, 2352, 2357, 2362, 2367, 2372 }; 152 static const u_int16_t rcl11[] = /* Added Japan channels in 4.9/5.0 spectrum */ 153 { 5040, 5060, 5080, 4920, 4940, 4960, 4980 }; 154 #ifdef ATH_TURBO_SCAN 155 static const u_int16_t rcl5[] = /* 3 static turbo channels */ 156 { 5210, 5250, 5290 }; 157 static const u_int16_t rcl6[] = /* 2 static turbo channels */ 158 { 5760, 5800 }; 159 static const u_int16_t rcl6x[] = /* 4 FCC3 turbo channels */ 160 { 5540, 5580, 5620, 5660 }; 161 static const u_int16_t rcl12[] = /* 2.4Ghz Turbo channel 6 */ 162 { 2437 }; 163 static const u_int16_t rcl13[] = /* dynamic Turbo channels */ 164 { 5200, 5240, 5280, 5765, 5805 }; 165 #endif /* ATH_TURBO_SCAN */ 166 167 struct scanlist { 168 u_int16_t mode; 169 u_int16_t count; 170 const u_int16_t *list; 171 }; 172 173 #define IEEE80211_MODE_TURBO_STATIC_A IEEE80211_MODE_MAX 174 #define X(a) .count = sizeof(a)/sizeof(a[0]), .list = a 175 176 static const struct scanlist staScanTable[] = { 177 { IEEE80211_MODE_11B, X(rcl3) }, 178 { IEEE80211_MODE_11A, X(rcl1) }, 179 { IEEE80211_MODE_11A, X(rcl2) }, 180 { IEEE80211_MODE_11B, X(rcl8) }, 181 { IEEE80211_MODE_11B, X(rcl9) }, 182 { IEEE80211_MODE_11A, X(rcl4) }, 183 #ifdef ATH_TURBO_SCAN 184 { IEEE80211_MODE_TURBO_STATIC_A, X(rcl5) }, 185 { IEEE80211_MODE_TURBO_STATIC_A, X(rcl6) }, 186 { IEEE80211_MODE_TURBO_A, X(rcl6x) }, 187 { IEEE80211_MODE_TURBO_A, X(rcl13) }, 188 #endif /* ATH_TURBO_SCAN */ 189 { IEEE80211_MODE_11A, X(rcl7) }, 190 { IEEE80211_MODE_11B, X(rcl10) }, 191 { IEEE80211_MODE_11A, X(rcl11) }, 192 #ifdef ATH_TURBO_SCAN 193 { IEEE80211_MODE_TURBO_G, X(rcl12) }, 194 #endif /* ATH_TURBO_SCAN */ 195 { .list = NULL } 196 }; 197 198 #undef X 199 /* This function must be invoked with locks acquired */ 200 static void 201 add_channels(struct ieee80211com *ic, 202 struct ieee80211_scan_state *ss, 203 enum ieee80211_phymode mode, const u_int16_t freq[], int nfreq) 204 { 205 #define N(a) (sizeof(a) / sizeof(a[0])) 206 struct ieee80211_channel *c, *cg; 207 u_int modeflags; 208 int i; 209 210 KASSERT(mode < N(chanflags), ("Unexpected mode %u", mode)); 211 modeflags = chanflags[mode]; 212 for (i = 0; i < nfreq; i++) { 213 c = ieee80211_find_channel(ic, freq[i], modeflags); 214 if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee)) 215 continue; 216 if (mode == IEEE80211_MODE_AUTO) { 217 /* 218 * XXX special-case 11b/g channels so we select 219 * the g channel if both are present. 220 */ 221 if (IEEE80211_IS_CHAN_B(c) && 222 (cg = find11gchannel(ic, i, c->ic_freq)) != NULL) 223 c = cg; 224 } 225 if (ss->ss_last >= IEEE80211_SCAN_MAX) 226 break; 227 ss->ss_chans[ss->ss_last++] = c; 228 } 229 #undef N 230 } 231 232 /* This function must be invoked with locks acquired */ 233 static int 234 checktable(const struct scanlist *scan, const struct ieee80211_channel *c) 235 { 236 int i; 237 238 for (; scan->list != NULL; scan++) { 239 for (i = 0; i < scan->count; i++) 240 if (scan->list[i] == c->ic_freq) 241 return 1; 242 } 243 return 0; 244 } 64 245 65 246 /* … … 74 255 75 256 MALLOC(as, struct ap_state *, sizeof(struct ap_state), 76 M_SCANCACHE, M_NOWAIT); 257 M_80211_SCAN, M_NOWAIT | M_ZERO); 258 if (as == NULL) 259 return 0; 260 SCAN_AP_LOCK_INIT(as, "scan_ap"); 261 SCAN_AP_GEN_LOCK_INIT(as, "scan_ap_gen"); 262 TAILQ_INIT(&as->as_entry); 263 IEEE80211_INIT_TQUEUE(&as->as_actiontq, action_tasklet, ss); 77 264 ss->ss_priv = as; 78 IEEE80211_INIT_TQUEUE(&as->as_actiontq, action_tasklet, ss);79 265 ap_flush(ss); 80 266 return 1; … … 89 275 struct ap_state *as = ss->ss_priv; 90 276 91 if (as != NULL) 92 FREE(as, M_SCANCACHE); 277 if (as != NULL) { 278 ap_flush(ss); 279 IEEE80211_CANCEL_TQUEUE(&as->as_actiontq); 280 FREE(as, M_80211_SCAN); 281 } 93 282 94 283 _MOD_DEC_USE(THIS_MODULE); … … 103 292 { 104 293 struct ap_state *as = ss->ss_priv; 105 294 struct scan_entry *se, *next; 295 296 SCAN_AP_LOCK_IRQ(as); 106 297 memset(as->as_maxrssi, 0, sizeof(as->as_maxrssi)); 298 TAILQ_FOREACH_SAFE(se, &as->as_entry, se_list, next) { 299 TAILQ_REMOVE(&as->as_entry, se, se_list); 300 LIST_REMOVE(se, se_hash); 301 FREE(se, M_80211_SCAN); 302 } 107 303 ss->ss_last = 0; /* ensure no channel will be picked */ 304 SCAN_AP_UNLOCK_IRQ(as); 108 305 return 0; 109 306 } 110 307 111 static int 308 /* This function must be invoked with locks acquired */ 309 static void 310 saveie(u_int8_t **iep, const u_int8_t *ie) 311 { 312 if (ie == NULL) 313 *iep = NULL; 314 else 315 ieee80211_saveie(iep, ie); 316 } 317 318 /* This function must be invoked with locks acquired */ 319 static struct ieee80211_channel * 112 320 find11gchannel(struct ieee80211com *ic, int i, int freq) 113 321 { 114 conststruct ieee80211_channel *c;322 struct ieee80211_channel *c; 115 323 int j; 116 324 … … 123 331 c = &ic->ic_channels[j]; 124 332 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) 125 return 1;333 return c; 126 334 } 127 335 for (j = 0; j < i; j++) { 128 336 c = &ic->ic_channels[j]; 129 337 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) 130 return 1;131 } 132 return 0;338 return c; 339 } 340 return NULL; 133 341 } 134 342 … … 139 347 ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) 140 348 { 141 struct ieee80211com *ic = vap->iv_ic; 142 struct ieee80211_channel *c; 349 struct ap_state *as = ss->ss_priv; 350 struct ieee80211com *ic = NULL; 351 const struct scanlist *sl = NULL; 352 struct ieee80211_channel *c = NULL; 143 353 int i; 354 unsigned int mode = 0; 355 356 SCAN_AP_LOCK_IRQ(as); 357 ic = vap->iv_ic; 358 /* Determine mode flags to match, or leave zero for auto mode */ 359 as->as_vap_desired_mode = vap->iv_des_mode; 360 as->as_required_mode = 0; 361 if (as->as_vap_desired_mode != IEEE80211_MODE_AUTO) { 362 as->as_required_mode = chanflags[as->as_vap_desired_mode]; 363 if (vap->iv_ath_cap & IEEE80211_ATHC_TURBOP && 364 as->as_required_mode != IEEE80211_CHAN_ST) { 365 /* Fixup for dynamic turbo flags */ 366 if (as->as_vap_desired_mode == IEEE80211_MODE_11G) 367 as->as_required_mode = IEEE80211_CHAN_108G; 368 else 369 as->as_required_mode = IEEE80211_CHAN_108A; 370 } 371 } 144 372 145 373 ss->ss_last = 0; 146 if (vap->iv_des_mode == IEEE80211_MODE_AUTO) { 147 for (i = 0; i < ic->ic_nchans; i++) { 148 c = &ic->ic_channels[i]; 149 if (IEEE80211_IS_CHAN_TURBO(c)) { 150 /* XR is not supported on turbo channels */ 151 if (vap->iv_ath_cap & IEEE80211_ATHC_XR) 152 continue; 153 /* dynamic channels are scanned in base mode */ 154 if (!IEEE80211_IS_CHAN_ST(c)) 155 continue; 156 } else { 157 /* 158 * Use any 11g channel instead of 11b one. 159 */ 160 if (IEEE80211_IS_CHAN_B(c) && 161 find11gchannel(ic, i, c->ic_freq)) 162 continue; 163 } 164 if (c->ic_flags & IEEE80211_CHAN_RADAR) 165 continue; 166 if (ss->ss_last >= IEEE80211_SCAN_MAX) 167 break; 168 ss->ss_chans[ss->ss_last++] = c; 169 } 170 } else { 171 static const u_int chanflags[] = { 172 0, /* IEEE80211_MODE_AUTO */ 173 IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */ 174 IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */ 175 IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */ 176 IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */ 177 IEEE80211_CHAN_108A, /* IEEE80211_MODE_TURBO_A */ 178 IEEE80211_CHAN_108G, /* IEEE80211_MODE_TURBO_G */ 179 IEEE80211_CHAN_ST, /* IEEE80211_MODE_TURBO_STATIC_A */ 180 }; 181 u_int modeflags; 182 183 modeflags = chanflags[vap->iv_des_mode]; 184 if (vap->iv_ath_cap & IEEE80211_ATHC_TURBOP && modeflags != IEEE80211_CHAN_ST) { 185 if (vap->iv_des_mode == IEEE80211_MODE_11G) 186 modeflags = IEEE80211_CHAN_108G; 187 else 188 modeflags = IEEE80211_CHAN_108A; 189 } 190 for (i = 0; i < ic->ic_nchans; i++) { 191 c = &ic->ic_channels[i]; 192 if ((c->ic_flags & modeflags) != modeflags) 193 continue; 194 /* XR is not supported on turbo channels */ 195 if (IEEE80211_IS_CHAN_TURBO(c) && vap->iv_ath_cap & IEEE80211_ATHC_XR) 196 continue; 197 if (ss->ss_last >= IEEE80211_SCAN_MAX) 198 break; 199 /* 200 * do not select static turbo channels if the mode is not 201 * static turbo . 202 */ 203 if (IEEE80211_IS_CHAN_STURBO(c) && vap->iv_des_mode != IEEE80211_MODE_MAX ) 204 continue; 205 /* No dfs interference detected channels */ 206 if (c->ic_flags & IEEE80211_CHAN_RADAR) 207 continue; 208 ss->ss_chans[ss->ss_last++] = c; 209 } 374 /* Use the table of ordered channels to construct the list 375 * of channels for scanning. Any channels in the ordered 376 * list not in the master list will be discarded. */ 377 for (sl = staScanTable; sl->list != NULL; sl++) { 378 mode = sl->mode; 379 /* The scan table marks 2.4Ghz channels as b 380 * so if the desired mode is 11g, then use 381 * the 11b channel list but upgrade the mode. */ 382 if (as->as_vap_desired_mode && 383 as->as_vap_desired_mode != mode && 384 as->as_vap_desired_mode == IEEE80211_MODE_11G && 385 mode == IEEE80211_MODE_11B) 386 mode = IEEE80211_MODE_11G; 387 /* If we are in "AUTO" mode, upgrade the mode to auto. 388 * This lets add_channels upgrade an 11b channel to 389 * 11g if available. */ 390 if(!as->as_vap_desired_mode && mode == IEEE80211_MODE_11B) 391 mode = IEEE80211_MODE_AUTO; 392 /* Add the list of the channels; any that are not 393 * in the master channel list will be discarded. */ 394 add_channels(ic, ss, mode, sl->list, sl->count); 395 } 396 397 /* 398 * Add the channels from the ic (from HAL) that are not present 399 * in the staScanTable, assuming they pass the sanity checks... 400 */ 401 for (i = 0; i < ic->ic_nchans; i++) { 402 c = &ic->ic_channels[i]; 403 /* XR is not supported on turbo channels */ 404 if (IEEE80211_IS_CHAN_TURBO(c) && vap->iv_flags & IEEE80211_F_XR) 405 continue; 406 407 /* Dynamic channels are scanned in base mode */ 408 if (!as->as_required_mode && !IEEE80211_IS_CHAN_ST(c)) 409 continue; 410 411 /* Use any 11g channel instead of 11b one. */ 412 if (vap->iv_des_mode == IEEE80211_MODE_AUTO && 413 IEEE80211_IS_CHAN_B(c) && 414 find11gchannel(ic, i, c->ic_freq)) 415 continue; 416 417 /* Do not add channels already put into the scan list by the 418 * scan table - these have already been filtered by mode 419 * and for whether they are in the active channel list. */ 420 if (checktable(staScanTable, c)) 421 continue; 422 423 /* Make sure the channel is active */ 424 if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee)) 425 continue; 426 427 /* Don't overrun */ 428 if (ss->ss_last >= IEEE80211_SCAN_MAX) 429 break; 430 431 ss->ss_chans[ss->ss_last++] = c; 210 432 } 211 433 ss->ss_next = 0; … … 223 445 #endif /* IEEE80211_DEBUG */ 224 446 447 as->as_newscan = 1; 448 SCAN_AP_UNLOCK_IRQ(as); 225 449 return 0; 226 450 } … … 232 456 ap_restart(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) 233 457 { 458 struct ap_state *as = ss->ss_priv; 459 as->as_newscan = 1; 234 460 return 0; 235 461 } … … 242 468 { 243 469 struct ap_state *as = ss->ss_priv; 244 245 470 IEEE80211_CANCEL_TQUEUE(&as->as_actiontq); 246 471 return 0; … … 254 479 const struct ieee80211_frame *wh, int subtype, int rssi, u_int64_t rtsf) 255 480 { 256 struct ap_state *as = ss->ss_priv; 257 struct ieee80211vap *vap = ss->ss_vap; 258 struct ieee80211com *ic = vap->iv_ic; 259 int chan; 260 261 chan = ieee80211_chan2ieee(ic, ic->ic_curchan); 262 /* XXX better quantification of channel use? */ 263 /* XXX: count BSSs? */ 481 struct ap_state *as = ss->ss_priv; 482 const u_int8_t *macaddr = wh->i_addr2; 483 struct ieee80211vap *vap = NULL; 484 struct ieee80211com *ic = NULL; 485 struct scan_entry *se = NULL; 486 struct ieee80211_scan_entry *ise = NULL; 487 int hash; 488 int chan = 0; 489 490 /* This section provides scan results to wireless extensions */ 491 SCAN_AP_LOCK_IRQ(as); 492 /* This is the only information used for channel selection by AP */ 264 493 if (rssi > as->as_maxrssi[chan]) 265 494 as->as_maxrssi[chan] = rssi; 266 /* XXX interference, turbo requirements */ 495 vap = ss->ss_vap; 496 ic = vap->iv_ic; 497 hash = AP_HASH(macaddr); 498 chan = ieee80211_chan2ieee(ic, ic->ic_curchan); 499 LIST_FOREACH(se, &as->as_hash[hash], se_hash) 500 if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr) && 501 sp->ssid[1] == se->base.se_ssid[1] && 502 !memcmp(se->base.se_ssid+2, sp->ssid+2, se->base.se_ssid[1])) 503 goto found; 504 505 MALLOC(se, struct scan_entry *, sizeof(struct scan_entry), 506 M_80211_SCAN, M_NOWAIT | M_ZERO); 507 if (se == NULL) { 508 SCAN_AP_UNLOCK_IRQ_EARLY(as); 509 return 0; 510 } 511 se->se_scangen = as->as_scangen-1; 512 IEEE80211_ADDR_COPY(se->base.se_macaddr, macaddr); 513 TAILQ_INSERT_TAIL(&as->as_entry, se, se_list); 514 LIST_INSERT_HEAD(&as->as_hash[hash], se, se_hash); 515 found: 516 ise = &se->base; 517 /* XXX ap beaconing multiple ssid w/ same bssid */ 518 if (sp->ssid[1] != 0 && 519 ((subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) || ise->se_ssid[1] == 0)) 520 { 521 memcpy(ise->se_ssid, sp->ssid, 2 + sp->ssid[1]); 522 } 523 KASSERT(sp->rates[1] <= IEEE80211_RATE_MAXSIZE, 524 ("rate set too large: %u", sp->rates[1])); 525 memcpy(ise->se_rates, sp->rates, 2 + sp->rates[1]); 526 if (sp->xrates != NULL) { 527 /* XXX validate xrates[1] */ 528 KASSERT(sp->xrates[1] <= IEEE80211_RATE_MAXSIZE, 529 ("xrate set too large: %u", sp->xrates[1])); 530 memcpy(ise->se_xrates, sp->xrates, 2 + sp->xrates[1]); 531 } else 532 ise->se_xrates[1] = 0; 533 IEEE80211_ADDR_COPY(ise->se_bssid, wh->i_addr3); 534 /* 535 * Record rssi data using extended precision LPF filter. 536 */ 537 if (se->se_lastupdate == 0) /* first sample */ 538 se->se_avgrssi = RSSI_IN(rssi); 539 else /* avg w/ previous samples */ 540 RSSI_LPF(se->se_avgrssi, rssi); 541 se->base.se_rssi = RSSI_GET(se->se_avgrssi); 542 ise->se_rtsf = rtsf; 543 memcpy(ise->se_tstamp.data, sp->tstamp, sizeof(ise->se_tstamp)); 544 ise->se_intval = sp->bintval; 545 ise->se_capinfo = sp->capinfo; 546 ise->se_chan = ic->ic_curchan; 547 ise->se_fhdwell = sp->fhdwell; 548 ise->se_fhindex = sp->fhindex; 549 ise->se_erp = sp->erp; 550 ise->se_timoff = sp->timoff; 551 if (sp->tim != NULL) { 552 const struct ieee80211_tim_ie *tim = 553 (const struct ieee80211_tim_ie *) sp->tim; 554 ise->se_dtimperiod = tim->tim_period; 555 } 556 saveie(&ise->se_wme_ie, sp->wme); 557 saveie(&ise->se_wpa_ie, sp->wpa); 558 saveie(&ise->se_rsn_ie, sp->rsn); 559 saveie(&ise->se_ath_ie, sp->ath); 560 561 se->se_lastupdate = jiffies; /* update time */ 562 se->se_seen = 1; 563 se->se_notseen = 0; 564 565 SCAN_AP_UNLOCK_IRQ(as); 566 267 567 return 1; 268 568 } 269 569 270 271 /* 272 * ap_end 273 * 274 * Choose the most optimal channel taking under consideration rssi of the 275 * received packets and the current Spectrum Management algorithm. 276 * 277 * This can be called a stub since it is of no important use unless there is a 278 * way to keep the scan results up-to-date without interrupting BSS operation. 279 * 280 */ 281 282 struct ap_pc_params { 570 struct pc_params { 283 571 struct ieee80211vap *vap; 284 572 struct ieee80211_scan_state *ss; … … 289 577 struct ieee80211_channel *chan; 290 578 int orig; 291 struct ap_pc_params *params;579 struct pc_params *params; 292 580 }; 293 581 294 static int 295 ap_pc_cmp_radar(struct ieee80211_channel *a, struct ieee80211_channel *b) 582 /* This function must be invoked with locks acquired */ 583 static int 584 pc_cmp_radar(struct ieee80211_channel *a, struct ieee80211_channel *b) 296 585 { 297 586 /* a is better than b (return < 0) when b is marked while a is not */ … … 299 588 } 300 589 301 static int 302 ap_pc_cmp_keepmode(struct ap_pc_params *params, struct ieee80211_channel *a, 590 /* This function must be invoked with locks acquired */ 591 static int 592 pc_cmp_keepmode(struct pc_params *params, struct ieee80211_channel *a, 303 593 struct ieee80211_channel *b) 304 594 { … … 315 605 } 316 606 317 static int 318 ap_pc_cmp_sc(struct ieee80211com *ic, struct ieee80211_channel *a, 607 /* This function must be invoked with locks acquired */ 608 static int 609 pc_cmp_sc(struct ieee80211com *ic, struct ieee80211_channel *a, 319 610 struct ieee80211_channel *b) 320 611 { … … 325 616 } 326 617 327 static int 328 ap_pc_cmp_rssi(struct ap_state *as, struct ieee80211_channel *a, 618 /* This function must be invoked with locks acquired */ 619 static int 620 pc_cmp_rssi(struct ap_state *as, struct ieee80211_channel *a, 329 621 struct ieee80211_channel *b) 330 622 { … … 335 627 } 336 628 337 static int 338 ap_pc_cmp_samechan(struct ieee80211com *ic, struct ieee80211_channel *a, 629 /* This function must be invoked with locks acquired */ 630 static int 631 pc_cmp_samechan(struct ieee80211com *ic, struct ieee80211_channel *a, 339 632 struct ieee80211_channel *b) 340 633 { … … 346 639 } 347 640 348 /* use original scan list order*/349 static int 350 ap_pc_cmp_orig(struct channel *a, struct channel *b)641 /* This function must be invoked with locks acquired */ 642 static int 643 pc_cmp_orig(struct channel *a, struct channel *b) 351 644 { 352 645 return a->orig - b->orig; 353 646 } 354 647 355 static int 356 ap_pc_cmp(const void *_a, const void *_b) 648 /* This function must be invoked with locks acquired */ 649 static int 650 pc_cmp(const void *_a, const void *_b) 357 651 { 358 652 struct ieee80211_channel *a = ((struct channel *)_a)->chan; 359 653 struct ieee80211_channel *b = ((struct channel *)_b)->chan; 360 struct ap_pc_params *params = ((struct channel *)_a)->params;654 struct pc_params *params = ((struct channel *)_a)->params; 361 655 struct ieee80211com *ic = params->vap->iv_ic; 362 656 int res; 363 657 364 658 #define EVALUATE_CRITERIUM(name, ...) do { \ 365 if ((res = ap_pc_cmp_##name(__VA_ARGS__)) != 0) \659 if ((res = pc_cmp_##name(__VA_ARGS__)) != 0) \ 366 660 return res; \ 367 661 } while (0) … … 370 664 EVALUATE_CRITERIUM(keepmode, params, a, b); 371 665 EVALUATE_CRITERIUM(sc, ic, a, b); 372 EVALUATE_CRITERIUM(rssi, params->ss->ss_priv, a, b); /* useless? ap_pick_channel evaluates it anyway */666 EVALUATE_CRITERIUM(rssi, params->ss->ss_priv, a, b); /* useless? pick_channel evaluates it anyway */ 373 667 EVALUATE_CRITERIUM(samechan, ic, a, b); 374 668 EVALUATE_CRITERIUM(orig, (struct channel *)_a, (struct channel *)_b); … … 378 672 } 379 673 674 /* This function must be invoked with locks acquired */ 380 675 static void 381 ap_pc_swap(void *a, void *b, int n)676 pc_swap(void *a, void *b, int n) 382 677 { 383 678 struct ieee80211_channel *t = ((struct channel *)a)->chan; … … 396 691 /* 397 692 * Pick a quiet channel to use for ap operation. 693 * Must be invoked while we hold the locks. 398 694 */ 399 695 static struct ieee80211_channel * 400 ap_pick_channel(struct ieee80211_scan_state *ss, struct ieee80211vap *vap, u_int32_t flags)696 pick_channel(struct ieee80211_scan_state *ss, struct ieee80211vap *vap, u_int32_t flags) 401 697 { 402 698 struct ieee80211com *ic = vap->iv_ic; 403 int i, be st_rssi;699 int i, beas_rssi; 404 700 int ss_last = ss->ss_last; 405 701 struct ieee80211_channel *best; 406 702 struct ap_state *as = ss->ss_priv; 407 703 struct channel chans[ss_last]; /* actually ss_last-1 is required */ 408 struct ap_pc_params params = { vap, ss, flags }; 704 struct channel *c = NULL; 705 struct pc_params params = { vap, ss, flags }; 706 int benefit = 0; 707 int sta_assoc = 0; 409 708 410 709 for (i = 0; i < ss_last; i++) { … … 414 713 } 415 714 416 sort(chans, ss_last, sizeof(*chans), ap_pc_cmp, ap_pc_swap);715 sort(chans, ss_last, sizeof(*chans), pc_cmp, pc_swap); 417 716 418 717 for (i = 0; i < ss_last; i++) { … … 426 725 } 427 726 428 best = chans[0].chan;429 be st_rssi = -1;727 best = NULL; 728 beas_rssi = -1; 430 729 431 730 for (i = 0; i < ss_last; i++) { 432 int benefit = best_rssi - as->as_maxrssi[chans[i].chan->ic_ieee]; 433 int sta_assoc = ic->ic_sta_assoc; 434 731 c = &chans[i]; 732 benefit = beas_rssi - as->as_maxrssi[c->chan->ic_ieee]; 733 sta_assoc = ic->ic_sta_assoc; 734 735 /* Don't switch... */ 435 736 if (benefit <= 0) 436 737 continue; 437 738 438 if ((flags & IEEE80211_SCAN_KEEPMODE) && !IEEE80211_ARE_CHANS_SAME_MODE(chans[i].chan, ic->ic_bsschan)) 439 /* break the loop as the subsequent chans won't be better */ 440 break; 441 442 if (!IEEE80211_ARE_CHANS_SAME_MODE(chans[i].chan, ic->ic_bsschan)) 739 /* Verify channel is not marked for non-occupancy */ 740 if (IEEE80211_IS_CHAN_RADAR(c->chan)) 741 continue; 742 743 /* Do not select 802.11a ST if mode is specified and is not 802.11a ST */ 744 if (as->as_required_mode && 745 IEEE80211_IS_CHAN_STURBO(c->chan) && 746 as->as_vap_desired_mode != IEEE80211_MODE_TURBO_STATIC_A) 747 continue; 748 749 /* Verify mode matches any fixed mode specified */ 750 if((c->chan->ic_flags & as->as_required_mode) != as->as_required_mode) 751 continue; 752 753 /* Make sure the channels are the same mode */ 754 if ((flags & IEEE80211_SCAN_KEEPMODE) && !IEEE80211_ARE_CHANS_SAME_MODE(c->chan, ic->ic_bsschan)) 443 755 /* break the loop as the subsequent chans won't be better */ 444 756 break; 445 757 758 if (!IEEE80211_ARE_CHANS_SAME_MODE(c->chan, ic->ic_bsschan)) 759 /* break the loop as the subsequent chans won't be better */ 760 break; 761 446 762 if (sta_assoc != 0) { 447 int sl = ic->ic_cn_total - ic->ic_chan_nodes[c hans[i].chan->ic_ieee]; /* count */763 int sl = ic->ic_cn_total - ic->ic_chan_nodes[c->chan->ic_ieee]; /* count */ 448 764 if (ic->ic_sc_algorithm == IEEE80211_SC_LOOSE) { 449 765 int sl_max = ic->ic_sc_sldg * benefit; … … 451 767 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 452 768 "%s: chan %d, dB gained: %d, STAs lost: %d permil (max %d)\n", __func__, 453 c hans[i].chan->ic_ieee, benefit, sl, sl_max);769 c->chan->ic_ieee, benefit, sl, sl_max); 454 770 if (sl > sl_max) 455 771 continue; … … 461 777 } 462 778 } 463 best = c hans[i].chan;464 be st_rssi = as->as_maxrssi[best->ic_ieee];779 best = c->chan; 780 beas_rssi = as->as_maxrssi[best->ic_ieee]; 465 781 } 466 782 … … 478 794 { 479 795 struct ap_state *as = ss->ss_priv; 480 struct ieee80211com *ic = vap->iv_ic; 481 struct ieee80211_channel *bestchan; 796 struct ieee80211_channel *bestchan = NULL; 797 struct ieee80211com *ic = NULL; 798 int res = 1; 799 800 SCAN_AP_LOCK_IRQ(as); 482 801 483 802 KASSERT(vap->iv_opmode == IEEE80211_M_HOSTAP, 484 803 ("wrong opmode %u", vap->iv_opmode)); 485 804 486 bestchan = ap_pick_channel(ss, vap, flags); 805 ic = vap->iv_ic; 806 bestchan = pick_channel(ss, vap, flags); 487 807 if (bestchan == NULL) { 488 808 if (ss->ss_last > 0) { … … 492 812 /* XXX print something? */ 493 813 } 494 re turn0; /* restart scan */814 res = 0; /* restart scan */ 495 815 } else { 496 816 struct ieee80211_scan_entry se; … … 517 837 */ 518 838 IEEE80211_SCHEDULE_TQUEUE(&as->as_actiontq); 519 return 1; 520 } 839 res = 1; 840 } 841 SCAN_AP_UNLOCK_IRQ(as); 842 return res; 521 843 } 522 844 … … 524 846 ap_age(struct ieee80211_scan_state *ss) 525 847 { 526 /* XXX is there anything meaningful to do? */ 848 struct ap_state *as = ss->ss_priv; 849 struct scan_entry *se, *next; 850 851 SCAN_AP_LOCK_IRQ(as); 852 TAILQ_FOREACH_SAFE(se, &as->as_entry, se_list, next) { 853 if (se->se_notseen > AP_PURGE_SCANS) { 854 TAILQ_REMOVE(&as->as_entry, se, se_list); 855 LIST_REMOVE(se, se_hash); 856 FREE(se, M_80211_SCAN); 857 } 858 } 859 SCAN_AP_UNLOCK_IRQ(as); 527 860 } 528 861 … … 531 864 ieee80211_scan_iter_func *f, void *arg) 532 865 { 533 /* NB: nothing meaningful we can do */ 534 return 0; 866 struct ap_state *as = ss->ss_priv; 867 struct scan_entry *se; 868 u_int gen; 869 int res = 0; 870 871 SCAN_AP_GEN_LOCK(as); 872 gen = as->as_scangen++; 873 restart: 874 SCAN_AP_LOCK_IRQ(as); 875 TAILQ_FOREACH(se, &as->as_entry, se_list) { 876 if (se->se_scangen != gen) { 877 se->se_scangen = gen; 878 /* update public state */ 879 se->base.se_age = jiffies - se->se_lastupdate; 880 SCAN_AP_UNLOCK_IRQ_EARLY(as); 881 882 res = (*f)(arg, &se->base); 883 884 /* We probably ran out of buffer space. */ 885 if (res != 0) 886 goto done; 887 888 goto restart; 889 } 890 } 891 892 SCAN_AP_UNLOCK_IRQ(as); 893 894 done:
