The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net80211/ieee80211_scan_sw.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   24  */
   25 
   26 #include <sys/cdefs.h>
   27 __FBSDID("$FreeBSD$");
   28 
   29 /*
   30  * IEEE 802.11 scanning support.
   31  */
   32 #include "opt_wlan.h"
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h> 
   36 #include <sys/proc.h>
   37 #include <sys/kernel.h>
   38 #include <sys/malloc.h>
   39 #include <sys/condvar.h>
   40 
   41 #include <sys/socket.h>
   42 
   43 #include <net/if.h>
   44 #include <net/if_var.h>
   45 #include <net/if_media.h>
   46 #include <net/ethernet.h>
   47 
   48 #include <net80211/ieee80211_var.h>
   49 
   50 #include <net80211/ieee80211_scan_sw.h>
   51 
   52 #include <net/bpf.h>
   53 
   54 struct scan_state {
   55         struct ieee80211_scan_state base;       /* public state */
   56 
   57         u_int                   ss_iflags;      /* flags used internally */
   58 #define ISCAN_MINDWELL          0x0001          /* min dwell time reached */
   59 #define ISCAN_DISCARD           0x0002          /* discard rx'd frames */
   60 #define ISCAN_INTERRUPT         0x0004          /* interrupt current scan */
   61 #define ISCAN_CANCEL            0x0008          /* cancel current scan */
   62 #define ISCAN_PAUSE             (ISCAN_INTERRUPT | ISCAN_CANCEL)
   63 #define ISCAN_ABORT             0x0010          /* end the scan immediately */
   64 #define ISCAN_RUNNING           0x0020          /* scan was started */
   65 
   66         unsigned long           ss_chanmindwell;  /* min dwell on curchan */
   67         unsigned long           ss_scanend;     /* time scan must stop */
   68         u_int                   ss_duration;    /* duration for next scan */
   69         struct task             ss_scan_start;  /* scan start */
   70         struct timeout_task     ss_scan_curchan;  /* scan execution */
   71 };
   72 #define SCAN_PRIVATE(ss)        ((struct scan_state *) ss)
   73 
   74 /*
   75  * Amount of time to go off-channel during a background
   76  * scan.  This value should be large enough to catch most
   77  * ap's but short enough that we can return on-channel
   78  * before our listen interval expires.
   79  *
   80  * XXX tunable
   81  * XXX check against configured listen interval
   82  */
   83 #define IEEE80211_SCAN_OFFCHANNEL       msecs_to_ticks(150)
   84 
   85 static  void scan_curchan(struct ieee80211_scan_state *, unsigned long);
   86 static  void scan_mindwell(struct ieee80211_scan_state *);
   87 static  void scan_signal(struct ieee80211_scan_state *, int);
   88 static  void scan_signal_locked(struct ieee80211_scan_state *, int);
   89 static  void scan_start(void *, int);
   90 static  void scan_curchan_task(void *, int);
   91 static  void scan_end(struct ieee80211_scan_state *, int);
   92 static  void scan_done(struct ieee80211_scan_state *, int);
   93 
   94 MALLOC_DEFINE(M_80211_SCAN, "80211scan", "802.11 scan state");
   95 
   96 static void
   97 ieee80211_swscan_detach(struct ieee80211com *ic)
   98 {
   99         struct ieee80211_scan_state *ss = ic->ic_scan;
  100 
  101         if (ss != NULL) {
  102                 scan_signal(ss, ISCAN_ABORT);
  103                 ieee80211_draintask(ic, &SCAN_PRIVATE(ss)->ss_scan_start);
  104                 taskqueue_drain_timeout(ic->ic_tq,
  105                     &SCAN_PRIVATE(ss)->ss_scan_curchan);
  106                 KASSERT((ic->ic_flags & IEEE80211_F_SCAN) == 0,
  107                     ("scan still running"));
  108 
  109                 /*
  110                  * For now, do the ss_ops detach here rather
  111                  * than ieee80211_scan_detach().
  112                  *
  113                  * I'll figure out how to cleanly split things up
  114                  * at a later date.
  115                  */
  116                 if (ss->ss_ops != NULL) {
  117                         ss->ss_ops->scan_detach(ss);
  118                         ss->ss_ops = NULL;
  119                 }
  120                 ic->ic_scan = NULL;
  121                 IEEE80211_FREE(SCAN_PRIVATE(ss), M_80211_SCAN);
  122         }
  123 }
  124 
  125 static void
  126 ieee80211_swscan_vattach(struct ieee80211vap *vap)
  127 {
  128         /* nothing to do for now */
  129         /*
  130          * TODO: all of the vap scan calls should be methods!
  131          */
  132 
  133 }
  134 
  135 static void
  136 ieee80211_swscan_vdetach(struct ieee80211vap *vap)
  137 {
  138         struct ieee80211com *ic = vap->iv_ic;
  139         struct ieee80211_scan_state *ss = ic->ic_scan;
  140 
  141         IEEE80211_LOCK_ASSERT(ic);
  142 
  143         if (ss != NULL && ss->ss_vap == vap &&
  144             (ic->ic_flags & IEEE80211_F_SCAN))
  145                 scan_signal_locked(ss, ISCAN_ABORT);
  146 }
  147 
  148 static void
  149 ieee80211_swscan_set_scan_duration(struct ieee80211vap *vap, u_int duration)
  150 {
  151         struct ieee80211com *ic = vap->iv_ic;
  152         struct ieee80211_scan_state *ss = ic->ic_scan;
  153 
  154         IEEE80211_LOCK_ASSERT(ic);
  155 
  156         /* NB: flush frames rx'd before 1st channel change */
  157         SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD;
  158         SCAN_PRIVATE(ss)->ss_duration = duration;
  159 }
  160 
  161 /*
  162  * Start a scan unless one is already going.
  163  */
  164 static int
  165 ieee80211_swscan_start_scan_locked(const struct ieee80211_scanner *scan,
  166         struct ieee80211vap *vap, int flags, u_int duration,
  167         u_int mindwell, u_int maxdwell,
  168         u_int nssid, const struct ieee80211_scan_ssid ssids[])
  169 {
  170         struct ieee80211com *ic = vap->iv_ic;
  171         struct ieee80211_scan_state *ss = ic->ic_scan;
  172 
  173         IEEE80211_LOCK_ASSERT(ic);
  174 
  175         if (ic->ic_flags & IEEE80211_F_CSAPENDING) {
  176                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
  177                     "%s: scan inhibited by pending channel change\n", __func__);
  178         } else if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
  179                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
  180                     "%s: %s scan, duration %u mindwell %u maxdwell %u, desired mode %s, %s%s%s%s%s%s\n"
  181                     , __func__
  182                     , flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive"
  183                     , duration, mindwell, maxdwell
  184                     , ieee80211_phymode_name[vap->iv_des_mode]
  185                     , flags & IEEE80211_SCAN_FLUSH ? "flush" : "append"
  186                     , flags & IEEE80211_SCAN_NOPICK ? ", nopick" : ""
  187                     , flags & IEEE80211_SCAN_NOJOIN ? ", nojoin" : ""
  188                     , flags & IEEE80211_SCAN_NOBCAST ? ", nobcast" : ""
  189                     , flags & IEEE80211_SCAN_PICK1ST ? ", pick1st" : ""
  190                     , flags & IEEE80211_SCAN_ONCE ? ", once" : ""
  191                 );
  192 
  193                 ieee80211_scan_update_locked(vap, scan);
  194                 if (ss->ss_ops != NULL) {
  195                         if ((flags & IEEE80211_SCAN_NOSSID) == 0)
  196                                 ieee80211_scan_copy_ssid(vap, ss, nssid, ssids);
  197 
  198                         /* NB: top 4 bits for internal use */
  199                         ss->ss_flags = flags & 0xfff;
  200                         if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
  201                                 vap->iv_stats.is_scan_active++;
  202                         else
  203                                 vap->iv_stats.is_scan_passive++;
  204                         if (flags & IEEE80211_SCAN_FLUSH)
  205                                 ss->ss_ops->scan_flush(ss);
  206                         if (flags & IEEE80211_SCAN_BGSCAN)
  207                                 ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN;
  208 
  209                         /* Set duration for this particular scan */
  210                         ieee80211_swscan_set_scan_duration(vap, duration);
  211 
  212                         ss->ss_next = 0;
  213                         ss->ss_mindwell = mindwell;
  214                         ss->ss_maxdwell = maxdwell;
  215                         /* NB: scan_start must be before the scan runtask */
  216                         ss->ss_ops->scan_start(ss, vap);
  217 #ifdef IEEE80211_DEBUG
  218                         if (ieee80211_msg_scan(vap))
  219                                 ieee80211_scan_dump(ss);
  220 #endif /* IEEE80211_DEBUG */
  221                         ic->ic_flags |= IEEE80211_F_SCAN;
  222 
  223                         /* Start scan task */
  224                         ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_start);
  225                 }
  226                 return 1;
  227         } else {
  228                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
  229                     "%s: %s scan already in progress\n", __func__,
  230                     ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive");
  231         }
  232         return 0;
  233 }
  234 
  235 /*
  236  * Start a scan unless one is already going.
  237  *
  238  * Called without the comlock held; grab the comlock as appropriate.
  239  */
  240 static int
  241 ieee80211_swscan_start_scan(const struct ieee80211_scanner *scan,
  242     struct ieee80211vap *vap, int flags,
  243     u_int duration, u_int mindwell, u_int maxdwell,
  244     u_int nssid, const struct ieee80211_scan_ssid ssids[])
  245 {
  246         struct ieee80211com *ic = vap->iv_ic;
  247         int result;
  248 
  249         IEEE80211_UNLOCK_ASSERT(ic);
  250 
  251         IEEE80211_LOCK(ic);
  252         result = ieee80211_swscan_start_scan_locked(scan, vap, flags, duration,
  253             mindwell, maxdwell, nssid, ssids);
  254         IEEE80211_UNLOCK(ic);
  255 
  256         return result;
  257 }
  258 
  259 /*
  260  * Check the scan cache for an ap/channel to use; if that
  261  * fails then kick off a new scan.
  262  *
  263  * Called with the comlock held.
  264  *
  265  * XXX TODO: split out!
  266  */
  267 static int
  268 ieee80211_swscan_check_scan(const struct ieee80211_scanner *scan,
  269     struct ieee80211vap *vap, int flags,
  270     u_int duration, u_int mindwell, u_int maxdwell,
  271     u_int nssid, const struct ieee80211_scan_ssid ssids[])
  272 {
  273         struct ieee80211com *ic = vap->iv_ic;
  274         struct ieee80211_scan_state *ss = ic->ic_scan;
  275         int result;
  276 
  277         IEEE80211_LOCK_ASSERT(ic);
  278 
  279         if (ss->ss_ops != NULL) {
  280                 /* XXX verify ss_ops matches vap->iv_opmode */
  281                 if ((flags & IEEE80211_SCAN_NOSSID) == 0) {
  282                         /*
  283                          * Update the ssid list and mark flags so if
  284                          * we call start_scan it doesn't duplicate work.
  285                          */
  286                         ieee80211_scan_copy_ssid(vap, ss, nssid, ssids);
  287                         flags |= IEEE80211_SCAN_NOSSID;
  288                 }
  289                 if ((ic->ic_flags & IEEE80211_F_SCAN) == 0 &&
  290                     (flags & IEEE80211_SCAN_FLUSH) == 0 &&
  291                     ieee80211_time_before(ticks, ic->ic_lastscan + vap->iv_scanvalid)) {
  292                         /*
  293                          * We're not currently scanning and the cache is
  294                          * deemed hot enough to consult.  Lock out others
  295                          * by marking IEEE80211_F_SCAN while we decide if
  296                          * something is already in the scan cache we can
  297                          * use.  Also discard any frames that might come
  298                          * in while temporarily marked as scanning.
  299                          */
  300                         IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
  301                             "cache hot; ic_lastscan=%d, scanvalid=%d, ticks=%d\n",
  302                             ic->ic_lastscan,
  303                             vap->iv_scanvalid,
  304                             ticks);
  305                         SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD;
  306                         ic->ic_flags |= IEEE80211_F_SCAN;
  307 
  308                         /* NB: need to use supplied flags in check */
  309                         ss->ss_flags = flags & 0xff;
  310                         result = ss->ss_ops->scan_end(ss, vap);
  311 
  312                         ic->ic_flags &= ~IEEE80211_F_SCAN;
  313                         SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_DISCARD;
  314                         IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
  315                             "%s: scan_end returned %d\n", __func__, result);
  316                         if (result) {
  317                                 ieee80211_notify_scan_done(vap);
  318                                 return 1;
  319                         }
  320                 }
  321         }
  322         result = ieee80211_swscan_start_scan_locked(scan, vap, flags, duration,
  323             mindwell, maxdwell, nssid, ssids);
  324 
  325         return result;
  326 }
  327 
  328 /*
  329  * Restart a previous scan.  If the previous scan completed
  330  * then we start again using the existing channel list.
  331  */
  332 static int
  333 ieee80211_swscan_bg_scan(const struct ieee80211_scanner *scan,
  334     struct ieee80211vap *vap, int flags)
  335 {
  336         struct ieee80211com *ic = vap->iv_ic;
  337         struct ieee80211_scan_state *ss = ic->ic_scan;
  338 
  339         /* XXX assert unlocked? */
  340         // IEEE80211_UNLOCK_ASSERT(ic);
  341 
  342         IEEE80211_LOCK(ic);
  343         if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
  344                 u_int duration;
  345                 /*
  346                  * Go off-channel for a fixed interval that is large
  347                  * enough to catch most ap's but short enough that
  348                  * we can return on-channel before our listen interval
  349                  * expires.
  350                  */
  351                 duration = IEEE80211_SCAN_OFFCHANNEL;
  352 
  353                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
  354                     "%s: %s scan, ticks %u duration %u\n", __func__,
  355                     ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive",
  356                     ticks, duration);
  357 
  358                 ieee80211_scan_update_locked(vap, scan);
  359                 if (ss->ss_ops != NULL) {
  360                         ss->ss_vap = vap;
  361                         /*
  362                          * A background scan does not select a new sta; it
  363                          * just refreshes the scan cache.  Also, indicate
  364                          * the scan logic should follow the beacon schedule:
  365                          * we go off-channel and scan for a while, then
  366                          * return to the bss channel to receive a beacon,
  367                          * then go off-channel again.  All during this time
  368                          * we notify the ap we're in power save mode.  When
  369                          * the scan is complete we leave power save mode.
  370                          * If any beacon indicates there are frames pending
  371                          * for us then we drop out of power save mode
  372                          * (and background scan) automatically by way of the
  373                          * usual sta power save logic.
  374                          */
  375                         ss->ss_flags |= IEEE80211_SCAN_NOPICK
  376                                      |  IEEE80211_SCAN_BGSCAN
  377                                      |  flags
  378                                      ;
  379                         /* if previous scan completed, restart */
  380                         if (ss->ss_next >= ss->ss_last) {
  381                                 if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
  382                                         vap->iv_stats.is_scan_active++;
  383                                 else
  384                                         vap->iv_stats.is_scan_passive++;
  385                                 /*
  386                                  * NB: beware of the scan cache being flushed;
  387                                  *     if the channel list is empty use the
  388                                  *     scan_start method to populate it.
  389                                  */
  390                                 ss->ss_next = 0;
  391                                 if (ss->ss_last != 0)
  392                                         ss->ss_ops->scan_restart(ss, vap);
  393                                 else {
  394                                         ss->ss_ops->scan_start(ss, vap);
  395 #ifdef IEEE80211_DEBUG
  396                                         if (ieee80211_msg_scan(vap))
  397                                                 ieee80211_scan_dump(ss);
  398 #endif /* IEEE80211_DEBUG */
  399                                 }
  400                         }
  401                         ieee80211_swscan_set_scan_duration(vap, duration);
  402                         ss->ss_maxdwell = duration;
  403                         ic->ic_flags |= IEEE80211_F_SCAN;
  404                         ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN;
  405                         ieee80211_runtask(ic,
  406                             &SCAN_PRIVATE(ss)->ss_scan_start);
  407                 } else {
  408                         /* XXX msg+stat */
  409                 }
  410         } else {
  411                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
  412                     "%s: %s scan already in progress\n", __func__,
  413                     ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive");
  414         }
  415         IEEE80211_UNLOCK(ic);
  416 
  417         /* NB: racey, does it matter? */
  418         return (ic->ic_flags & IEEE80211_F_SCAN);
  419 }
  420 
  421 /*
  422  * Taskqueue work to cancel a scan.
  423  *
  424  * Note: for offload scan devices, we may want to call into the
  425  * driver to try and cancel scanning, however it may not be cancelable.
  426  */
  427 static void
  428 cancel_scan(struct ieee80211vap *vap, int any, const char *func)
  429 {
  430         struct ieee80211com *ic = vap->iv_ic;
  431         struct ieee80211_scan_state *ss = ic->ic_scan;
  432         struct scan_state *ss_priv = SCAN_PRIVATE(ss);
  433         int signal;
  434 
  435         IEEE80211_LOCK(ic);
  436         signal = any ? ISCAN_PAUSE : ISCAN_CANCEL;
  437         if ((ic->ic_flags & IEEE80211_F_SCAN) &&
  438             (any || ss->ss_vap == vap) &&
  439             (ss_priv->ss_iflags & signal) == 0) {
  440                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
  441                     "%s: %s %s scan\n", func,
  442                     any ? "pause" : "cancel",
  443                     ss->ss_flags & IEEE80211_SCAN_ACTIVE ?
  444                         "active" : "passive");
  445 
  446                 /* clear bg scan NOPICK */
  447                 ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
  448                 /* mark request and wake up the scan task */
  449                 scan_signal_locked(ss, signal);
  450         } else {
  451                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
  452                     "%s: called; F_SCAN=%d, vap=%s, signal=%d\n",
  453                         func,
  454                         !! (ic->ic_flags & IEEE80211_F_SCAN),
  455                         (ss->ss_vap == vap ? "match" : "nomatch"),
  456                         !! (ss_priv->ss_iflags & signal));
  457         }
  458         IEEE80211_UNLOCK(ic);
  459 }
  460 
  461 /*
  462  * Cancel any scan currently going on for the specified vap.
  463  */
  464 static void
  465 ieee80211_swscan_cancel_scan(struct ieee80211vap *vap)
  466 {
  467         cancel_scan(vap, 0, __func__);
  468 }
  469 
  470 /*
  471  * Cancel any scan currently going on.
  472  */
  473 static void
  474 ieee80211_swscan_cancel_anyscan(struct ieee80211vap *vap)
  475 {
  476 
  477         /* XXX for now - just don't do this per packet. */
  478         if (vap->iv_flags_ext & IEEE80211_FEXT_SCAN_OFFLOAD)
  479                 return;
  480 
  481         cancel_scan(vap, 1, __func__);
  482 }
  483 
  484 /*
  485  * Manually switch to the next channel in the channel list.
  486  * Provided for drivers that manage scanning themselves
  487  * (e.g. for firmware-based devices).
  488  */
  489 static void
  490 ieee80211_swscan_scan_next(struct ieee80211vap *vap)
  491 {
  492         struct ieee80211_scan_state *ss = vap->iv_ic->ic_scan;
  493 
  494         IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: called\n", __func__);
  495 
  496         /* wake up the scan task */
  497         scan_signal(ss, 0);
  498 }
  499 
  500 /*
  501  * Manually stop a scan that is currently running.
  502  * Provided for drivers that are not able to scan single channels
  503  * (e.g. for firmware-based devices).
  504  */
  505 static void
  506 ieee80211_swscan_scan_done(struct ieee80211vap *vap)
  507 {
  508         struct ieee80211com *ic = vap->iv_ic;
  509         struct ieee80211_scan_state *ss = ic->ic_scan;
  510 
  511         IEEE80211_LOCK_ASSERT(ic);
  512 
  513         scan_signal_locked(ss, 0);
  514 }
  515 
  516 /*
  517  * Probe the current channel, if allowed, while scanning.
  518  * If the channel is not marked passive-only then send
  519  * a probe request immediately.  Otherwise mark state and
  520  * listen for beacons on the channel; if we receive something
  521  * then we'll transmit a probe request.
  522  */
  523 static void
  524 ieee80211_swscan_probe_curchan(struct ieee80211vap *vap, int force)
  525 {
  526         struct ieee80211com *ic = vap->iv_ic;
  527         struct ieee80211_scan_state *ss = ic->ic_scan;
  528         struct ifnet *ifp = vap->iv_ifp;
  529         int i;
  530 
  531         /*
  532          * Full-offload scan devices don't require this.
  533          */
  534         if (vap->iv_flags_ext & IEEE80211_FEXT_SCAN_OFFLOAD)
  535                 return;
  536 
  537         /*
  538          * Send directed probe requests followed by any
  539          * broadcast probe request.
  540          * XXX remove dependence on ic/vap->iv_bss
  541          */
  542         for (i = 0; i < ss->ss_nssid; i++)
  543                 ieee80211_send_probereq(vap->iv_bss,
  544                         vap->iv_myaddr, ifp->if_broadcastaddr,
  545                         ifp->if_broadcastaddr,
  546                         ss->ss_ssid[i].ssid, ss->ss_ssid[i].len);
  547         if ((ss->ss_flags & IEEE80211_SCAN_NOBCAST) == 0)
  548                 ieee80211_send_probereq(vap->iv_bss,
  549                         vap->iv_myaddr, ifp->if_broadcastaddr,
  550                         ifp->if_broadcastaddr,
  551                         "", 0);
  552 }
  553 
  554 /*
  555  * Scan curchan.  If this is an active scan and the channel
  556  * is not marked passive then send probe request frame(s).
  557  * Arrange for the channel change after maxdwell ticks.
  558  */
  559 static void
  560 scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
  561 {
  562         struct ieee80211vap *vap  = ss->ss_vap;
  563         struct ieee80211com *ic = ss->ss_ic;
  564 
  565         IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
  566             "%s: calling; maxdwell=%lu\n",
  567             __func__,
  568             maxdwell);
  569         IEEE80211_LOCK(ic);
  570         if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
  571                 ieee80211_probe_curchan(vap, 0);
  572         taskqueue_enqueue_timeout(ic->ic_tq,
  573             &SCAN_PRIVATE(ss)->ss_scan_curchan, maxdwell);
  574         IEEE80211_UNLOCK(ic);
  575 }
  576 
  577 static void
  578 scan_signal(struct ieee80211_scan_state *ss, int iflags)
  579 {
  580         struct ieee80211com *ic = ss->ss_ic;
  581 
  582         IEEE80211_UNLOCK_ASSERT(ic);
  583 
  584         IEEE80211_LOCK(ic);
  585         scan_signal_locked(ss, iflags);
  586         IEEE80211_UNLOCK(ic);
  587 }
  588 
  589 static void
  590 scan_signal_locked(struct ieee80211_scan_state *ss, int iflags)
  591 {
  592         struct scan_state *ss_priv = SCAN_PRIVATE(ss);
  593         struct timeout_task *scan_task = &ss_priv->ss_scan_curchan;
  594         struct ieee80211com *ic = ss->ss_ic;
  595 
  596         IEEE80211_LOCK_ASSERT(ic);
  597 
  598         ss_priv->ss_iflags |= iflags;
  599         if (ss_priv->ss_iflags & ISCAN_RUNNING) {
  600                 if (taskqueue_cancel_timeout(ic->ic_tq, scan_task, NULL) == 0)
  601                         taskqueue_enqueue_timeout(ic->ic_tq, scan_task, 0);
  602         }
  603 }
  604 
  605 /*
  606  * Handle mindwell requirements completed; initiate a channel
  607  * change to the next channel asap.
  608  */
  609 static void
  610 scan_mindwell(struct ieee80211_scan_state *ss)
  611 {
  612 
  613         IEEE80211_DPRINTF(ss->ss_vap, IEEE80211_MSG_SCAN, "%s: called\n",
  614             __func__);
  615 
  616         scan_signal(ss, 0);
  617 }
  618 
  619 static void
  620 scan_start(void *arg, int pending)
  621 {
  622 #define ISCAN_REP       (ISCAN_MINDWELL | ISCAN_DISCARD)
  623         struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg;
  624         struct scan_state *ss_priv = SCAN_PRIVATE(ss);
  625         struct ieee80211vap *vap = ss->ss_vap;
  626         struct ieee80211com *ic = ss->ss_ic;
  627 
  628         IEEE80211_LOCK(ic);
  629         if (vap == NULL || (ic->ic_flags & IEEE80211_F_SCAN) == 0 ||
  630             (ss_priv->ss_iflags & ISCAN_ABORT)) {
  631                 /* Cancelled before we started */
  632                 scan_done(ss, 0);
  633                 return;
  634         }
  635 
  636         if (ss->ss_next == ss->ss_last) {
  637                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
  638                         "%s: no channels to scan\n", __func__);
  639                 scan_done(ss, 1);
  640                 return;
  641         }
  642 
  643         /*
  644          * Put the station into power save mode.
  645          *
  646          * This is only required if we're not a full-offload devices;
  647          * those devices manage scan/traffic differently.
  648          */
  649         if (((vap->iv_flags_ext & IEEE80211_FEXT_SCAN_OFFLOAD) == 0) &&
  650             vap->iv_opmode == IEEE80211_M_STA &&
  651             vap->iv_state == IEEE80211_S_RUN) {
  652                 if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) {
  653                         /* Enable station power save mode */
  654                         vap->iv_sta_ps(vap, 1);
  655                         /* Wait until null data frame will be ACK'ed */
  656                         mtx_sleep(vap, IEEE80211_LOCK_OBJ(ic), PCATCH,
  657                             "sta_ps", msecs_to_ticks(10));
  658                         if (ss_priv->ss_iflags & ISCAN_ABORT) {
  659                                 scan_done(ss, 0);
  660                                 return;
  661                         }
  662                 }
  663         }
  664 
  665         ss_priv->ss_scanend = ticks + ss_priv->ss_duration;
  666 
  667         /* XXX scan state can change! Re-validate scan state! */
  668 
  669         IEEE80211_UNLOCK(ic);
  670 
  671         ic->ic_scan_start(ic);          /* notify driver */
  672 
  673         scan_curchan_task(ss, 0);
  674 }
  675 
  676 static void
  677 scan_curchan_task(void *arg, int pending)
  678 {
  679         struct ieee80211_scan_state *ss = arg;
  680         struct scan_state *ss_priv = SCAN_PRIVATE(ss);
  681         struct ieee80211com *ic = ss->ss_ic;
  682         struct ieee80211_channel *chan;
  683         unsigned long maxdwell;
  684         int scandone, scanstop;
  685 
  686         IEEE80211_LOCK(ic);
  687 end:
  688         /*
  689          * Note: only /end/ the scan if we're CANCEL rather than
  690          * CANCEL+INTERRUPT (ie, 'PAUSE').
  691          *
  692          * We can stop the scan if we hit cancel, but we shouldn't
  693          * call scan_end(ss, 1) if we're just PAUSEing the scan.
  694          */
  695         scandone = (ss->ss_next >= ss->ss_last) ||
  696             ((ss_priv->ss_iflags & ISCAN_PAUSE) == ISCAN_CANCEL);
  697         scanstop = (ss->ss_next >= ss->ss_last) ||
  698             ((ss_priv->ss_iflags & ISCAN_CANCEL) != 0);
  699 
  700         IEEE80211_DPRINTF(ss->ss_vap, IEEE80211_MSG_SCAN,
  701             "%s: loop start; scandone=%d, scanstop=%d, ss_iflags=0x%x, ss_next=%u, ss_last=%u\n",
  702             __func__,
  703             scandone,
  704             scanstop,
  705             (uint32_t) ss_priv->ss_iflags,
  706             (uint32_t) ss->ss_next,
  707             (uint32_t) ss->ss_last);
  708 
  709         if (scanstop || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) ||
  710             (ss_priv->ss_iflags & ISCAN_ABORT) ||
  711              ieee80211_time_after(ticks + ss->ss_mindwell, ss_priv->ss_scanend)) {
  712                 ss_priv->ss_iflags &= ~ISCAN_RUNNING;
  713                 scan_end(ss, scandone);
  714                 return;
  715         } else
  716                 ss_priv->ss_iflags |= ISCAN_RUNNING;
  717 
  718         chan = ss->ss_chans[ss->ss_next++];
  719 
  720         /*
  721          * Watch for truncation due to the scan end time.
  722          */
  723         if (ieee80211_time_after(ticks + ss->ss_maxdwell, ss_priv->ss_scanend))
  724                 maxdwell = ss_priv->ss_scanend - ticks;
  725         else
  726                 maxdwell = ss->ss_maxdwell;
  727 
  728         IEEE80211_DPRINTF(ss->ss_vap, IEEE80211_MSG_SCAN,
  729             "%s: chan %3d%c -> %3d%c [%s, dwell min %lums max %lums]\n",
  730             __func__,
  731             ieee80211_chan2ieee(ic, ic->ic_curchan),
  732             ieee80211_channel_type_char(ic->ic_curchan),
  733             ieee80211_chan2ieee(ic, chan),
  734             ieee80211_channel_type_char(chan),
  735             (ss->ss_flags & IEEE80211_SCAN_ACTIVE) &&
  736                 (chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0 ?
  737                 "active" : "passive",
  738             ticks_to_msecs(ss->ss_mindwell), ticks_to_msecs(maxdwell));
  739 
  740         /*
  741          * Potentially change channel and phy mode.
  742          */
  743         ic->ic_curchan = chan;
  744         ic->ic_rt = ieee80211_get_ratetable(chan);
  745         IEEE80211_UNLOCK(ic);
  746         /*
  747          * Perform the channel change and scan unlocked so the driver
  748          * may sleep. Once set_channel returns the hardware has
  749          * completed the channel change.
  750          */
  751         ic->ic_set_channel(ic);
  752         ieee80211_radiotap_chan_change(ic);
  753 
  754         /*
  755          * Scan curchan.  Drivers for "intelligent hardware"
  756          * override ic_scan_curchan to tell the device to do
  757          * the work.  Otherwise we manage the work ourselves;
  758          * sending a probe request (as needed), and arming the
  759          * timeout to switch channels after maxdwell ticks.
  760          *
  761          * scan_curchan should only pause for the time required to
  762          * prepare/initiate the hardware for the scan (if at all).
  763          */
  764         ic->ic_scan_curchan(ss, maxdwell);
  765         IEEE80211_LOCK(ic);
  766 
  767         /* XXX scan state can change! Re-validate scan state! */
  768 
  769         ss_priv->ss_chanmindwell = ticks + ss->ss_mindwell;
  770         /* clear mindwell lock and initial channel change flush */
  771         ss_priv->ss_iflags &= ~ISCAN_REP;
  772 
  773         if (ss_priv->ss_iflags & (ISCAN_CANCEL|ISCAN_ABORT)) {
  774                 taskqueue_cancel_timeout(ic->ic_tq, &ss_priv->ss_scan_curchan,
  775                     NULL);
  776                 goto end;
  777         }
  778 
  779         IEEE80211_DPRINTF(ss->ss_vap, IEEE80211_MSG_SCAN, "%s: waiting\n",
  780             __func__);
  781         IEEE80211_UNLOCK(ic);
  782 }
  783 
  784 static void
  785 scan_end(struct ieee80211_scan_state *ss, int scandone)
  786 {
  787         struct scan_state *ss_priv = SCAN_PRIVATE(ss);
  788         struct ieee80211vap *vap = ss->ss_vap;
  789         struct ieee80211com *ic = ss->ss_ic;
  790 
  791         IEEE80211_LOCK_ASSERT(ic);
  792 
  793         IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: out\n", __func__);
  794 
  795         if (ss_priv->ss_iflags & ISCAN_ABORT) {
  796                 scan_done(ss, scandone);
  797                 return;
  798         }
  799 
  800         IEEE80211_UNLOCK(ic);
  801         ic->ic_scan_end(ic);            /* notify driver */
  802         IEEE80211_LOCK(ic);
  803         /* XXX scan state can change! Re-validate scan state! */
  804 
  805         /*
  806          * Since a cancellation may have occurred during one of the
  807          * driver calls (whilst unlocked), update scandone.
  808          */
  809         if ((scandone == 0) && ((ss_priv->ss_iflags & ISCAN_PAUSE) == ISCAN_CANCEL)) {
  810                 /* XXX printf? */
  811                 if_printf(vap->iv_ifp,
  812                     "%s: OOPS! scan cancelled during driver call (1) (ss_iflags=0x%x)!\n",
  813                     __func__,
  814                     ss_priv->ss_iflags);
  815                 scandone = 1;
  816         }
  817 
  818         /*
  819          * Record scan complete time.  Note that we also do
  820          * this when canceled so any background scan will
  821          * not be restarted for a while.
  822          */
  823         if (scandone)
  824                 ic->ic_lastscan = ticks;
  825         /* return to the bss channel */
  826         if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
  827             ic->ic_curchan != ic->ic_bsschan) {
  828                 ieee80211_setupcurchan(ic, ic->ic_bsschan);
  829                 IEEE80211_UNLOCK(ic);
  830                 ic->ic_set_channel(ic);
  831                 ieee80211_radiotap_chan_change(ic);
  832                 IEEE80211_LOCK(ic);
  833         }
  834         /* clear internal flags and any indication of a pick */
  835         ss_priv->ss_iflags &= ~ISCAN_REP;
  836         ss->ss_flags &= ~IEEE80211_SCAN_GOTPICK;
  837 
  838         /*
  839          * If not canceled and scan completed, do post-processing.
  840          * If the callback function returns 0, then it wants to
  841          * continue/restart scanning.  Unfortunately we needed to
  842          * notify the driver to end the scan above to avoid having
  843          * rx frames alter the scan candidate list.
  844          */
  845         if ((ss_priv->ss_iflags & ISCAN_CANCEL) == 0 &&
  846             !ss->ss_ops->scan_end(ss, vap) &&
  847             (ss->ss_flags & IEEE80211_SCAN_ONCE) == 0 &&
  848             ieee80211_time_before(ticks + ss->ss_mindwell, ss_priv->ss_scanend)) {
  849                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
  850                     "%s: done, restart "
  851                     "[ticks %u, dwell min %lu scanend %lu]\n",
  852                     __func__,
  853                     ticks, ss->ss_mindwell, ss_priv->ss_scanend);
  854                 ss->ss_next = 0;        /* reset to beginning */
  855                 if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
  856                         vap->iv_stats.is_scan_active++;
  857                 else
  858                         vap->iv_stats.is_scan_passive++;
  859 
  860                 ss->ss_ops->scan_restart(ss, vap);      /* XXX? */
  861                 ieee80211_runtask(ic, &ss_priv->ss_scan_start);
  862                 IEEE80211_UNLOCK(ic);
  863                 return;
  864         }
  865 
  866         /* past here, scandone is ``true'' if not in bg mode */
  867         if ((ss->ss_flags & IEEE80211_SCAN_BGSCAN) == 0)
  868                 scandone = 1;
  869 
  870         IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
  871             "%s: %s, [ticks %u, dwell min %lu scanend %lu]\n",
  872             __func__, scandone ? "done" : "stopped",
  873             ticks, ss->ss_mindwell, ss_priv->ss_scanend);
  874 
  875         /*
  876          * Since a cancellation may have occurred during one of the
  877          * driver calls (whilst unlocked), update scandone.
  878          */
  879         if (scandone == 0 && (ss_priv->ss_iflags & ISCAN_PAUSE) == ISCAN_CANCEL) {
  880                 /* XXX printf? */
  881                 if_printf(vap->iv_ifp,
  882                     "%s: OOPS! scan cancelled during driver call (2) (ss_iflags=0x%x)!\n",
  883                     __func__,
  884                     ss_priv->ss_iflags);
  885                 scandone = 1;
  886         }
  887 
  888         scan_done(ss, scandone);
  889 }
  890 
  891 static void
  892 scan_done(struct ieee80211_scan_state *ss, int scandone)
  893 {
  894         struct scan_state *ss_priv = SCAN_PRIVATE(ss);
  895         struct ieee80211com *ic = ss->ss_ic;
  896         struct ieee80211vap *vap = ss->ss_vap;
  897 
  898         IEEE80211_LOCK_ASSERT(ic);
  899 
  900         /*
  901          * Clear the SCAN bit first in case frames are
  902          * pending on the station power save queue.  If
  903          * we defer this then the dispatch of the frames
  904          * may generate a request to cancel scanning.
  905          */
  906         ic->ic_flags &= ~IEEE80211_F_SCAN;
  907 
  908         /*
  909          * Drop out of power save mode when a scan has
  910          * completed.  If this scan was prematurely terminated
  911          * because it is a background scan then don't notify
  912          * the ap; we'll either return to scanning after we
  913          * receive the beacon frame or we'll drop out of power
  914          * save mode because the beacon indicates we have frames
  915          * waiting for us.
  916          */
  917         if (scandone) {
  918                 /*
  919                  * If we're not a scan offload device, come back out of
  920                  * station powersave.  Offload devices handle this themselves.
  921                  */
  922                 if ((vap->iv_flags_ext & IEEE80211_FEXT_SCAN_OFFLOAD) == 0)
  923                         vap->iv_sta_ps(vap, 0);
  924                 if (ss->ss_next >= ss->ss_last) {
  925                         IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
  926                             "%s: Dropping out of scan; ss_next=%u, ss_last=%u\n",
  927                             __func__,
  928                             (uint32_t) ss->ss_next,
  929                             (uint32_t) ss->ss_last);
  930                         ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN;
  931                 }
  932 
  933                 /* send 'scan done' event if not interrupted due to traffic. */
  934                 if (!(ss_priv->ss_iflags & ISCAN_INTERRUPT) ||
  935                     (ss->ss_next >= ss->ss_last))
  936                         ieee80211_notify_scan_done(vap);
  937         }
  938         ss_priv->ss_iflags &= ~(ISCAN_PAUSE | ISCAN_ABORT);
  939         ss_priv->ss_scanend = 0;
  940         ss->ss_flags &= ~(IEEE80211_SCAN_ONCE | IEEE80211_SCAN_PICK1ST);
  941         IEEE80211_UNLOCK(ic);
  942 #undef ISCAN_REP
  943 }
  944 
  945 /*
  946  * Process a beacon or probe response frame.
  947  */
  948 static void
  949 ieee80211_swscan_add_scan(struct ieee80211vap *vap,
  950         struct ieee80211_channel *curchan,
  951         const struct ieee80211_scanparams *sp,
  952         const struct ieee80211_frame *wh,
  953         int subtype, int rssi, int noise)
  954 {
  955         struct ieee80211com *ic = vap->iv_ic;
  956         struct ieee80211_scan_state *ss = ic->ic_scan;
  957 
  958         /* XXX locking */
  959         /*
  960          * Frames received during startup are discarded to avoid
  961          * using scan state setup on the initial entry to the timer
  962          * callback.  This can occur because the device may enable
  963          * rx prior to our doing the initial channel change in the
  964          * timer routine.
  965          */
  966         if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_DISCARD)
  967                 return;
  968 #ifdef IEEE80211_DEBUG
  969         if (ieee80211_msg_scan(vap) && (ic->ic_flags & IEEE80211_F_SCAN))
  970                 ieee80211_scan_dump_probe_beacon(subtype, 1, wh->i_addr2, sp, rssi);
  971 #endif
  972         if (ss->ss_ops != NULL &&
  973             ss->ss_ops->scan_add(ss, curchan, sp, wh, subtype, rssi, noise)) {
  974                 /*
  975                  * If we've reached the min dwell time terminate
  976                  * the timer so we'll switch to the next channel.
  977                  */
  978                 if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_MINDWELL) == 0 &&
  979                     ieee80211_time_after_eq(ticks, SCAN_PRIVATE(ss)->ss_chanmindwell)) {
  980                         IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
  981                             "%s: chan %3d%c min dwell met (%u > %lu)\n",
  982                             __func__,
  983                             ieee80211_chan2ieee(ic, ic->ic_curchan),
  984                             ieee80211_channel_type_char(ic->ic_curchan),
  985                             ticks, SCAN_PRIVATE(ss)->ss_chanmindwell);
  986                         SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_MINDWELL;
  987                         /*
  988                          * NB: trigger at next clock tick or wait for the
  989                          * hardware.
  990                          */
  991                         ic->ic_scan_mindwell(ss);
  992                 }
  993         }
  994 }
  995 
  996 static struct ieee80211_scan_methods swscan_methods = {
  997         .sc_attach = ieee80211_swscan_attach,
  998         .sc_detach = ieee80211_swscan_detach,
  999         .sc_vattach = ieee80211_swscan_vattach,
 1000         .sc_vdetach = ieee80211_swscan_vdetach,
 1001         .sc_set_scan_duration = ieee80211_swscan_set_scan_duration,
 1002         .sc_start_scan = ieee80211_swscan_start_scan,
 1003         .sc_check_scan = ieee80211_swscan_check_scan,
 1004         .sc_bg_scan = ieee80211_swscan_bg_scan,
 1005         .sc_cancel_scan = ieee80211_swscan_cancel_scan,
 1006         .sc_cancel_anyscan = ieee80211_swscan_cancel_anyscan,
 1007         .sc_scan_next = ieee80211_swscan_scan_next,
 1008         .sc_scan_done = ieee80211_swscan_scan_done,
 1009         .sc_scan_probe_curchan = ieee80211_swscan_probe_curchan,
 1010         .sc_add_scan = ieee80211_swscan_add_scan
 1011 };
 1012 
 1013 /*
 1014  * Default scan attach method.
 1015  */
 1016 void
 1017 ieee80211_swscan_attach(struct ieee80211com *ic)
 1018 {
 1019         struct scan_state *ss;
 1020 
 1021         /*
 1022          * Setup the default methods
 1023          */
 1024         ic->ic_scan_methods = &swscan_methods;
 1025 
 1026         /* Allocate initial scan state */
 1027         ss = (struct scan_state *) IEEE80211_MALLOC(sizeof(struct scan_state),
 1028                 M_80211_SCAN, IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
 1029         if (ss == NULL) {
 1030                 ic->ic_scan = NULL;
 1031                 return;
 1032         }
 1033         TASK_INIT(&ss->ss_scan_start, 0, scan_start, ss);
 1034         TIMEOUT_TASK_INIT(ic->ic_tq, &ss->ss_scan_curchan, 0,
 1035             scan_curchan_task, ss);
 1036 
 1037         ic->ic_scan = &ss->base;
 1038         ss->base.ss_ic = ic;
 1039 
 1040         ic->ic_scan_curchan = scan_curchan;
 1041         ic->ic_scan_mindwell = scan_mindwell;
 1042 }

Cache object: 9da60e93024439d4827058e6b00a18d5


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.