Changeset 2724

Show
Ignore:
Timestamp:
10/05/07 07:52:42 (1 year ago)
Author:
mtaylor
Message:

Added support for AP mode scan results to be updated and returned to
wireless tools and other clients. This fixes:

bgscan
iwlist <iface> scan
wlanconfig <iface> list scan
wlanconfig <iface> list peers

etc...

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • madwifi/trunk/net80211/ieee80211_scan_ap.c

    r2513 r2724  
    5252#include <net80211/ieee80211_var.h> 
    5353 
     54#define AP_PURGE_SCANS  2               /* age for purging entries (scans) */ 
     55#define RSSI_LPF_LEN    10 
     56#define RSSI_EP_MULTIPLIER      (1<<7)  /* pow2 to optimize out * and / */ 
     57#define RSSI_IN(x)              ((x) * RSSI_EP_MULTIPLIER) 
     58#define LPF_RSSI(x, y, len)     (((x) * ((len) - 1) + (y)) / (len)) 
     59#define RSSI_LPF(x, y) do {                                             \ 
     60        if ((y) >= -20)                                                 \ 
     61                x = LPF_RSSI((x), RSSI_IN((y)), RSSI_LPF_LEN);                  \ 
     62} while (0) 
     63#define EP_RND(x, mul) \ 
     64        ((((x)%(mul)) >= ((mul)/2)) ? howmany(x, mul) : (x)/(mul)) 
     65#define RSSI_GET(x)     EP_RND(x, RSSI_EP_MULTIPLIER) 
     66#define AP_HASHSIZE     32 
     67/* simple hash is enough for variation of macaddr */ 
     68#define AP_HASH(addr)   \ 
     69        (((const u_int8_t *)(addr))[IEEE80211_ADDR_LEN - 1] % AP_HASHSIZE) 
     70#define SCAN_AP_LOCK_INIT(_st, _name)                                   \ 
     71        spin_lock_init(&(_st)->as_lock) 
     72#define SCAN_AP_LOCK_DESTROY(_st) 
     73#define SCAN_AP_LOCK_IRQ(_st) do {                                      \ 
     74        unsigned long __stlockflags;                                    \ 
     75        spin_lock_irqsave(&(_st)->as_lock, __stlockflags); 
     76#define SCAN_AP_UNLOCK_IRQ(_st)                                         \ 
     77        spin_unlock_irqrestore(&(_st)->as_lock, __stlockflags);         \ 
     78} while (0) 
     79#define SCAN_AP_UNLOCK_IRQ_EARLY(_st)                                   \ 
     80        spin_unlock_irqrestore(&(_st)->as_lock, __stlockflags); 
     81 
     82#define SCAN_AP_GEN_LOCK_INIT(_st, _name)                               \ 
     83        spin_lock_init(&(_st)->as_scanlock) 
     84#define SCAN_AP_GEN_LOCK_DESTROY(_st) 
     85#define SCAN_AP_GEN_LOCK(_st)           spin_lock(&(_st)->as_scanlock); 
     86#define SCAN_AP_GEN_UNLOCK(_st) spin_unlock(&(_st)->as_scanlock); 
     87 
     88struct scan_entry { 
     89        struct ieee80211_scan_entry base; 
     90        TAILQ_ENTRY(scan_entry) se_list; 
     91        LIST_ENTRY(scan_entry) se_hash; 
     92        u_int8_t        se_seen;                /* seen during current scan */ 
     93        u_int8_t        se_notseen;             /* not seen in previous scans */ 
     94        u_int32_t se_avgrssi;           /* LPF rssi state */ 
     95        unsigned long se_lastupdate;    /* time of last update */ 
     96        unsigned long se_lastfail;      /* time of last failure */ 
     97        unsigned long se_lastassoc;     /* time of last association */ 
     98        u_int se_scangen;               /* iterator scan gen# */ 
     99}; 
     100 
    54101struct ap_state { 
    55         int as_maxrssi[IEEE80211_CHAN_MAX]; 
     102        unsigned int as_vap_desired_mode;       /* Used for channel selection, vap->iv_des_mode */ 
     103        unsigned int as_required_mode;          /* Used for channel selection, filtered version of as_vap_desired_mode */ 
     104        int as_maxrssi[IEEE80211_CHAN_MAX];     /* Used for channel selection */ 
     105 
     106        /* These fields are just for scan caching for returning responses to 
     107         * wireless extensions.  i.e. show peers, APs, etc. */ 
     108        spinlock_t as_lock;                     /* on scan table */ 
     109        int as_newscan;                         /* trigger for updating seen/not-seen for aging */ 
     110        TAILQ_HEAD(, scan_entry) as_entry;      /* all entries */ 
     111        ATH_LIST_HEAD(, scan_entry) as_hash[AP_HASHSIZE]; 
     112        spinlock_t as_scanlock;                 /* on as_scangen */ 
     113        u_int as_scangen;                       /* gen# for iterator */ 
     114 
    56115        struct IEEE80211_TQ_STRUCT as_actiontq; /* tasklet for "action" */ 
    57116        struct ieee80211_scan_entry as_selbss;  /* selected bss for action tasklet */ 
     
    61120static int ap_flush(struct ieee80211_scan_state *); 
    62121static void action_tasklet(IEEE80211_TQUEUE_ARG); 
     122static struct ieee80211_channel *find11gchannel(struct ieee80211com *ic, int i, int freq); 
     123 
     124static const u_int chanflags[] = { 
     125        IEEE80211_CHAN_B,       /* IEEE80211_MODE_AUTO */ 
     126        IEEE80211_CHAN_A,       /* IEEE80211_MODE_11A */ 
     127        IEEE80211_CHAN_B,       /* IEEE80211_MODE_11B */ 
     128        IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_11G */ 
     129        IEEE80211_CHAN_FHSS,    /* IEEE80211_MODE_FH */ 
     130        IEEE80211_CHAN_A,       /* IEEE80211_MODE_TURBO_A */ /* for turbo mode look for AP in normal channel */ 
     131        IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_TURBO_G */ 
     132        IEEE80211_CHAN_ST,      /* IEEE80211_MODE_TURBO_STATIC_A */ 
     133}; 
     134 
     135static const u_int16_t rcl1[] =         /* 8 FCC channel: 52, 56, 60, 64, 36, 40, 44, 48 */ 
     136{ 5260, 5280, 5300, 5320, 5180, 5200, 5220, 5240 }; 
     137static const u_int16_t rcl2[] =         /* 4 MKK channels: 34, 38, 42, 46 */ 
     138{ 5170, 5190, 5210, 5230 }; 
     139static const u_int16_t rcl3[] =         /* 2.4Ghz ch: 1,6,11,7,13 */ 
     140{ 2412, 2437, 2462, 2442, 2472 }; 
     141static const u_int16_t rcl4[] =         /* 5 FCC channel: 149, 153, 161, 165 */ 
     142{ 5745, 5765, 5785, 5805, 5825 }; 
     143static const u_int16_t rcl7[] =         /* 11 ETSI channel: 100,104,108,112,116,120,124,128,132,136,140 */ 
     144{ 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700 }; 
     145static const u_int16_t rcl8[] =         /* 2.4Ghz ch: 2,3,4,5,8,9,10,12 */ 
     146{ 2417, 2422, 2427, 2432, 2447, 2452, 2457, 2467 }; 
     147static const u_int16_t rcl9[] =         /* 2.4Ghz ch: 14 */ 
     148{ 2484 }; 
     149static const u_int16_t rcl10[] =        /* Added Korean channels 2312-2372 */ 
     150{ 2312, 2317, 2322, 2327, 2332, 2337, 2342, 2347, 2352, 2357, 2362, 2367, 2372 }; 
     151static const u_int16_t rcl11[] =        /* Added Japan channels in 4.9/5.0 spectrum */ 
     152{ 5040, 5060, 5080, 4920, 4940, 4960, 4980 }; 
     153#ifdef ATH_TURBO_SCAN 
     154static const u_int16_t rcl5[] =         /* 3 static turbo channels */ 
     155{ 5210, 5250, 5290 }; 
     156static const u_int16_t rcl6[] =         /* 2 static turbo channels */ 
     157{ 5760, 5800 }; 
     158static const u_int16_t rcl6x[] =                /* 4 FCC3 turbo channels */ 
     159{ 5540, 5580, 5620, 5660 }; 
     160static const u_int16_t rcl12[] =                /* 2.4Ghz Turbo channel 6 */ 
     161{ 2437 }; 
     162static const u_int16_t rcl13[] =                /* dynamic Turbo channels */ 
     163{ 5200, 5240, 5280, 5765, 5805 }; 
     164#endif /* ATH_TURBO_SCAN */ 
     165 
     166struct scanlist { 
     167        u_int16_t       mode; 
     168        u_int16_t       count; 
     169        const u_int16_t *list; 
     170}; 
     171 
     172#define IEEE80211_MODE_TURBO_STATIC_A   IEEE80211_MODE_MAX 
     173#define X(a)    .count = sizeof(a)/sizeof(a[0]), .list = a 
     174 
     175static const struct scanlist staScanTable[] = { 
     176        { IEEE80211_MODE_11B,                   X(rcl3) }, 
     177        { IEEE80211_MODE_11A,                   X(rcl1) }, 
     178        { IEEE80211_MODE_11A,                   X(rcl2) }, 
     179        { IEEE80211_MODE_11B,                   X(rcl8) }, 
     180        { IEEE80211_MODE_11B,                   X(rcl9) }, 
     181        { IEEE80211_MODE_11A,                   X(rcl4) }, 
     182#ifdef ATH_TURBO_SCAN 
     183        { IEEE80211_MODE_TURBO_STATIC_A,        X(rcl5) }, 
     184        { IEEE80211_MODE_TURBO_STATIC_A,        X(rcl6) }, 
     185        { IEEE80211_MODE_TURBO_A,               X(rcl6x) }, 
     186        { IEEE80211_MODE_TURBO_A,               X(rcl13) }, 
     187#endif /* ATH_TURBO_SCAN */ 
     188        { IEEE80211_MODE_11A,                   X(rcl7) }, 
     189        { IEEE80211_MODE_11B,                   X(rcl10) }, 
     190        { IEEE80211_MODE_11A,                   X(rcl11) }, 
     191#ifdef ATH_TURBO_SCAN 
     192        { IEEE80211_MODE_TURBO_G,               X(rcl12) }, 
     193#endif /* ATH_TURBO_SCAN */ 
     194        { .list = NULL } 
     195}; 
     196 
     197#undef X 
     198/* This function must be invoked with locks acquired */ 
     199static void 
     200add_channels(struct ieee80211com *ic, 
     201        struct ieee80211_scan_state *ss, 
     202        enum ieee80211_phymode mode, const u_int16_t freq[], int nfreq) 
     203{ 
     204#define N(a)    (sizeof(a) / sizeof(a[0])) 
     205        struct ieee80211_channel *c, *cg; 
     206        u_int modeflags; 
     207        int i; 
     208 
     209        KASSERT(mode < N(chanflags), ("Unexpected mode %u", mode)); 
     210        modeflags = chanflags[mode]; 
     211        for (i = 0; i < nfreq; i++) { 
     212                c = ieee80211_find_channel(ic, freq[i], modeflags); 
     213                if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee)) 
     214                        continue; 
     215                if (mode == IEEE80211_MODE_AUTO) { 
     216                        /* 
     217                         * XXX special-case 11b/g channels so we select 
     218                         *     the g channel if both are present. 
     219                         */ 
     220                        if (IEEE80211_IS_CHAN_B(c) && 
     221                            (cg = find11gchannel(ic, i, c->ic_freq)) != NULL) 
     222                                c = cg; 
     223                } 
     224                if (ss->ss_last >= IEEE80211_SCAN_MAX) 
     225                        break; 
     226                ss->ss_chans[ss->ss_last++] = c; 
     227        } 
     228#undef N 
     229} 
     230 
     231/* This function must be invoked with locks acquired */ 
     232static int 
     233checktable(const struct scanlist *scan, const struct ieee80211_channel *c) 
     234{ 
     235        int i; 
     236 
     237        for (; scan->list != NULL; scan++) { 
     238                for (i = 0; i < scan->count; i++) 
     239                        if (scan->list[i] == c->ic_freq) 
     240                                return 1; 
     241        } 
     242        return 0; 
     243} 
    63244 
    64245/* 
     
    73254 
    74255        MALLOC(as, struct ap_state *, sizeof(struct ap_state), 
    75                 M_SCANCACHE, M_NOWAIT); 
     256                M_80211_SCAN, M_NOWAIT | M_ZERO); 
     257        if (as == NULL) 
     258                return 0; 
     259        SCAN_AP_LOCK_INIT(as, "scan_ap"); 
     260        SCAN_AP_GEN_LOCK_INIT(as, "scan_ap_gen"); 
     261        TAILQ_INIT(&as->as_entry); 
     262        IEEE80211_INIT_TQUEUE(&as->as_actiontq, action_tasklet, ss); 
    76263        ss->ss_priv = as; 
    77         IEEE80211_INIT_TQUEUE(&as->as_actiontq, action_tasklet, ss); 
    78264        ap_flush(ss); 
    79265        return 1; 
     
    88274        struct ap_state *as = ss->ss_priv; 
    89275 
    90         if (as != NULL) 
    91                 FREE(as, M_SCANCACHE); 
     276        if (as != NULL) { 
     277                ap_flush(ss); 
     278                IEEE80211_CANCEL_TQUEUE(&as->as_actiontq); 
     279                FREE(as, M_80211_SCAN); 
     280        } 
    92281 
    93282        _MOD_DEC_USE(THIS_MODULE); 
     
    102291{ 
    103292        struct ap_state *as = ss->ss_priv; 
    104  
     293        struct scan_entry *se, *next; 
     294 
     295        SCAN_AP_LOCK_IRQ(as); 
    105296        memset(as->as_maxrssi, 0, sizeof(as->as_maxrssi)); 
     297        TAILQ_FOREACH_SAFE(se, &as->as_entry, se_list, next) { 
     298                TAILQ_REMOVE(&as->as_entry, se, se_list); 
     299                LIST_REMOVE(se, se_hash); 
     300                FREE(se, M_80211_SCAN); 
     301        } 
    106302        ss->ss_last = 0;                /* ensure no channel will be picked */ 
     303        SCAN_AP_UNLOCK_IRQ(as); 
    107304        return 0; 
    108305} 
    109306 
    110 static int 
     307/* This function must be invoked with locks acquired */ 
     308static void 
     309saveie(u_int8_t **iep, const u_int8_t *ie) 
     310
     311        if (ie == NULL) 
     312                *iep = NULL; 
     313        else 
     314                ieee80211_saveie(iep, ie); 
     315
     316 
     317/* This function must be invoked with locks acquired */ 
     318static struct ieee80211_channel * 
    111319find11gchannel(struct ieee80211com *ic, int i, int freq) 
    112320{ 
    113         const struct ieee80211_channel *c; 
     321        struct ieee80211_channel *c; 
    114322        int j; 
    115323 
     
    122330                c = &ic->ic_channels[j]; 
    123331                if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) 
    124                         return 1
     332                        return c
    125333        } 
    126334        for (j = 0; j < i; j++) { 
    127335                c = &ic->ic_channels[j]; 
    128336                if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) 
    129                         return 1
    130         } 
    131         return 0
     337                        return c
     338        } 
     339        return NULL
    132340} 
    133341 
     
    138346ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) 
    139347{ 
    140         struct ieee80211com *ic = vap->iv_ic; 
    141         struct ieee80211_channel *c; 
     348        struct ap_state *as         = ss->ss_priv; 
     349        struct ieee80211com *ic     = NULL; 
     350        const struct scanlist *sl   = NULL; 
     351        struct ieee80211_channel *c = NULL; 
    142352        int i; 
     353        unsigned int mode = 0; 
     354 
     355        SCAN_AP_LOCK_IRQ(as); 
     356        ic = vap->iv_ic; 
     357        /* Determine mode flags to match, or leave zero for auto mode */ 
     358        as->as_vap_desired_mode = vap->iv_des_mode; 
     359        as->as_required_mode    = 0; 
     360        if (as->as_vap_desired_mode != IEEE80211_MODE_AUTO) { 
     361                as->as_required_mode = chanflags[as->as_vap_desired_mode]; 
     362                if (vap->iv_ath_cap & IEEE80211_ATHC_TURBOP &&  
     363                    as->as_required_mode != IEEE80211_CHAN_ST) { 
     364                        /* Fixup for dynamic turbo flags */ 
     365                        if (as->as_vap_desired_mode == IEEE80211_MODE_11G) 
     366                                as->as_required_mode = IEEE80211_CHAN_108G; 
     367                        else 
     368                                as->as_required_mode = IEEE80211_CHAN_108A; 
     369                } 
     370        } 
    143371 
    144372        ss->ss_last = 0; 
    145         if (vap->iv_des_mode == IEEE80211_MODE_AUTO) { 
    146                 for (i = 0; i < ic->ic_nchans; i++) { 
    147                         c = &ic->ic_channels[i]; 
    148                         if (IEEE80211_IS_CHAN_TURBO(c)) { 
    149                                 /* XR is not supported on turbo channels */ 
    150                                 if (vap->iv_ath_cap & IEEE80211_ATHC_XR) 
    151                                         continue; 
    152                                 /* dynamic channels are scanned in base mode */ 
    153                                 if (!IEEE80211_IS_CHAN_ST(c)) 
    154                                         continue; 
    155                         } else { 
    156                                 /* 
    157                                  * Use any 11g channel instead of 11b one. 
    158                                  */ 
    159                                 if (IEEE80211_IS_CHAN_B(c) && 
    160                                     find11gchannel(ic, i, c->ic_freq)) 
    161                                         continue; 
    162                         } 
    163                         if (c->ic_flags & IEEE80211_CHAN_RADAR) 
    164                                 continue; 
    165                         if (ss->ss_last >= IEEE80211_SCAN_MAX) 
    166                                 break; 
    167                         ss->ss_chans[ss->ss_last++] = c; 
    168                 } 
    169         } else { 
    170                 static const u_int chanflags[] = { 
    171                         0,                      /* IEEE80211_MODE_AUTO */ 
    172                         IEEE80211_CHAN_A,       /* IEEE80211_MODE_11A */ 
    173                         IEEE80211_CHAN_B,       /* IEEE80211_MODE_11B */ 
    174                         IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_11G */ 
    175                         IEEE80211_CHAN_FHSS,    /* IEEE80211_MODE_FH */ 
    176                         IEEE80211_CHAN_108A,    /* IEEE80211_MODE_TURBO_A */ 
    177                         IEEE80211_CHAN_108G,    /* IEEE80211_MODE_TURBO_G */ 
    178                         IEEE80211_CHAN_ST,      /* IEEE80211_MODE_TURBO_STATIC_A */ 
    179                 }; 
    180                 u_int modeflags; 
    181  
    182                 modeflags = chanflags[vap->iv_des_mode]; 
    183                 if (vap->iv_ath_cap & IEEE80211_ATHC_TURBOP && modeflags != IEEE80211_CHAN_ST) { 
    184                         if (vap->iv_des_mode == IEEE80211_MODE_11G) 
    185                                 modeflags = IEEE80211_CHAN_108G; 
    186                         else 
    187                                 modeflags = IEEE80211_CHAN_108A; 
    188                 } 
    189                 for (i = 0; i < ic->ic_nchans; i++) { 
    190                         c = &ic->ic_channels[i]; 
    191                         if ((c->ic_flags & modeflags) != modeflags) 
    192                                 continue; 
    193                         /* XR is not supported on turbo channels */ 
    194                         if (IEEE80211_IS_CHAN_TURBO(c) && vap->iv_ath_cap & IEEE80211_ATHC_XR) 
    195                                 continue; 
    196                         if (ss->ss_last >= IEEE80211_SCAN_MAX) 
    197                                 break; 
    198                         /*  
    199                          * do not select static turbo channels if the mode is not 
    200                          * static turbo . 
    201                          */ 
    202                         if (IEEE80211_IS_CHAN_STURBO(c) && vap->iv_des_mode != IEEE80211_MODE_MAX ) 
    203                                 continue; 
    204                         /* No dfs interference detected channels */ 
    205                         if (c->ic_flags & IEEE80211_CHAN_RADAR) 
    206                                 continue; 
    207                         ss->ss_chans[ss->ss_last++] = c; 
    208                 } 
     373        /* Use the table of ordered channels to construct the list 
     374         * of channels for scanning.  Any channels in the ordered 
     375         * list not in the master list will be discarded. */ 
     376        for (sl = staScanTable; sl->list != NULL; sl++) { 
     377                mode = sl->mode; 
     378                /* The scan table marks 2.4Ghz channels as b 
     379                 * so if the desired mode is 11g, then use 
     380                 * the 11b channel list but upgrade the mode. */ 
     381                if (as->as_vap_desired_mode && 
     382                    as->as_vap_desired_mode != mode &&  
     383                    as->as_vap_desired_mode == IEEE80211_MODE_11G &&  
     384                    mode == IEEE80211_MODE_11B) 
     385                        mode = IEEE80211_MODE_11G; 
     386                /* If we are in "AUTO" mode, upgrade the mode to auto.  
     387                 * This lets add_channels upgrade an 11b channel to  
     388                 * 11g if available. */ 
     389                if(!as->as_vap_desired_mode && mode == IEEE80211_MODE_11B) 
     390                        mode = IEEE80211_MODE_AUTO; 
     391                /* Add the list of the channels; any that are not 
     392                 * in the master channel list will be discarded. */ 
     393                add_channels(ic, ss, mode, sl->list, sl->count); 
     394        } 
     395 
     396        /* 
     397         * Add the channels from the ic (from HAL) that are not present 
     398         * in the staScanTable, assuming they pass the sanity checks... 
     399         */ 
     400        for (i = 0; i < ic->ic_nchans; i++) { 
     401                c = &ic->ic_channels[i]; 
     402                /* XR is not supported on turbo channels */ 
     403                if (IEEE80211_IS_CHAN_TURBO(c) && vap->iv_flags & IEEE80211_F_XR) 
     404                        continue; 
     405 
     406                /* Dynamic channels are scanned in base mode */ 
     407                if (!as->as_required_mode && !IEEE80211_IS_CHAN_ST(c)) 
     408                        continue; 
     409 
     410                /* Use any 11g channel instead of 11b one. */ 
     411                if (vap->iv_des_mode == IEEE80211_MODE_AUTO &&  
     412                    IEEE80211_IS_CHAN_B(c) && 
     413                    find11gchannel(ic, i, c->ic_freq)) 
     414                        continue; 
     415 
     416                /* Do not add channels already put into the scan list by the 
     417                 * scan table - these have already been filtered by mode 
     418                 * and for whether they are in the active channel list. */ 
     419                if (checktable(staScanTable, c)) 
     420                        continue; 
     421 
     422                /* Make sure the channel is active */ 
     423                if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee)) 
     424                        continue; 
     425 
     426                /* Don't overrun */ 
     427                if (ss->ss_last >= IEEE80211_SCAN_MAX) 
     428                        break; 
     429 
     430                ss->ss_chans[ss->ss_last++] = c; 
    209431        } 
    210432        ss->ss_next = 0; 
     
    222444#endif /* IEEE80211_DEBUG */ 
    223445 
     446        as->as_newscan = 1; 
     447        SCAN_AP_UNLOCK_IRQ(as); 
    224448        return 0; 
    225449} 
     
    231455ap_restart(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) 
    232456{ 
     457        struct ap_state *as = ss->ss_priv; 
     458        as->as_newscan = 1; 
    233459        return 0; 
    234460} 
     
    241467{ 
    242468        struct ap_state *as = ss->ss_priv; 
    243  
    244469        IEEE80211_CANCEL_TQUEUE(&as->as_actiontq); 
    245470        return 0; 
     
    253478        const struct ieee80211_frame *wh, int subtype, int rssi, u_int64_t rtsf) 
    254479{ 
    255         struct ap_state *as = ss->ss_priv; 
    256         struct ieee80211vap *vap = ss->ss_vap; 
    257         struct ieee80211com *ic = vap->iv_ic; 
    258         int chan; 
    259  
    260         chan = ieee80211_chan2ieee(ic, ic->ic_curchan); 
    261         /* XXX better quantification of channel use? */ 
    262         /* XXX: count BSSs? */ 
     480        struct ap_state *as              = ss->ss_priv; 
     481        const u_int8_t *macaddr          = wh->i_addr2; 
     482        struct ieee80211vap *vap         = NULL; 
     483        struct ieee80211com *ic          = NULL; 
     484        struct scan_entry *se            = NULL; 
     485        struct ieee80211_scan_entry *ise = NULL; 
     486        int hash; 
     487        int chan = 0; 
     488 
     489        /* This section provides scan results to wireless extensions */ 
     490        SCAN_AP_LOCK_IRQ(as); 
     491        /* This is the only information used for channel selection by AP */ 
    263492        if (rssi > as->as_maxrssi[chan]) 
    264493                as->as_maxrssi[chan] = rssi; 
    265         /* XXX interference, turbo requirements */ 
     494        vap = ss->ss_vap; 
     495        ic = vap->iv_ic; 
     496        hash = AP_HASH(macaddr); 
     497        chan = ieee80211_chan2ieee(ic, ic->ic_curchan); 
     498        LIST_FOREACH(se, &as->as_hash[hash], se_hash) 
     499                if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr) && 
     500                    sp->ssid[1] == se->base.se_ssid[1] && 
     501                    !memcmp(se->base.se_ssid+2, sp->ssid+2, se->base.se_ssid[1])) 
     502                        goto found; 
     503 
     504        MALLOC(se, struct scan_entry *, sizeof(struct scan_entry), 
     505                M_80211_SCAN, M_NOWAIT | M_ZERO); 
     506        if (se == NULL) { 
     507                SCAN_AP_UNLOCK_IRQ_EARLY(as); 
     508                return 0; 
     509        } 
     510        se->se_scangen = as->as_scangen-1; 
     511        IEEE80211_ADDR_COPY(se->base.se_macaddr, macaddr); 
     512        TAILQ_INSERT_TAIL(&as->as_entry, se, se_list); 
     513        LIST_INSERT_HEAD(&as->as_hash[hash], se, se_hash); 
     514found: 
     515        ise = &se->base; 
     516        /* XXX ap beaconing multiple ssid w/ same bssid */ 
     517        if (sp->ssid[1] != 0 && 
     518            ((subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) || ise->se_ssid[1] == 0)) 
     519        { 
     520                memcpy(ise->se_ssid, sp->ssid, 2 + sp->ssid[1]); 
     521        } 
     522        KASSERT(sp->rates[1] <= IEEE80211_RATE_MAXSIZE, 
     523                ("rate set too large: %u", sp->rates[1])); 
     524        memcpy(ise->se_rates, sp->rates, 2 + sp->rates[1]); 
     525        if (sp->xrates != NULL) { 
     526                /* XXX validate xrates[1] */ 
     527                KASSERT(sp->xrates[1] <= IEEE80211_RATE_MAXSIZE, 
     528                        ("xrate set too large: %u", sp->xrates[1])); 
     529                memcpy(ise->se_xrates, sp->xrates, 2 + sp->xrates[1]); 
     530        } else 
     531                ise->se_xrates[1] = 0; 
     532        IEEE80211_ADDR_COPY(ise->se_bssid, wh->i_addr3); 
     533        /* 
     534         * Record rssi data using extended precision LPF filter. 
     535         */ 
     536        if (se->se_lastupdate == 0)             /* first sample */ 
     537                se->se_avgrssi = RSSI_IN(rssi); 
     538        else                                    /* avg w/ previous samples */ 
     539                RSSI_LPF(se->se_avgrssi, rssi); 
     540        se->base.se_rssi = RSSI_GET(se->se_avgrssi); 
     541        ise->se_rtsf = rtsf; 
     542        memcpy(ise->se_tstamp.data, sp->tstamp, sizeof(ise->se_tstamp)); 
     543        ise->se_intval = sp->bintval; 
     544        ise->se_capinfo = sp->capinfo; 
     545        ise->se_chan = ic->ic_curchan; 
     546        ise->se_fhdwell = sp->fhdwell; 
     547        ise->se_fhindex = sp->fhindex; 
     548        ise->se_erp = sp->erp; 
     549        ise->se_timoff = sp->timoff; 
     550        if (sp->tim != NULL) { 
     551                const struct ieee80211_tim_ie *tim = 
     552                    (const struct ieee80211_tim_ie *) sp->tim; 
     553                ise->se_dtimperiod = tim->tim_period; 
     554        } 
     555        saveie(&ise->se_wme_ie, sp->wme); 
     556        saveie(&ise->se_wpa_ie, sp->wpa); 
     557        saveie(&ise->se_rsn_ie, sp->rsn); 
     558        saveie(&ise->se_ath_ie, sp->ath); 
     559 
     560        se->se_lastupdate = jiffies;            /* update time */ 
     561        se->se_seen = 1; 
     562        se->se_notseen = 0; 
     563 
     564        SCAN_AP_UNLOCK_IRQ(as); 
     565 
    266566        return 1; 
    267567} 
     
    272572static int 
    273573ap_end(struct ieee80211_scan_state *ss, struct ieee80211vap *vap, 
    274           int (*action)(struct ieee80211vap *, const struct ieee80211_scan_entry *), 
    275           u_int32_t flags) 
     574   int (*action)(struct ieee80211vap *, const struct ieee80211_scan_entry *), 
     575   u_int32_t flags) 
    276576{ 
    277577        struct ap_state *as = ss->ss_priv; 
    278         struct ieee80211com *ic = vap->iv_ic; 
     578        struct ieee80211com *ic = NULL; 
     579        int res = 1; 
    279580        int i, chan, bestchan, bestchanix; 
     581 
     582        SCAN_AP_LOCK_IRQ(as); 
    280583 
    281584        KASSERT(vap->iv_opmode == IEEE80211_M_HOSTAP, 
    282585                ("wrong opmode %u", vap->iv_opmode)); 
     586 
     587        ic = vap->iv_ic; 
    283588        /* XXX select channel more intelligently, e.g. channel spread, power */ 
    284589        bestchan = -1; 
     
    334639                        /* XXX print something? */ 
    335640                } 
    336                 return 0; /* restart scan */ 
     641                res = 0; /* restart scan */ 
    337642        } else { 
    338643                struct ieee80211_channel *c; 
     
    362667                 */ 
    363668                IEEE80211_SCHEDULE_TQUEUE(&as->as_actiontq); 
    364                 return 1; 
    365         } 
     669                res = 1; 
     670        } 
     671        SCAN_AP_UNLOCK_IRQ(as); 
     672        return res; 
    366673} 
    367674 
     
    369676ap_age(struct ieee80211_scan_state *ss) 
    370677{ 
    371         /* XXX is there anything meaningful to do? */ 
     678        struct ap_state *as = ss->ss_priv; 
     679        struct scan_entry *se, *next; 
     680 
     681        SCAN_AP_LOCK_IRQ(as); 
     682        TAILQ_FOREACH_SAFE(se, &as->as_entry, se_list, next) { 
     683                if (se->se_notseen > AP_PURGE_SCANS) { 
     684                        TAILQ_REMOVE(&as->as_entry, se, se_list); 
     685                        LIST_REMOVE(se, se_hash); 
     686                        FREE(se, M_80211_SCAN); 
     687                } 
     688        } 
     689        SCAN_AP_UNLOCK_IRQ(as); 
    372690} 
    373691 
     
    376694        ieee80211_scan_iter_func *f, void *arg) 
    377695{ 
    378         /* NB: nothing meaningful we can do */ 
    379   return 0; 
     696        struct ap_state *as = ss->ss_priv; 
     697        struct scan_entry *se; 
     698        u_int gen; 
     699        int res = 0; 
     700 
     701        SCAN_AP_GEN_LOCK(as); 
     702        gen = as->as_scangen++; 
     703restart: 
     704        SCAN_AP_LOCK_IRQ(as); 
     705        TAILQ_FOREACH(se, &as->as_entry, se_list) { 
     706                if (se->se_scangen != gen) { 
     707                        se->se_scangen = gen; 
     708                        /* update public state */ 
     709                        se->base.se_age = jiffies - se->se_lastupdate; 
     710                        SCAN_AP_UNLOCK_IRQ_EARLY(as); 
     711 
     712                        res = (*f)(arg, &se->base); 
     713 
     714                        /* We probably ran out of buffer space. */ 
     715                        if (res != 0) 
     716                                goto done; 
     717 
     718                        goto restart; 
     719                } 
     720        } 
     721 
     722        SCAN_AP_UNLOCK_IRQ(as); 
     723 
     724done: 
     725        SCAN_AP_GEN_UNLOCK(as); 
     726 
     727        return res; 
    380728} 
    381729 
     
    403751{ 
    404752        ieee80211_create_ibss(vap, se->se_chan); 
     753 
    405754        return 1; 
    406755} 
     
    412761        struct ap_state *as = (struct ap_state *)ss->ss_priv; 
    413762        struct ieee80211vap *vap = ss->ss_vap; 
     763        SCAN_AP_LOCK_IRQ(as); 
     764        if (as->as_newscan) { 
     765                struct scan_entry *se; 
     766                TAILQ_FOREACH(se, &as->as_entry, se_list) { 
     767                        /* 
     768                         * If seen then reset and don't bump the count; 
     769                         * otherwise bump the ``not seen'' count.  Note 
     770                         * that this ensures that stations for which we 
     771                         * see frames while not scanning but not during 
     772                         * this scan will not be penalized. 
     773                         */ 
     774                        if (se->se_seen) 
     775                                se->se_seen = 0; 
     776                        else 
     777                                se->se_notseen++; 
     778                } 
     779                as->as_newscan = 0; 
     780        } 
     781        SCAN_AP_UNLOCK_IRQ(as); 
    414782 
    415783        (*ss->ss_ops->scan_default)(vap, &as->as_selbss); 
     
    442810}; 
    443811 
     812 
    444813static int __init 
    445814init_scanner_ap(void) 
  • madwifi/trunk/net80211/ieee80211_wireless.c

    r2716 r2724  
    16481648        iwe.cmd = SIOCGIWESSID; 
    16491649        iwe.u.data.flags = 1; 
    1650         if (vap->iv_opmode == IEEE80211_M_HOSTAP) { 
    1651                 iwe.u.data.length = vap->iv_des_nssid > 0 ? 
    1652                         vap->iv_des_ssid[0].len : 0; 
    1653                 current_ev = iwe_stream_add_point(current_ev, 
    1654                         end_buf, &iwe, vap->iv_des_ssid[0].ssid); 
    1655         } else { 
    1656                 iwe.u.data.length = se->se_ssid[1]; 
    1657                 current_ev = iwe_stream_add_point(current_ev, 
    1658                         end_buf, &iwe, (char *) se->se_ssid+2); 
    1659         } 
     1650        iwe.u.data.length = se->se_ssid[1]; 
     1651        current_ev = iwe_stream_add_point(current_ev, 
     1652                end_buf, &iwe, (char *) se->se_ssid+2); 
    16601653 
    16611654        /* We ran out of space in the buffer. */