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.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 /*      $OpenBSD: ieee80211.c,v 1.88 2022/03/19 10:25:09 stsp Exp $     */
    2 /*      $NetBSD: ieee80211.c,v 1.19 2004/06/06 05:45:29 dyoung Exp $    */
    3 
    4 /*-
    5  * Copyright (c) 2001 Atsushi Onoe
    6  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. The name of the author may not be used to endorse or promote products
   18  *    derived from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * IEEE 802.11 generic handler
   34  */
   35 
   36 #include "bpfilter.h"
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/mbuf.h>
   41 #include <sys/kernel.h>
   42 #include <sys/socket.h>
   43 #include <sys/sockio.h>
   44 #include <sys/endian.h>
   45 #include <sys/errno.h>
   46 #include <sys/sysctl.h>
   47 
   48 #include <net/if.h>
   49 #include <net/if_dl.h>
   50 #include <net/if_media.h>
   51 
   52 #if NBPFILTER > 0
   53 #include <net/bpf.h>
   54 #endif
   55 
   56 #include <netinet/in.h>
   57 #include <netinet/if_ether.h>
   58 
   59 #include <net80211/ieee80211_var.h>
   60 #include <net80211/ieee80211_priv.h>
   61 
   62 #ifdef IEEE80211_DEBUG
   63 int     ieee80211_debug = 0;
   64 #endif
   65 
   66 int ieee80211_cache_size = IEEE80211_CACHE_SIZE;
   67 
   68 void ieee80211_setbasicrates(struct ieee80211com *);
   69 int ieee80211_findrate(struct ieee80211com *, enum ieee80211_phymode, int);
   70 void ieee80211_configure_ampdu_tx(struct ieee80211com *, int);
   71 
   72 void
   73 ieee80211_begin_bgscan(struct ifnet *ifp)
   74 {
   75         struct ieee80211com *ic = (void *)ifp;
   76 
   77         if ((ic->ic_flags & IEEE80211_F_BGSCAN) ||
   78             ic->ic_state != IEEE80211_S_RUN || ic->ic_mgt_timer != 0)
   79                 return;
   80 
   81         if ((ic->ic_flags & IEEE80211_F_RSNON) && !ic->ic_bss->ni_port_valid)
   82                 return;
   83 
   84         if (ic->ic_bgscan_start != NULL && ic->ic_bgscan_start(ic) == 0) {
   85                 /*
   86                  * Free the nodes table to ensure we get an up-to-date view
   87                  * of APs around us. In particular, we need to kick out the
   88                  * AP we are associated to. Otherwise, our current AP might
   89                  * stay cached if it is turned off while we are scanning, and
   90                  * we could end up picking a now non-existent AP over and over.
   91                  */
   92                 ieee80211_free_allnodes(ic, 0 /* keep ic->ic_bss */);
   93 
   94                 ic->ic_flags |= IEEE80211_F_BGSCAN;
   95                 if (ifp->if_flags & IFF_DEBUG)
   96                         printf("%s: begin background scan\n", ifp->if_xname);
   97 
   98                 /* Driver calls ieee80211_end_scan() when done. */
   99         }
  100 }
  101 
  102 void
  103 ieee80211_bgscan_timeout(void *arg)
  104 {
  105         struct ifnet *ifp = arg;
  106 
  107         ieee80211_begin_bgscan(ifp);
  108 }
  109 
  110 void
  111 ieee80211_channel_init(struct ifnet *ifp)
  112 {
  113         struct ieee80211com *ic = (void *)ifp;
  114         struct ieee80211_channel *c;
  115         int i;
  116 
  117         /*
  118          * Fill in 802.11 available channel set, mark
  119          * all available channels as active, and pick
  120          * a default channel if not already specified.
  121          */
  122         memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail));
  123         ic->ic_modecaps |= 1<<IEEE80211_MODE_AUTO;
  124         for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
  125                 c = &ic->ic_channels[i];
  126                 if (c->ic_flags) {
  127                         /*
  128                          * Verify driver passed us valid data.
  129                          */
  130                         if (i != ieee80211_chan2ieee(ic, c)) {
  131                                 printf("%s: bad channel ignored; "
  132                                         "freq %u flags %x number %u\n",
  133                                         ifp->if_xname, c->ic_freq, c->ic_flags,
  134                                         i);
  135                                 c->ic_flags = 0;        /* NB: remove */
  136                                 continue;
  137                         }
  138                         setbit(ic->ic_chan_avail, i);
  139                         /*
  140                          * Identify mode capabilities.
  141                          */
  142                         if (IEEE80211_IS_CHAN_A(c))
  143                                 ic->ic_modecaps |= 1<<IEEE80211_MODE_11A;
  144                         if (IEEE80211_IS_CHAN_B(c))
  145                                 ic->ic_modecaps |= 1<<IEEE80211_MODE_11B;
  146                         if (IEEE80211_IS_CHAN_PUREG(c))
  147                                 ic->ic_modecaps |= 1<<IEEE80211_MODE_11G;
  148                         if (IEEE80211_IS_CHAN_N(c))
  149                                 ic->ic_modecaps |= 1<<IEEE80211_MODE_11N;
  150                         if (IEEE80211_IS_CHAN_AC(c))
  151                                 ic->ic_modecaps |= 1<<IEEE80211_MODE_11AC;
  152                 }
  153         }
  154         /* validate ic->ic_curmode */
  155         if ((ic->ic_modecaps & (1<<ic->ic_curmode)) == 0)
  156                 ic->ic_curmode = IEEE80211_MODE_AUTO;
  157         ic->ic_des_chan = IEEE80211_CHAN_ANYC;  /* any channel is ok */
  158 }
  159 
  160 void
  161 ieee80211_ifattach(struct ifnet *ifp)
  162 {
  163         struct ieee80211com *ic = (void *)ifp;
  164 
  165         memcpy(((struct arpcom *)ifp)->ac_enaddr, ic->ic_myaddr,
  166                 ETHER_ADDR_LEN);
  167         ether_ifattach(ifp);
  168 
  169         ifp->if_output = ieee80211_output;
  170 
  171 #if NBPFILTER > 0
  172         bpfattach(&ic->ic_rawbpf, ifp, DLT_IEEE802_11,
  173             sizeof(struct ieee80211_frame_addr4));
  174 #endif
  175         ieee80211_crypto_attach(ifp);
  176 
  177         ieee80211_channel_init(ifp);
  178 
  179         /* IEEE 802.11 defines a MTU >= 2290 */
  180         ifp->if_capabilities |= IFCAP_VLAN_MTU;
  181 
  182         ieee80211_setbasicrates(ic);
  183         (void)ieee80211_setmode(ic, ic->ic_curmode);
  184 
  185         if (ic->ic_lintval == 0)
  186                 ic->ic_lintval = 100;           /* default sleep */
  187         ic->ic_bmissthres = IEEE80211_BEACON_MISS_THRES;
  188         ic->ic_dtim_period = 1; /* all TIMs are DTIMs */
  189 
  190         ieee80211_node_attach(ifp);
  191         ieee80211_proto_attach(ifp);
  192 
  193         if_addgroup(ifp, "wlan");
  194         ifp->if_priority = IF_WIRELESS_DEFAULT_PRIORITY;
  195 
  196         task_set(&ic->ic_rtm_80211info_task, ieee80211_rtm_80211info_task, ic);
  197         ieee80211_set_link_state(ic, LINK_STATE_DOWN);
  198 
  199         timeout_set(&ic->ic_bgscan_timeout, ieee80211_bgscan_timeout, ifp);
  200 }
  201 
  202 void
  203 ieee80211_ifdetach(struct ifnet *ifp)
  204 {
  205         struct ieee80211com *ic = (void *)ifp;
  206 
  207         task_del(systq, &ic->ic_rtm_80211info_task);
  208         timeout_del(&ic->ic_bgscan_timeout);
  209 
  210         /*
  211          * Undo pseudo-driver changes. Pseudo-driver detach hooks could
  212          * call back into the driver, e.g. via ioctl. So deactivate the
  213          * interface before freeing net80211-specific data structures.
  214          */
  215         if_deactivate(ifp);
  216 
  217         ieee80211_proto_detach(ifp);
  218         ieee80211_crypto_detach(ifp);
  219         ieee80211_node_detach(ifp);
  220         ifmedia_delete_instance(&ic->ic_media, IFM_INST_ANY);
  221         ether_ifdetach(ifp);
  222 }
  223 
  224 /*
  225  * Convert MHz frequency to IEEE channel number.
  226  */
  227 u_int
  228 ieee80211_mhz2ieee(u_int freq, u_int flags)
  229 {
  230         if (flags & IEEE80211_CHAN_2GHZ) {      /* 2GHz band */
  231                 if (freq == 2484)
  232                         return 14;
  233                 if (freq < 2484)
  234                         return (freq - 2407) / 5;
  235                 else
  236                         return 15 + ((freq - 2512) / 20);
  237         } else if (flags & IEEE80211_CHAN_5GHZ) {       /* 5GHz band */
  238                 return (freq - 5000) / 5;
  239         } else {                                /* either, guess */
  240                 if (freq == 2484)
  241                         return 14;
  242                 if (freq < 2484)
  243                         return (freq - 2407) / 5;
  244                 if (freq < 5000)
  245                         return 15 + ((freq - 2512) / 20);
  246                 return (freq - 5000) / 5;
  247         }
  248 }
  249 
  250 /*
  251  * Convert channel to IEEE channel number.
  252  */
  253 u_int
  254 ieee80211_chan2ieee(struct ieee80211com *ic, const struct ieee80211_channel *c)
  255 {
  256         struct ifnet *ifp = &ic->ic_if;
  257         if (ic->ic_channels <= c && c <= &ic->ic_channels[IEEE80211_CHAN_MAX])
  258                 return c - ic->ic_channels;
  259         else if (c == IEEE80211_CHAN_ANYC)
  260                 return IEEE80211_CHAN_ANY;
  261 
  262         panic("%s: bogus channel pointer", ifp->if_xname);
  263 }
  264 
  265 /*
  266  * Convert IEEE channel number to MHz frequency.
  267  */
  268 u_int
  269 ieee80211_ieee2mhz(u_int chan, u_int flags)
  270 {
  271         if (flags & IEEE80211_CHAN_2GHZ) {      /* 2GHz band */
  272                 if (chan == 14)
  273                         return 2484;
  274                 if (chan < 14)
  275                         return 2407 + chan*5;
  276                 else
  277                         return 2512 + ((chan-15)*20);
  278         } else if (flags & IEEE80211_CHAN_5GHZ) {/* 5GHz band */
  279                 return 5000 + (chan*5);
  280         } else {                                /* either, guess */
  281                 if (chan == 14)
  282                         return 2484;
  283                 if (chan < 14)                  /* 0-13 */
  284                         return 2407 + chan*5;
  285                 if (chan < 27)                  /* 15-26 */
  286                         return 2512 + ((chan-15)*20);
  287                 return 5000 + (chan*5);
  288         }
  289 }
  290 
  291 void
  292 ieee80211_configure_ampdu_tx(struct ieee80211com *ic, int enable)
  293 {
  294         if ((ic->ic_caps & IEEE80211_C_TX_AMPDU) == 0)
  295                 return;
  296 
  297         /* Sending AMPDUs requires QoS support. */
  298         if ((ic->ic_caps & IEEE80211_C_QOS) == 0)
  299                 return;
  300 
  301         if (enable)
  302                 ic->ic_flags |= IEEE80211_F_QOS;
  303         else
  304                 ic->ic_flags &= ~IEEE80211_F_QOS;
  305 }
  306 
  307 /*
  308  * Setup the media data structures according to the channel and
  309  * rate tables.  This must be called by the driver after
  310  * ieee80211_attach and before most anything else.
  311  */
  312 void
  313 ieee80211_media_init(struct ifnet *ifp,
  314         ifm_change_cb_t media_change, ifm_stat_cb_t media_stat)
  315 {
  316 #define ADD(_ic, _s, _o) \
  317         ifmedia_add(&(_ic)->ic_media, \
  318                 IFM_MAKEWORD(IFM_IEEE80211, (_s), (_o), 0), 0, NULL)
  319         struct ieee80211com *ic = (void *)ifp;
  320         struct ifmediareq imr;
  321         int i, j, mode, rate, maxrate, r;
  322         uint64_t mword, mopt;
  323         const struct ieee80211_rateset *rs;
  324         struct ieee80211_rateset allrates;
  325 
  326         /*
  327          * Do late attach work that must wait for any subclass
  328          * (i.e. driver) work such as overriding methods.
  329          */
  330         ieee80211_node_lateattach(ifp);
  331 
  332         /*
  333          * Fill in media characteristics.
  334          */
  335         ifmedia_init(&ic->ic_media, 0, media_change, media_stat);
  336         maxrate = 0;
  337         memset(&allrates, 0, sizeof(allrates));
  338         for (mode = IEEE80211_MODE_AUTO; mode <= IEEE80211_MODE_11G; mode++) {
  339                 static const uint64_t mopts[] = {
  340                         IFM_AUTO,
  341                         IFM_IEEE80211_11A,
  342                         IFM_IEEE80211_11B,
  343                         IFM_IEEE80211_11G,
  344                 };
  345                 if ((ic->ic_modecaps & (1<<mode)) == 0)
  346                         continue;
  347                 mopt = mopts[mode];
  348                 ADD(ic, IFM_AUTO, mopt);        /* e.g. 11a auto */
  349 #ifndef IEEE80211_STA_ONLY
  350                 if (ic->ic_caps & IEEE80211_C_IBSS)
  351                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_IBSS);
  352                 if (ic->ic_caps & IEEE80211_C_HOSTAP)
  353                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_HOSTAP);
  354                 if (ic->ic_caps & IEEE80211_C_AHDEMO)
  355                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_ADHOC);
  356 #endif
  357                 if (ic->ic_caps & IEEE80211_C_MONITOR)
  358                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_MONITOR);
  359                 if (mode == IEEE80211_MODE_AUTO)
  360                         continue;
  361                 rs = &ic->ic_sup_rates[mode];
  362                 for (i = 0; i < rs->rs_nrates; i++) {
  363                         rate = rs->rs_rates[i];
  364                         mword = ieee80211_rate2media(ic, rate, mode);
  365                         if (mword == 0)
  366                                 continue;
  367                         ADD(ic, mword, mopt);
  368 #ifndef IEEE80211_STA_ONLY
  369                         if (ic->ic_caps & IEEE80211_C_IBSS)
  370                                 ADD(ic, mword, mopt | IFM_IEEE80211_IBSS);
  371                         if (ic->ic_caps & IEEE80211_C_HOSTAP)
  372                                 ADD(ic, mword, mopt | IFM_IEEE80211_HOSTAP);
  373                         if (ic->ic_caps & IEEE80211_C_AHDEMO)
  374                                 ADD(ic, mword, mopt | IFM_IEEE80211_ADHOC);
  375 #endif
  376                         if (ic->ic_caps & IEEE80211_C_MONITOR)
  377                                 ADD(ic, mword, mopt | IFM_IEEE80211_MONITOR);
  378                         /*
  379                          * Add rate to the collection of all rates.
  380                          */
  381                         r = rate & IEEE80211_RATE_VAL;
  382                         for (j = 0; j < allrates.rs_nrates; j++)
  383                                 if (allrates.rs_rates[j] == r)
  384                                         break;
  385                         if (j == allrates.rs_nrates) {
  386                                 /* unique, add to the set */
  387                                 allrates.rs_rates[j] = r;
  388                                 allrates.rs_nrates++;
  389                         }
  390                         rate = (rate & IEEE80211_RATE_VAL) / 2;
  391                         if (rate > maxrate)
  392                                 maxrate = rate;
  393                 }
  394         }
  395         for (i = 0; i < allrates.rs_nrates; i++) {
  396                 mword = ieee80211_rate2media(ic, allrates.rs_rates[i],
  397                                 IEEE80211_MODE_AUTO);
  398                 if (mword == 0)
  399                         continue;
  400                 mword = IFM_SUBTYPE(mword);     /* remove media options */
  401                 ADD(ic, mword, 0);
  402 #ifndef IEEE80211_STA_ONLY
  403                 if (ic->ic_caps & IEEE80211_C_IBSS)
  404                         ADD(ic, mword, IFM_IEEE80211_IBSS);
  405                 if (ic->ic_caps & IEEE80211_C_HOSTAP)
  406                         ADD(ic, mword, IFM_IEEE80211_HOSTAP);
  407                 if (ic->ic_caps & IEEE80211_C_AHDEMO)
  408                         ADD(ic, mword, IFM_IEEE80211_ADHOC);
  409 #endif
  410                 if (ic->ic_caps & IEEE80211_C_MONITOR)
  411                         ADD(ic, mword, IFM_IEEE80211_MONITOR);
  412         }
  413 
  414         if (ic->ic_modecaps & (1 << IEEE80211_MODE_11N)) {
  415                 mopt = IFM_IEEE80211_11N;
  416                 ADD(ic, IFM_AUTO, mopt);
  417 #ifndef IEEE80211_STA_ONLY
  418                 if (ic->ic_caps & IEEE80211_C_IBSS)
  419                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_IBSS);
  420                 if (ic->ic_caps & IEEE80211_C_HOSTAP)
  421                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_HOSTAP);
  422 #endif
  423                 if (ic->ic_caps & IEEE80211_C_MONITOR)
  424                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_MONITOR);
  425                 for (i = 0; i < IEEE80211_HT_NUM_MCS; i++) {
  426                         if (!isset(ic->ic_sup_mcs, i))
  427                                 continue;
  428                         ADD(ic, IFM_IEEE80211_HT_MCS0 + i, mopt);
  429 #ifndef IEEE80211_STA_ONLY
  430                         if (ic->ic_caps & IEEE80211_C_IBSS)
  431                                 ADD(ic, IFM_IEEE80211_HT_MCS0 + i,
  432                                      mopt | IFM_IEEE80211_IBSS);
  433                         if (ic->ic_caps & IEEE80211_C_HOSTAP)
  434                                 ADD(ic, IFM_IEEE80211_HT_MCS0 + i,
  435                                     mopt | IFM_IEEE80211_HOSTAP);
  436 #endif
  437                         if (ic->ic_caps & IEEE80211_C_MONITOR)
  438                                 ADD(ic, IFM_IEEE80211_HT_MCS0 + i,
  439                                     mopt | IFM_IEEE80211_MONITOR);
  440                 }
  441                 ic->ic_flags |= IEEE80211_F_HTON; /* enable 11n by default */
  442                 ieee80211_configure_ampdu_tx(ic, 1);
  443         }
  444 
  445         if (ic->ic_modecaps & (1 << IEEE80211_MODE_11AC)) {
  446                 mopt = IFM_IEEE80211_11AC;
  447                 ADD(ic, IFM_AUTO, mopt);
  448 #ifndef IEEE80211_STA_ONLY
  449                 if (ic->ic_caps & IEEE80211_C_IBSS)
  450                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_IBSS);
  451                 if (ic->ic_caps & IEEE80211_C_HOSTAP)
  452                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_HOSTAP);
  453 #endif
  454                 if (ic->ic_caps & IEEE80211_C_MONITOR)
  455                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_MONITOR);
  456                 for (i = 0; i < IEEE80211_VHT_NUM_MCS; i++) {
  457 #if 0
  458                         /* TODO: Obtain VHT MCS information from VHT CAP IE. */
  459                         if (!vht_mcs_supported)
  460                                 continue;
  461 #endif
  462                         ADD(ic, IFM_IEEE80211_VHT_MCS0 + i, mopt);
  463 #ifndef IEEE80211_STA_ONLY
  464                         if (ic->ic_caps & IEEE80211_C_IBSS)
  465                                 ADD(ic, IFM_IEEE80211_VHT_MCS0 + i,
  466                                      mopt | IFM_IEEE80211_IBSS);
  467                         if (ic->ic_caps & IEEE80211_C_HOSTAP)
  468                                 ADD(ic, IFM_IEEE80211_VHT_MCS0 + i,
  469                                     mopt | IFM_IEEE80211_HOSTAP);
  470 #endif
  471                         if (ic->ic_caps & IEEE80211_C_MONITOR)
  472                                 ADD(ic, IFM_IEEE80211_VHT_MCS0 + i,
  473                                     mopt | IFM_IEEE80211_MONITOR);
  474                 }
  475                 ic->ic_flags |= IEEE80211_F_VHTON; /* enable 11ac by default */
  476                 ic->ic_flags |= IEEE80211_F_HTON; /* 11ac implies 11n */
  477                 if (ic->ic_caps & IEEE80211_C_QOS)
  478                         ic->ic_flags |= IEEE80211_F_QOS;
  479         }
  480 
  481         ieee80211_media_status(ifp, &imr);
  482         ifmedia_set(&ic->ic_media, imr.ifm_active);
  483 
  484         if (maxrate)
  485                 ifp->if_baudrate = IF_Mbps(maxrate);
  486 
  487 #undef ADD
  488 }
  489 
  490 int
  491 ieee80211_findrate(struct ieee80211com *ic, enum ieee80211_phymode mode,
  492     int rate)
  493 {
  494 #define IEEERATE(_ic,_m,_i) \
  495         ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL)
  496         int i, nrates = ic->ic_sup_rates[mode].rs_nrates;
  497         for (i = 0; i < nrates; i++)
  498                 if (IEEERATE(ic, mode, i) == rate)
  499                         return i;
  500         return -1;
  501 #undef IEEERATE
  502 }
  503 
  504 /*
  505  * Handle a media change request.
  506  */
  507 int
  508 ieee80211_media_change(struct ifnet *ifp)
  509 {
  510         struct ieee80211com *ic = (void *)ifp;
  511         struct ifmedia_entry *ime;
  512         enum ieee80211_opmode newopmode;
  513         enum ieee80211_phymode newphymode;
  514         int i, j, newrate, error = 0;
  515 
  516         ime = ic->ic_media.ifm_cur;
  517         /*
  518          * First, identify the phy mode.
  519          */
  520         switch (IFM_MODE(ime->ifm_media)) {
  521         case IFM_IEEE80211_11A:
  522                 newphymode = IEEE80211_MODE_11A;
  523                 break;
  524         case IFM_IEEE80211_11B:
  525                 newphymode = IEEE80211_MODE_11B;
  526                 break;
  527         case IFM_IEEE80211_11G:
  528                 newphymode = IEEE80211_MODE_11G;
  529                 break;
  530         case IFM_IEEE80211_11N:
  531                 newphymode = IEEE80211_MODE_11N;
  532                 break;
  533         case IFM_IEEE80211_11AC:
  534                 newphymode = IEEE80211_MODE_11AC;
  535                 break;
  536         case IFM_AUTO:
  537                 newphymode = IEEE80211_MODE_AUTO;
  538                 break;
  539         default:
  540                 return EINVAL;
  541         }
  542 
  543         /*
  544          * Validate requested mode is available.
  545          */
  546         if ((ic->ic_modecaps & (1<<newphymode)) == 0)
  547                 return EINVAL;
  548 
  549         /*
  550          * Next, the fixed/variable rate.
  551          */
  552         i = -1;
  553         if (IFM_SUBTYPE(ime->ifm_media) >= IFM_IEEE80211_VHT_MCS0 &&
  554             IFM_SUBTYPE(ime->ifm_media) <= IFM_IEEE80211_VHT_MCS9) {
  555                 if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11AC)) == 0)
  556                         return EINVAL;
  557                 if (newphymode != IEEE80211_MODE_AUTO &&
  558                     newphymode != IEEE80211_MODE_11AC)
  559                         return EINVAL;
  560                 i = ieee80211_media2mcs(ime->ifm_media);
  561                 /* TODO: Obtain VHT MCS information from VHT CAP IE. */
  562                 if (i == -1 /* || !vht_mcs_supported */)
  563                         return EINVAL;
  564         } else if (IFM_SUBTYPE(ime->ifm_media) >= IFM_IEEE80211_HT_MCS0 &&
  565             IFM_SUBTYPE(ime->ifm_media) <= IFM_IEEE80211_HT_MCS76) {
  566                 if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11N)) == 0)
  567                         return EINVAL;
  568                 if (newphymode != IEEE80211_MODE_AUTO &&
  569                     newphymode != IEEE80211_MODE_11N)
  570                         return EINVAL;
  571                 i = ieee80211_media2mcs(ime->ifm_media);
  572                 if (i == -1 || isclr(ic->ic_sup_mcs, i))
  573                         return EINVAL;
  574         } else if (IFM_SUBTYPE(ime->ifm_media) != IFM_AUTO) {
  575                 /*
  576                  * Convert media subtype to rate.
  577                  */
  578                 newrate = ieee80211_media2rate(ime->ifm_media);
  579                 if (newrate == 0)
  580                         return EINVAL;
  581                 /*
  582                  * Check the rate table for the specified/current phy.
  583                  */
  584                 if (newphymode == IEEE80211_MODE_AUTO) {
  585                         /*
  586                          * In autoselect mode search for the rate.
  587                          */
  588                         for (j = IEEE80211_MODE_11A;
  589                              j < IEEE80211_MODE_MAX; j++) {
  590                                 if ((ic->ic_modecaps & (1<<j)) == 0)
  591                                         continue;
  592                                 i = ieee80211_findrate(ic, j, newrate);
  593                                 if (i != -1) {
  594                                         /* lock mode too */
  595                                         newphymode = j;
  596                                         break;
  597                                 }
  598                         }
  599                 } else {
  600                         i = ieee80211_findrate(ic, newphymode, newrate);
  601                 }
  602                 if (i == -1)                    /* mode/rate mismatch */
  603                         return EINVAL;
  604         }
  605         /* NB: defer rate setting to later */
  606 
  607         /*
  608          * Deduce new operating mode but don't install it just yet.
  609          */
  610 #ifndef IEEE80211_STA_ONLY
  611         if (ime->ifm_media & IFM_IEEE80211_ADHOC)
  612                 newopmode = IEEE80211_M_AHDEMO;
  613         else if (ime->ifm_media & IFM_IEEE80211_HOSTAP)
  614                 newopmode = IEEE80211_M_HOSTAP;
  615         else if (ime->ifm_media & IFM_IEEE80211_IBSS)
  616                 newopmode = IEEE80211_M_IBSS;
  617         else
  618 #endif
  619         if (ime->ifm_media & IFM_IEEE80211_MONITOR)
  620                 newopmode = IEEE80211_M_MONITOR;
  621         else
  622                 newopmode = IEEE80211_M_STA;
  623 
  624 #ifndef IEEE80211_STA_ONLY
  625         /*
  626          * Autoselect doesn't make sense when operating as an AP.
  627          * If no phy mode has been selected, pick one and lock it
  628          * down so rate tables can be used in forming beacon frames
  629          * and the like.
  630          */
  631         if (newopmode == IEEE80211_M_HOSTAP &&
  632             newphymode == IEEE80211_MODE_AUTO) {
  633                 if (ic->ic_modecaps & (1 << IEEE80211_MODE_11AC))
  634                         newphymode = IEEE80211_MODE_11AC;
  635                 else if (ic->ic_modecaps & (1 << IEEE80211_MODE_11N))
  636                         newphymode = IEEE80211_MODE_11N;
  637                 else if (ic->ic_modecaps & (1 << IEEE80211_MODE_11A))
  638                         newphymode = IEEE80211_MODE_11A;
  639                 else if (ic->ic_modecaps & (1 << IEEE80211_MODE_11G))
  640                         newphymode = IEEE80211_MODE_11G;
  641                 else
  642                         newphymode = IEEE80211_MODE_11B;
  643         }
  644 #endif
  645 
  646         /*
  647          * Handle phy mode change.
  648          */
  649         if (ic->ic_curmode != newphymode) {             /* change phy mode */
  650                 error = ieee80211_setmode(ic, newphymode);
  651                 if (error != 0)
  652                         return error;
  653                 error = ENETRESET;
  654         }
  655 
  656         /*
  657          * Committed to changes, install the MCS/rate setting.
  658          */
  659         ic->ic_flags &= ~(IEEE80211_F_HTON | IEEE80211_F_VHTON);
  660         ieee80211_configure_ampdu_tx(ic, 0);
  661         if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11AC)) &&
  662             (newphymode == IEEE80211_MODE_AUTO ||
  663             newphymode == IEEE80211_MODE_11AC)) {
  664                 ic->ic_flags |= IEEE80211_F_VHTON;
  665                 ic->ic_flags |= IEEE80211_F_HTON;
  666                 ieee80211_configure_ampdu_tx(ic, 1);
  667         } else if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11N)) &&
  668             (newphymode == IEEE80211_MODE_AUTO ||
  669             newphymode == IEEE80211_MODE_11N)) {
  670                 ic->ic_flags |= IEEE80211_F_HTON;
  671                 ieee80211_configure_ampdu_tx(ic, 1);
  672         }
  673         if ((ic->ic_flags & (IEEE80211_F_HTON | IEEE80211_F_VHTON)) == 0) {
  674                 ic->ic_fixed_mcs = -1;
  675                 if (ic->ic_fixed_rate != i) {
  676                         ic->ic_fixed_rate = i;          /* set fixed tx rate */
  677                         error = ENETRESET;
  678                 }
  679         } else {
  680                 ic->ic_fixed_rate = -1;
  681                 if (ic->ic_fixed_mcs != i) {
  682                         ic->ic_fixed_mcs = i;           /* set fixed mcs */
  683                         error = ENETRESET;
  684                 }
  685         }
  686 
  687         /*
  688          * Handle operating mode change.
  689          */
  690         if (ic->ic_opmode != newopmode) {
  691                 ic->ic_opmode = newopmode;
  692 #ifndef IEEE80211_STA_ONLY
  693                 switch (newopmode) {
  694                 case IEEE80211_M_AHDEMO:
  695                 case IEEE80211_M_HOSTAP:
  696                 case IEEE80211_M_STA:
  697                 case IEEE80211_M_MONITOR:
  698                         ic->ic_flags &= ~IEEE80211_F_IBSSON;
  699                         break;
  700                 case IEEE80211_M_IBSS:
  701                         ic->ic_flags |= IEEE80211_F_IBSSON;
  702                         break;
  703                 }
  704 #endif
  705                 /*
  706                  * Yech, slot time may change depending on the
  707                  * operating mode so reset it to be sure everything
  708                  * is setup appropriately.
  709                  */
  710                 ieee80211_reset_erp(ic);
  711                 error = ENETRESET;
  712         }
  713 #ifdef notdef
  714         if (error == 0)
  715                 ifp->if_baudrate = ifmedia_baudrate(ime->ifm_media);
  716 #endif
  717         return error;
  718 }
  719 
  720 void
  721 ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
  722 {
  723         struct ieee80211com *ic = (void *)ifp;
  724         const struct ieee80211_node *ni = NULL;
  725 
  726         imr->ifm_status = IFM_AVALID;
  727         imr->ifm_active = IFM_IEEE80211;
  728         if (ic->ic_state == IEEE80211_S_RUN &&
  729             (ic->ic_opmode != IEEE80211_M_STA ||
  730              !(ic->ic_flags & IEEE80211_F_RSNON) ||
  731              ic->ic_bss->ni_port_valid))
  732                 imr->ifm_status |= IFM_ACTIVE;
  733         imr->ifm_active |= IFM_AUTO;
  734         switch (ic->ic_opmode) {
  735         case IEEE80211_M_STA:
  736                 ni = ic->ic_bss;
  737                 if (ic->ic_curmode == IEEE80211_MODE_11N ||
  738                     ic->ic_curmode == IEEE80211_MODE_11AC)
  739                         imr->ifm_active |= ieee80211_mcs2media(ic,
  740                                 ni->ni_txmcs, ic->ic_curmode);
  741                 else if (ni->ni_flags & IEEE80211_NODE_VHT) /* in MODE_AUTO */
  742                         imr->ifm_active |= ieee80211_mcs2media(ic,
  743                                 ni->ni_txmcs, IEEE80211_MODE_11AC);
  744                 else if (ni->ni_flags & IEEE80211_NODE_HT) /* in MODE_AUTO */
  745                         imr->ifm_active |= ieee80211_mcs2media(ic,
  746                                 ni->ni_txmcs, IEEE80211_MODE_11N);
  747                 else
  748                         /* calculate rate subtype */
  749                         imr->ifm_active |= ieee80211_rate2media(ic,
  750                                 ni->ni_rates.rs_rates[ni->ni_txrate],
  751                                 ic->ic_curmode);
  752                 break;
  753 #ifndef IEEE80211_STA_ONLY
  754         case IEEE80211_M_IBSS:
  755                 imr->ifm_active |= IFM_IEEE80211_IBSS;
  756                 break;
  757         case IEEE80211_M_AHDEMO:
  758                 imr->ifm_active |= IFM_IEEE80211_ADHOC;
  759                 break;
  760         case IEEE80211_M_HOSTAP:
  761                 imr->ifm_active |= IFM_IEEE80211_HOSTAP;
  762                 break;
  763 #endif
  764         case IEEE80211_M_MONITOR:
  765                 imr->ifm_active |= IFM_IEEE80211_MONITOR;
  766                 break;
  767         default:
  768                 break;
  769         }
  770         switch (ic->ic_curmode) {
  771         case IEEE80211_MODE_11A:
  772                 imr->ifm_active |= IFM_IEEE80211_11A;
  773                 break;
  774         case IEEE80211_MODE_11B:
  775                 imr->ifm_active |= IFM_IEEE80211_11B;
  776                 break;
  777         case IEEE80211_MODE_11G:
  778                 imr->ifm_active |= IFM_IEEE80211_11G;
  779                 break;
  780         case IEEE80211_MODE_11N:
  781                 imr->ifm_active |= IFM_IEEE80211_11N;
  782                 break;
  783         case IEEE80211_MODE_11AC:
  784                 imr->ifm_active |= IFM_IEEE80211_11AC;
  785                 break;
  786         }
  787 }
  788 
  789 void
  790 ieee80211_watchdog(struct ifnet *ifp)
  791 {
  792         struct ieee80211com *ic = (void *)ifp;
  793 
  794         if (ic->ic_mgt_timer && --ic->ic_mgt_timer == 0) {
  795                 if (ic->ic_opmode == IEEE80211_M_STA &&
  796                     (ic->ic_state == IEEE80211_S_AUTH ||
  797                     ic->ic_state == IEEE80211_S_ASSOC)) {
  798                         struct ieee80211_node *ni;
  799                         if (ifp->if_flags & IFF_DEBUG)
  800                                 printf("%s: %s timed out for %s\n",
  801                                     ifp->if_xname,
  802                                     ic->ic_state == IEEE80211_S_ASSOC ?
  803                                     "association" : "authentication",
  804                                     ether_sprintf(ic->ic_bss->ni_macaddr));
  805                         ni = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr);
  806                         if (ni)
  807                                 ni->ni_fails++;
  808                         if (ISSET(ic->ic_flags, IEEE80211_F_AUTO_JOIN))
  809                                 ieee80211_deselect_ess(ic);
  810                 }
  811                 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
  812         }
  813 
  814         if (ic->ic_mgt_timer != 0)
  815                 ifp->if_timer = 1;
  816 }
  817 
  818 const struct ieee80211_rateset ieee80211_std_rateset_11a =
  819         { 8, { 12, 18, 24, 36, 48, 72, 96, 108 } };
  820 
  821 const struct ieee80211_rateset ieee80211_std_rateset_11b =
  822         { 4, { 2, 4, 11, 22 } };
  823 
  824 const struct ieee80211_rateset ieee80211_std_rateset_11g =
  825         { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
  826 
  827 const struct ieee80211_ht_rateset ieee80211_std_ratesets_11n[] = {
  828         /* MCS 0-7, 20MHz channel, no SGI */
  829         { 8, { 13, 26, 39, 52, 78, 104, 117, 130 },
  830             0x000000ff, 0, 7, 0, 0},
  831 
  832         /* MCS 0-7, 20MHz channel, SGI */
  833         { 8, { 14, 29, 43, 58, 87, 116, 130, 144 },
  834             0x000000ff, 0, 7, 0, 1 },
  835 
  836         /* MCS 8-15, 20MHz channel, no SGI */
  837         { 8, { 26, 52, 78, 104, 156, 208, 234, 260 },
  838             0x0000ff00, 8, 15, 0, 0 },
  839 
  840         /* MCS 8-15, 20MHz channel, SGI */
  841         { 8, { 29, 58, 87, 116, 173, 231, 261, 289 },
  842             0x0000ff00, 8, 15, 0, 1 },
  843 
  844         /* MCS 16-23, 20MHz channel, no SGI */
  845         { 8, { 39, 78, 117, 156, 234, 312, 351, 390 },
  846             0x00ff0000, 16, 23, 0, 0 },
  847 
  848         /* MCS 16-23, 20MHz channel, SGI */
  849         { 8, { 43, 87, 130, 173, 260, 347, 390, 433 },
  850             0x00ff0000, 16, 23, 0, 1 },
  851 
  852         /* MCS 24-31, 20MHz channel, no SGI */
  853         { 8, { 52, 104, 156, 208, 312, 416, 468, 520 },
  854             0xff000000, 24, 31, 0, 0 },
  855 
  856         /* MCS 24-31, 20MHz channel, SGI */
  857         { 8, { 58, 116, 173, 231, 347, 462, 520, 578 },
  858             0xff000000, 24, 31, 0, 1 },
  859 
  860         /* MCS 0-7, 40MHz channel, no SGI */
  861         { 8, { 27, 54, 81, 108, 162, 216, 243, 270 },
  862             0x000000ff, 0, 7, 1, 0 },
  863 
  864         /* MCS 0-7, 40MHz channel, SGI */
  865         { 8, { 30, 60, 90, 120, 180, 240, 270, 300 },
  866             0x000000ff, 0, 7, 1, 1 },
  867 
  868         /* MCS 8-15, 40MHz channel, no SGI */
  869         { 8, { 54, 108, 192, 216, 324, 432, 486, 540 },
  870             0x0000ff00, 8, 15, 1, 0 },
  871 
  872         /* MCS 8-15, 40MHz channel, SGI */
  873         { 8, { 60, 120, 180, 240, 360, 480, 540, 600 },
  874             0x0000ff00, 8, 15, 1, 1 },
  875 
  876         /* MCS 16-23, 40MHz channel, no SGI */
  877         { 8, { 81, 162, 243, 324, 486, 648, 729, 810 },
  878             0x00ff0000, 16, 23, 1, 0 },
  879 
  880         /* MCS 16-23, 40MHz channel, SGI */
  881         { 8, { 90, 180, 270, 360, 540, 720, 810, 900 },
  882             0x00ff0000, 16, 23, 1, 1 },
  883 
  884         /* MCS 24-31, 40MHz channel, no SGI */
  885         { 8, { 108, 216, 324, 432, 324, 864, 972, 1080 },
  886             0xff000000, 24, 31, 1, 0 },
  887 
  888         /* MCS 24-31, 40MHz channel, SGI */
  889         { 8, { 120, 240, 360, 480, 520, 960, 1080, 1200 },
  890             0xff000000, 24, 31, 1, 1 },
  891 };
  892 
  893 const struct ieee80211_vht_rateset ieee80211_std_ratesets_11ac[] = {
  894         /* MCS 0-8 (MCS 9 N/A), 1 SS, 20MHz channel, no SGI */
  895         { 0, 9, { 13, 26, 39, 52, 78, 104, 117, 130, 156 },
  896             1, 0, 0, 0 },
  897 
  898         /* MCS 0-8 (MCS 9 N/A), 1 SS, 20MHz channel, SGI */
  899         { 1, 9, { 14, 29, 43, 58, 87, 116, 130, 144, 174 },
  900             1, 0, 0, 1 },
  901 
  902         /* MCS 0-8 (MCS 9 N/A), 2 SS, 20MHz channel, no SGI */
  903         { 2, 9, { 26, 52, 78, 104, 156, 208, 234, 260, 312 },
  904             2, 0, 0, 0 },
  905 
  906         /* MCS 0-8 (MCS 9 N/A), 2 SS, 20MHz channel, SGI */
  907         { 3, 9, { 29, 58, 87, 116, 173, 231, 261, 289, 347 },
  908             2, 0, 0, 1 },
  909 
  910         /* MCS 0-9, 1 SS, 40MHz channel, no SGI */
  911         { 4, 10, { 27, 54, 81, 108, 162, 216, 243, 270, 324, 360 },
  912             1, 1, 0, 0 },
  913 
  914         /* MCS 0-9, 1 SS, 40MHz channel, SGI */
  915         { 5, 10, { 30, 60, 90, 120, 180, 240, 270, 300, 360, 400 },
  916             1, 1, 0, 1 },
  917 
  918         /* MCS 0-9, 2 SS, 40MHz channel, no SGI */
  919         { 6, 10, { 54, 108, 162, 216, 324, 432, 486, 540, 648, 720 },
  920             2, 1, 0, 0 },
  921 
  922         /* MCS 0-9, 2 SS, 40MHz channel, SGI */
  923         { 7, 10, { 60, 120, 180, 240, 360, 480, 540, 600, 720, 800 },
  924             2, 1, 0, 1 },
  925 
  926         /* MCS 0-9, 1 SS, 80MHz channel, no SGI */
  927         { 8, 10, { 59, 117, 176, 234, 351, 468, 527, 585, 702, 780 },
  928             1, 0, 1, 0 },
  929 
  930         /* MCS 0-9, 1 SS, 80MHz channel, SGI */
  931         { 9, 10, { 65, 130, 195, 260, 390, 520, 585, 650, 780, 867 },
  932             1, 0, 1, 1 },
  933 
  934         /* MCS 0-9, 2 SS, 80MHz channel, no SGI */
  935         { 10, 10, { 117, 234, 351, 468, 702, 936, 1053, 1404, 1560 },
  936             2, 0, 1, 0 },
  937 
  938         /* MCS 0-9, 2 SS, 80MHz channel, SGI */
  939         { 11, 10, { 130, 260, 390, 520, 780, 1040, 1170, 1300, 1560, 1734 },
  940             2, 0, 1, 1 },
  941 };
  942 
  943 /*
  944  * Mark the basic rates for the 11g rate table based on the
  945  * operating mode.  For real 11g we mark all the 11b rates
  946  * and 6, 12, and 24 OFDM.  For 11b compatibility we mark only
  947  * 11b rates.  There's also a pseudo 11a-mode used to mark only
  948  * the basic OFDM rates.
  949  */
  950 void
  951 ieee80211_setbasicrates(struct ieee80211com *ic)
  952 {
  953         static const struct ieee80211_rateset basic[] = {
  954             { 0 },                              /* IEEE80211_MODE_AUTO */
  955             { 3, { 12, 24, 48 } },              /* IEEE80211_MODE_11A */
  956             { 2, { 2, 4 } },                    /* IEEE80211_MODE_11B */
  957             { 4, { 2, 4, 11, 22 } },            /* IEEE80211_MODE_11G */
  958             { 0 },                              /* IEEE80211_MODE_11N   */
  959             { 0 },                              /* IEEE80211_MODE_11AC  */
  960         };
  961         enum ieee80211_phymode mode;
  962         struct ieee80211_rateset *rs;
  963         int i, j;
  964 
  965         for (mode = 0; mode < IEEE80211_MODE_MAX; mode++) {
  966                 rs = &ic->ic_sup_rates[mode];
  967                 for (i = 0; i < rs->rs_nrates; i++) {
  968                         rs->rs_rates[i] &= IEEE80211_RATE_VAL;
  969                         for (j = 0; j < basic[mode].rs_nrates; j++) {
  970                                 if (basic[mode].rs_rates[j] ==
  971                                     rs->rs_rates[i]) {
  972                                         rs->rs_rates[i] |=
  973                                             IEEE80211_RATE_BASIC;
  974                                         break;
  975                                 }
  976                         }
  977                 }
  978         }
  979 }
  980 
  981 int
  982 ieee80211_min_basic_rate(struct ieee80211com *ic)
  983 {
  984         struct ieee80211_rateset *rs = &ic->ic_bss->ni_rates;
  985         int i, min, rval;
  986 
  987         min = -1;
  988 
  989         for (i = 0; i < rs->rs_nrates; i++) {
  990                 if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0)
  991                         continue;
  992                 rval = (rs->rs_rates[i] & IEEE80211_RATE_VAL);
  993                 if (min == -1)
  994                         min = rval;
  995                 else if (rval < min)
  996                         min = rval;
  997         }
  998 
  999         /* Default to 1 Mbit/s on 2GHz and 6 Mbit/s on 5GHz. */
 1000         if (min == -1)
 1001                 min = IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan) ? 2 : 12;
 1002 
 1003         return min;
 1004 }
 1005 
 1006 int
 1007 ieee80211_max_basic_rate(struct ieee80211com *ic)
 1008 {
 1009         struct ieee80211_rateset *rs = &ic->ic_bss->ni_rates;
 1010         int i, max, rval;
 1011 
 1012         /* Default to 1 Mbit/s on 2GHz and 6 Mbit/s on 5GHz. */
 1013         max = IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan) ? 2 : 12;
 1014 
 1015         for (i = 0; i < rs->rs_nrates; i++) {
 1016                 if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0)
 1017                         continue;
 1018                 rval = (rs->rs_rates[i] & IEEE80211_RATE_VAL);
 1019                 if (rval > max)
 1020                         max = rval;
 1021         }
 1022 
 1023         return max;
 1024 }
 1025 
 1026 /*
 1027  * Set the current phy mode and recalculate the active channel
 1028  * set based on the available channels for this mode.  Also
 1029  * select a new default/current channel if the current one is
 1030  * inappropriate for this mode.
 1031  */
 1032 int
 1033 ieee80211_setmode(struct ieee80211com *ic, enum ieee80211_phymode mode)
 1034 {
 1035         struct ifnet *ifp = &ic->ic_if;
 1036         static const u_int chanflags[] = {
 1037                 0,                      /* IEEE80211_MODE_AUTO */
 1038                 IEEE80211_CHAN_A,       /* IEEE80211_MODE_11A */
 1039                 IEEE80211_CHAN_B,       /* IEEE80211_MODE_11B */
 1040                 IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_11G */
 1041                 IEEE80211_CHAN_HT,      /* IEEE80211_MODE_11N */
 1042                 IEEE80211_CHAN_VHT,     /* IEEE80211_MODE_11AC */
 1043         };
 1044         const struct ieee80211_channel *c;
 1045         u_int modeflags;
 1046         int i;
 1047 
 1048         /* validate new mode */
 1049         if ((ic->ic_modecaps & (1<<mode)) == 0) {
 1050                 DPRINTF(("mode %u not supported (caps 0x%x)\n",
 1051                     mode, ic->ic_modecaps));
 1052                 return EINVAL;
 1053         }
 1054 
 1055         /*
 1056          * Verify at least one channel is present in the available
 1057          * channel list before committing to the new mode.
 1058          */
 1059         if (mode >= nitems(chanflags))
 1060                 panic("%s: unexpected mode %u", __func__, mode);
 1061         modeflags = chanflags[mode];
 1062         for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
 1063                 c = &ic->ic_channels[i];
 1064                 if (mode == IEEE80211_MODE_AUTO) {
 1065                         if (c->ic_flags != 0)
 1066                                 break;
 1067                 } else if ((c->ic_flags & modeflags) == modeflags)
 1068                         break;
 1069         }
 1070         if (i > IEEE80211_CHAN_MAX) {
 1071                 DPRINTF(("no channels found for mode %u\n", mode));
 1072                 return EINVAL;
 1073         }
 1074 
 1075         /*
 1076          * Calculate the active channel set.
 1077          */
 1078         memset(ic->ic_chan_active, 0, sizeof(ic->ic_chan_active));
 1079         for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
 1080                 c = &ic->ic_channels[i];
 1081                 if (mode == IEEE80211_MODE_AUTO) {
 1082                         if (c->ic_flags != 0)
 1083                                 setbit(ic->ic_chan_active, i);
 1084                 } else if ((c->ic_flags & modeflags) == modeflags)
 1085                         setbit(ic->ic_chan_active, i);
 1086         }
 1087         /*
 1088          * If no current/default channel is setup or the current
 1089          * channel is wrong for the mode then pick the first
 1090          * available channel from the active list.  This is likely
 1091          * not the right one.
 1092          */
 1093         if (ic->ic_ibss_chan == NULL || isclr(ic->ic_chan_active,
 1094             ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) {
 1095                 for (i = 0; i <= IEEE80211_CHAN_MAX; i++)
 1096                         if (isset(ic->ic_chan_active, i)) {
 1097                                 ic->ic_ibss_chan = &ic->ic_channels[i];
 1098                                 break;
 1099                         }
 1100                 if ((ic->ic_ibss_chan == NULL) || isclr(ic->ic_chan_active,
 1101                     ieee80211_chan2ieee(ic, ic->ic_ibss_chan)))
 1102                         panic("Bad IBSS channel %u",
 1103                             ieee80211_chan2ieee(ic, ic->ic_ibss_chan));
 1104         }
 1105 
 1106         /*
 1107          * Reset the scan state for the new mode. This avoids scanning
 1108          * of invalid channels, ie. 5GHz channels in 11b mode.
 1109          */
 1110         ieee80211_reset_scan(ifp);
 1111 
 1112         ic->ic_curmode = mode;
 1113         ieee80211_reset_erp(ic);        /* reset ERP state */
 1114 
 1115         return 0;
 1116 }
 1117 
 1118 enum ieee80211_phymode
 1119 ieee80211_next_mode(struct ifnet *ifp)
 1120 {
 1121         struct ieee80211com *ic = (void *)ifp;
 1122         uint16_t mode;
 1123 
 1124         /*
 1125          * Indicate a wrap-around if we're running in a fixed, user-specified
 1126          * phy mode.
 1127          */
 1128         if (IFM_MODE(ic->ic_media.ifm_cur->ifm_media) != IFM_AUTO)
 1129                 return (IEEE80211_MODE_AUTO);
 1130 
 1131         /*
 1132          * Always scan in AUTO mode if the driver scans all bands.
 1133          * The current mode might have changed during association
 1134          * so we must reset it here.
 1135          */
 1136         if (ic->ic_caps & IEEE80211_C_SCANALLBAND) {
 1137                 ieee80211_setmode(ic, IEEE80211_MODE_AUTO);
 1138                 return (ic->ic_curmode);
 1139         }
 1140 
 1141         /*
 1142          * Get the next supported mode; effectively, this alternates between
 1143          * the 11a (5GHz) and 11b/g (2GHz) modes. What matters is that each
 1144          * supported channel gets scanned.
 1145          */
 1146         for (mode = ic->ic_curmode + 1; mode <= IEEE80211_MODE_MAX; mode++) {
 1147                 /*
 1148                  * Skip over 11n mode. Its set of channels is the superset
 1149                  * of all channels supported by the other modes.
 1150                  */
 1151                 if (mode == IEEE80211_MODE_11N)
 1152                         continue;
 1153                 /*
 1154                  * Skip over 11ac mode. Its set of channels is the set
 1155                  * of all channels supported by 11a.
 1156                  */
 1157                 if (mode == IEEE80211_MODE_11AC)
 1158                         continue;
 1159 
 1160                 /* Start over if we have already tried all modes. */
 1161                 if (mode == IEEE80211_MODE_MAX) {
 1162                         mode = IEEE80211_MODE_AUTO;
 1163                         break;
 1164                 }
 1165 
 1166                 if (ic->ic_modecaps & (1 << mode))
 1167                         break;
 1168         }
 1169 
 1170         if (mode != ic->ic_curmode)
 1171                 ieee80211_setmode(ic, mode);
 1172 
 1173         return (ic->ic_curmode);
 1174 }
 1175 
 1176 /*
 1177  * Return the phy mode for with the specified channel so the
 1178  * caller can select a rate set.  This is problematic and the
 1179  * work here assumes how things work elsewhere in this code.
 1180  *
 1181  * Because the result of this function is ultimately used to select a
 1182  * rate from the rate set of the returned mode, it must return one of the
 1183  * legacy 11a/b/g modes; 11n and 11ac modes use MCS instead of rate sets.
 1184  */
 1185 enum ieee80211_phymode
 1186 ieee80211_chan2mode(struct ieee80211com *ic,
 1187     const struct ieee80211_channel *chan)
 1188 {
 1189         /*
 1190          * Are we fixed in 11a/b/g mode?
 1191          * NB: this assumes the channel would not be supplied to us
 1192          *     unless it was already compatible with the current mode.
 1193          */
 1194         if (ic->ic_curmode == IEEE80211_MODE_11A ||
 1195             ic->ic_curmode == IEEE80211_MODE_11B ||
 1196             ic->ic_curmode == IEEE80211_MODE_11G)
 1197                 return ic->ic_curmode;
 1198 
 1199         /* If no channel was provided, return the most suitable legacy mode. */
 1200         if (chan == IEEE80211_CHAN_ANYC) {
 1201                 switch (ic->ic_curmode) {
 1202                 case IEEE80211_MODE_AUTO:
 1203                 case IEEE80211_MODE_11N:
 1204                         if (ic->ic_modecaps & (1 << IEEE80211_MODE_11A))
 1205                                 return IEEE80211_MODE_11A;
 1206                         if (ic->ic_modecaps & (1 << IEEE80211_MODE_11G))
 1207                                 return IEEE80211_MODE_11G;
 1208                         return IEEE80211_MODE_11B;
 1209                 case IEEE80211_MODE_11AC:
 1210                         return IEEE80211_MODE_11A;
 1211                 default:
 1212                         return ic->ic_curmode;
 1213                 }
 1214         }
 1215 
 1216         /* Deduce a legacy mode based on the channel characteristics. */
 1217         if (IEEE80211_IS_CHAN_5GHZ(chan))
 1218                 return IEEE80211_MODE_11A;
 1219         else if (chan->ic_flags & (IEEE80211_CHAN_OFDM|IEEE80211_CHAN_DYN))
 1220                 return IEEE80211_MODE_11G;
 1221         else
 1222                 return IEEE80211_MODE_11B;
 1223 }
 1224 
 1225 /*
 1226  * Convert IEEE80211 MCS index to ifmedia subtype.
 1227  */
 1228 uint64_t
 1229 ieee80211_mcs2media(struct ieee80211com *ic, int mcs,
 1230     enum ieee80211_phymode mode)
 1231 {
 1232         switch (mode) {
 1233         case IEEE80211_MODE_11A:
 1234         case IEEE80211_MODE_11B:
 1235         case IEEE80211_MODE_11G:
 1236                 /* these modes use rates, not MCS */
 1237                 panic("%s: unexpected mode %d", __func__, mode);
 1238                 break;
 1239         case IEEE80211_MODE_11N:
 1240                 if (mcs >= 0 && mcs < IEEE80211_HT_NUM_MCS)
 1241                         return (IFM_IEEE80211_11N |
 1242                             (IFM_IEEE80211_HT_MCS0 + mcs));
 1243                 break;
 1244         case IEEE80211_MODE_11AC:
 1245                 if (mcs >= 0 && mcs < IEEE80211_VHT_NUM_MCS)
 1246                         return (IFM_IEEE80211_11AC |
 1247                             (IFM_IEEE80211_VHT_MCS0 + mcs));
 1248                 break;
 1249         case IEEE80211_MODE_AUTO:
 1250                 break;
 1251         }
 1252 
 1253         return IFM_AUTO;
 1254 }
 1255 
 1256 /*
 1257  * Convert ifmedia subtype to IEEE80211 MCS index.
 1258  */
 1259 int
 1260 ieee80211_media2mcs(uint64_t mword)
 1261 {
 1262         uint64_t subtype;
 1263 
 1264         subtype = IFM_SUBTYPE(mword);
 1265 
 1266         if (subtype == IFM_AUTO)
 1267                 return -1;
 1268         else if (subtype == IFM_MANUAL || subtype == IFM_NONE)
 1269                 return 0;
 1270 
 1271         if (subtype >= IFM_IEEE80211_HT_MCS0 &&
 1272             subtype <= IFM_IEEE80211_HT_MCS76)
 1273                 return (int)(subtype - IFM_IEEE80211_HT_MCS0);
 1274 
 1275         if (subtype >= IFM_IEEE80211_VHT_MCS0 &&
 1276             subtype <= IFM_IEEE80211_VHT_MCS9)
 1277                 return (int)(subtype - IFM_IEEE80211_VHT_MCS0);
 1278 
 1279         return -1;
 1280 }
 1281 
 1282 /*
 1283  * convert IEEE80211 rate value to ifmedia subtype.
 1284  * ieee80211 rate is in unit of 0.5Mbps.
 1285  */
 1286 uint64_t
 1287 ieee80211_rate2media(struct ieee80211com *ic, int rate,
 1288     enum ieee80211_phymode mode)
 1289 {
 1290         static const struct {
 1291                 uint64_t        m;      /* rate + mode */
 1292                 uint64_t        r;      /* if_media rate */
 1293         } rates[] = {
 1294                 {   2 | IFM_IEEE80211_11B, IFM_IEEE80211_DS1 },
 1295                 {   4 | IFM_IEEE80211_11B, IFM_IEEE80211_DS2 },
 1296                 {  11 | IFM_IEEE80211_11B, IFM_IEEE80211_DS5 },
 1297                 {  22 | IFM_IEEE80211_11B, IFM_IEEE80211_DS11 },
 1298                 {  44 | IFM_IEEE80211_11B, IFM_IEEE80211_DS22 },
 1299                 {  12 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM6 },
 1300                 {  18 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM9 },
 1301                 {  24 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM12 },
 1302                 {  36 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM18 },
 1303                 {  48 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM24 },
 1304                 {  72 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM36 },
 1305                 {  96 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM48 },
 1306                 { 108 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM54 },
 1307                 {   2 | IFM_IEEE80211_11G, IFM_IEEE80211_DS1 },
 1308                 {   4 | IFM_IEEE80211_11G, IFM_IEEE80211_DS2 },
 1309                 {  11 | IFM_IEEE80211_11G, IFM_IEEE80211_DS5 },
 1310                 {  22 | IFM_IEEE80211_11G, IFM_IEEE80211_DS11 },
 1311                 {  12 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM6 },
 1312                 {  18 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM9 },
 1313                 {  24 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM12 },
 1314                 {  36 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM18 },
 1315                 {  48 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM24 },
 1316                 {  72 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM36 },
 1317                 {  96 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM48 },
 1318                 { 108 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM54 },
 1319                 /* NB: OFDM72 doesn't really exist so we don't handle it */
 1320         };
 1321         uint64_t mask;
 1322         int i;
 1323 
 1324         mask = rate & IEEE80211_RATE_VAL;
 1325         switch (mode) {
 1326         case IEEE80211_MODE_11A:
 1327                 mask |= IFM_IEEE80211_11A;
 1328                 break;
 1329         case IEEE80211_MODE_11B:
 1330                 mask |= IFM_IEEE80211_11B;
 1331                 break;
 1332         case IEEE80211_MODE_AUTO:
 1333                 /* NB: hack, 11g matches both 11b+11a rates */
 1334                 /* FALLTHROUGH */
 1335         case IEEE80211_MODE_11G:
 1336                 mask |= IFM_IEEE80211_11G;
 1337                 break;
 1338         case IEEE80211_MODE_11N:
 1339         case IEEE80211_MODE_11AC:
 1340                 /* 11n/11ac uses MCS, not rates. */
 1341                 panic("%s: unexpected mode %d", __func__, mode);
 1342                 break;
 1343         }
 1344         for (i = 0; i < nitems(rates); i++)
 1345                 if (rates[i].m == mask)
 1346                         return rates[i].r;
 1347         return IFM_AUTO;
 1348 }
 1349 
 1350 int
 1351 ieee80211_media2rate(uint64_t mword)
 1352 {
 1353         int i;
 1354         static const struct {
 1355                 uint64_t subtype;
 1356                 int rate;
 1357         } ieeerates[] = {
 1358                 { IFM_AUTO,             -1      },
 1359                 { IFM_MANUAL,           0       },
 1360                 { IFM_NONE,             0       },
 1361                 { IFM_IEEE80211_DS1,    2       },
 1362                 { IFM_IEEE80211_DS2,    4       },
 1363                 { IFM_IEEE80211_DS5,    11      },
 1364                 { IFM_IEEE80211_DS11,   22      },
 1365                 { IFM_IEEE80211_DS22,   44      },
 1366                 { IFM_IEEE80211_OFDM6,  12      },
 1367                 { IFM_IEEE80211_OFDM9,  18      },
 1368                 { IFM_IEEE80211_OFDM12, 24      },
 1369                 { IFM_IEEE80211_OFDM18, 36      },
 1370                 { IFM_IEEE80211_OFDM24, 48      },
 1371                 { IFM_IEEE80211_OFDM36, 72      },
 1372                 { IFM_IEEE80211_OFDM48, 96      },
 1373                 { IFM_IEEE80211_OFDM54, 108     },
 1374                 { IFM_IEEE80211_OFDM72, 144     },
 1375         };
 1376         for (i = 0; i < nitems(ieeerates); i++) {
 1377                 if (ieeerates[i].subtype == IFM_SUBTYPE(mword))
 1378                         return ieeerates[i].rate;
 1379         }
 1380         return 0;
 1381 }
 1382 
 1383 /*
 1384  * Convert bit rate (in 0.5Mbps units) to PLCP signal (R4-R1) and vice versa.
 1385  */
 1386 u_int8_t
 1387 ieee80211_rate2plcp(u_int8_t rate, enum ieee80211_phymode mode)
 1388 {
 1389         rate &= IEEE80211_RATE_VAL;
 1390 
 1391         if (mode == IEEE80211_MODE_11B) {
 1392                 /* IEEE Std 802.11b-1999 page 15, subclause 18.2.3.3 */
 1393                 switch (rate) {
 1394                 case 2:         return 10;
 1395                 case 4:         return 20;
 1396                 case 11:        return 55;
 1397                 case 22:        return 110;
 1398                 /* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */
 1399                 case 44:        return 220;
 1400                 }
 1401         } else if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11A) {
 1402                 /* IEEE Std 802.11a-1999 page 14, subclause 17.3.4.1 */
 1403                 switch (rate) {
 1404                 case 12:        return 0x0b;
 1405                 case 18:        return 0x0f;
 1406                 case 24:        return 0x0a;
 1407                 case 36:        return 0x0e;
 1408                 case 48:        return 0x09;
 1409                 case 72:        return 0x0d;
 1410                 case 96:        return 0x08;
 1411                 case 108:       return 0x0c;
 1412                 }
 1413         } else
 1414                 panic("%s: unexpected mode %u", __func__, mode);
 1415 
 1416         DPRINTF(("unsupported rate %u\n", rate));
 1417 
 1418         return 0;
 1419 }
 1420 
 1421 u_int8_t
 1422 ieee80211_plcp2rate(u_int8_t plcp, enum ieee80211_phymode mode)
 1423 {
 1424         if (mode == IEEE80211_MODE_11B) {
 1425                 /* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */
 1426                 switch (plcp) {
 1427                 case 10:        return 2;
 1428                 case 20:        return 4;
 1429                 case 55:        return 11;
 1430                 case 110:       return 22;
 1431                 /* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */
 1432                 case 220:       return 44;
 1433                 }
 1434         } else if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11A) {
 1435                 /* IEEE Std 802.11a-1999 page 14, subclause 17.3.4.1 */
 1436                 switch (plcp) {
 1437                 case 0x0b:      return 12;
 1438                 case 0x0f:      return 18;
 1439                 case 0x0a:      return 24;
 1440                 case 0x0e:      return 36;
 1441                 case 0x09:      return 48;
 1442                 case 0x0d:      return 72;
 1443                 case 0x08:      return 96;
 1444                 case 0x0c:      return 108;
 1445                 }
 1446         } else
 1447                 panic("%s: unexpected mode %u", __func__, mode);
 1448 
 1449         DPRINTF(("unsupported plcp %u\n", plcp));
 1450 
 1451         return 0;
 1452 }

Cache object: 46ba31a860db2cf59257fb6dc98d47c3


[ 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.