📄 ieee80211.c.svn-base
字号:
vap->iv_ath_cap &= ~IEEE80211_ATHC_TURBOP; if ((vap->iv_flags & IEEE80211_VAP_XR) == 0) vap->iv_ath_cap &= ~IEEE80211_ATHC_XR; break; case IEEE80211_M_MONITOR: vap->iv_caps |= IEEE80211_C_MONITOR; vap->iv_ath_cap &= ~(IEEE80211_ATHC_XR | IEEE80211_ATHC_TURBOP); break; case IEEE80211_M_WDS: vap->iv_caps |= IEEE80211_C_WDS; vap->iv_ath_cap &= ~(IEEE80211_ATHC_XR | IEEE80211_ATHC_TURBOP); vap->iv_flags_ext |= IEEE80211_FEXT_WDS; break; } vap->iv_opmode = opmode; IEEE80211_INIT_TQUEUE(&vap->iv_stajoin1tq, ieee80211_sta_join1_tasklet, vap); vap->iv_chanchange_count = 0; /* Enable various functionality by default, if we're capable. */#ifdef ATH_WME /* Not yet the default */ if (vap->iv_caps & IEEE80211_C_WME) vap->iv_flags |= IEEE80211_F_WME;#endif if (vap->iv_caps & IEEE80211_C_FF) vap->iv_flags |= IEEE80211_F_FF; /* NB: Background scanning only makes sense for station mode right now */ if (ic->ic_opmode == IEEE80211_M_STA && (vap->iv_caps & IEEE80211_C_BGSCAN)) vap->iv_flags |= IEEE80211_F_BGSCAN; vap->iv_dtim_period = IEEE80211_DTIM_DEFAULT; vap->iv_des_chan = IEEE80211_CHAN_ANYC; /* any channel is OK */ vap->iv_monitor_crc_errors = 0; vap->iv_monitor_phy_errors = 0; IEEE80211_ADDR_COPY(vap->iv_myaddr, ic->ic_myaddr); IEEE80211_ADDR_COPY(vap->iv_bssid, ic->ic_myaddr); /* NB: Defer setting dev_addr so driver can override */ ieee80211_crypto_vattach(vap); ieee80211_node_vattach(vap); ieee80211_power_vattach(vap); ieee80211_proto_vattach(vap); ieee80211_scan_vattach(vap); ieee80211_vlan_vattach(vap); ieee80211_ioctl_vattach(vap); return 1;#undef IEEE80211_C_OPMODE}EXPORT_SYMBOL(ieee80211_vap_setup);intieee80211_vap_attach(struct ieee80211vap *vap, ifm_change_cb_t media_change, ifm_stat_cb_t media_status){ struct net_device *dev = vap->iv_dev; struct ieee80211com *ic = vap->iv_ic; struct ifmediareq imr; ieee80211_node_latevattach(vap); /* XXX: move into vattach */ ieee80211_power_latevattach(vap); /* XXX: move into vattach */ memset(vap->wds_mac, 0x00, IEEE80211_ADDR_LEN); (void) ieee80211_media_setup(ic, &vap->iv_media, vap->iv_caps, media_change, media_status); ieee80211_media_status(dev, &imr); ifmedia_set(&vap->iv_media, imr.ifm_active); IEEE80211_LOCK_IRQ(ic); TAILQ_INSERT_TAIL(&ic->ic_vaps, vap, iv_next); IEEE80211_UNLOCK_IRQ(ic); IEEE80211_ADDR_COPY(dev->dev_addr, vap->iv_myaddr);#ifdef ATH_SUPERG_XR /* Do not register XR VAP device with OS. */ if (vap->iv_flags & IEEE80211_F_XR) return 0;#endif ieee80211_scanner_get(vap->iv_opmode, 1); /* NB: rtnl_lock is held on entry, so don't use register_netdev */ if (register_netdevice(dev)) { printk(KERN_ERR "%s: unable to register device\n", dev->name); return 0; } /* SysFS needs to be initialised after the device, as it uses the * device koject */ ieee80211_virtfs_latevattach(vap); return 1;}EXPORT_SYMBOL(ieee80211_vap_attach);voidieee80211_vap_detach(struct ieee80211vap *vap){ struct ieee80211com *ic = vap->iv_ic; struct net_device *dev = vap->iv_dev; IEEE80211_CANCEL_TQUEUE(&vap->iv_stajoin1tq); IEEE80211_LOCK_IRQ(ic); TAILQ_REMOVE(&ic->ic_vaps, vap, iv_next); if (TAILQ_EMPTY(&ic->ic_vaps)) /* reset to supported mode */ ic->ic_opmode = IEEE80211_M_STA; IEEE80211_UNLOCK_IRQ(ic); ifmedia_removeall(&vap->iv_media); ieee80211_virtfs_vdetach(vap); ieee80211_proc_cleanup(vap); ieee80211_ioctl_vdetach(vap); ieee80211_vlan_vdetach(vap); ieee80211_scan_vdetach(vap); ieee80211_proto_vdetach(vap); ieee80211_crypto_vdetach(vap); ieee80211_power_vdetach(vap); ieee80211_node_vdetach(vap);#ifdef ATH_SUPERG_XR /* XR VAP is not registered. */ if (!(vap->iv_flags & IEEE80211_F_XR))#endif /* NB: rtnl_lock is held on entry so don't use unregister_netdev */ unregister_netdevice(dev);}EXPORT_SYMBOL(ieee80211_vap_detach);/* * Convert MHz frequency to IEEE channel number. */u_intieee80211_mhz2ieee(u_int freq, u_int flags){ if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */ if (freq == 2484) /* Japan */ return 14; if ((freq >= 2412) && (freq < 2484)) /* don't number non-IEEE channels */ return (freq - 2407) / 5; return 0; } else if (flags & IEEE80211_CHAN_5GHZ) { /* 5Ghz band */ if ((freq >= 5150) && (freq <= 5825)) /* don't number non-IEEE channels */ return (freq - 5000) / 5; return 0; } else { /* Something is fishy, don't do anything */ return 0; }}EXPORT_SYMBOL(ieee80211_mhz2ieee);/* * Convert channel to IEEE channel number. */u_intieee80211_chan2ieee(struct ieee80211com *ic, const struct ieee80211_channel *c){ if (c == NULL) { if_printf(ic->ic_dev, "invalid channel (NULL)\n"); return 0; /* XXX */ } return (c == IEEE80211_CHAN_ANYC ? IEEE80211_CHAN_ANY : c->ic_ieee);}EXPORT_SYMBOL(ieee80211_chan2ieee);/* * Convert IEEE channel number to MHz frequency. */u_intieee80211_ieee2mhz(u_int chan, u_int flags){ if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */ if (chan == 14) return 2484; if (chan < 14) return 2407 + chan * 5; else return 2512 + ((chan - 15) * 20); } else if (flags & IEEE80211_CHAN_5GHZ) /* 5Ghz band */ return 5000 + (chan * 5); else { /* either, guess */ if (chan == 14) return 2484; if (chan < 14) /* 0-13 */ return 2407 + chan * 5; if (chan < 27) /* 15-26 */ return 2512 + ((chan - 15) * 20); return 5000 + (chan * 5); }}EXPORT_SYMBOL(ieee80211_ieee2mhz);/* * Locate a channel given a frequency+flags. We cache * the previous lookup to optimize swithing between two * channels--as happens with dynamic turbo. */struct ieee80211_channel *ieee80211_find_channel(struct ieee80211com *ic, int freq, int flags){ struct ieee80211_channel *c; int i; /* Brute force search */ for (i = 0; i < ic->ic_nchans; i++) { c = &ic->ic_channels[i]; if (c->ic_freq == freq && (flags == 0 || (c->ic_flags & IEEE80211_CHAN_ALLTURBO) == flags)) return c; } return NULL;}EXPORT_SYMBOL(ieee80211_find_channel);/* * Setup the media data structures according to the channel and * rate tables. This must be called by the driver after * ieee80211_attach and before most anything else. */intieee80211_media_setup(struct ieee80211com *ic, struct ifmedia *media, u_int32_t caps, ifm_change_cb_t media_change, ifm_stat_cb_t media_stat){#define ADD(_media, _s, _o) \ ifmedia_add(_media, IFM_MAKEWORD(IFM_IEEE80211, (_s), (_o), 0), 0, NULL) int i, j, mode, rate, maxrate, mword, mopt, r; struct ieee80211_rateset *rs; struct ieee80211_rateset allrates; /* Fill in media characteristics. */ ifmedia_init(media, 0, media_change, media_stat); maxrate = 0; memset(&allrates, 0, sizeof(allrates)); for (mode = IEEE80211_MODE_AUTO; mode < IEEE80211_MODE_MAX; mode++) { static const u_int mopts[] = { IFM_AUTO, IFM_IEEE80211_11A, IFM_IEEE80211_11B, IFM_IEEE80211_11G, IFM_IEEE80211_FH, IFM_IEEE80211_11A | IFM_IEEE80211_TURBO, IFM_IEEE80211_11G | IFM_IEEE80211_TURBO, }; if ((ic->ic_modecaps & (1 << mode)) == 0) continue; mopt = mopts[mode]; ADD(media, IFM_AUTO, mopt); /* e.g. 11a auto */ if (caps & IEEE80211_C_IBSS) ADD(media, IFM_AUTO, mopt | IFM_IEEE80211_ADHOC); if (caps & IEEE80211_C_HOSTAP) ADD(media, IFM_AUTO, mopt | IFM_IEEE80211_HOSTAP); if (caps & IEEE80211_C_AHDEMO) ADD(media, IFM_AUTO, mopt | IFM_IEEE80211_ADHOC | IFM_FLAG0); if (caps & IEEE80211_C_MONITOR) ADD(media, IFM_AUTO, mopt | IFM_IEEE80211_MONITOR); if (caps & IEEE80211_C_WDS) ADD(media, IFM_AUTO, mopt | IFM_IEEE80211_WDS); if (mode == IEEE80211_MODE_AUTO) continue; rs = &ic->ic_sup_rates[mode]; for (i = 0; i < rs->rs_nrates; i++) { rate = rs->rs_rates[i]; mword = ieee80211_rate2media(ic, rate, mode); if (mword == 0) continue; ADD(media, mword, mopt); if (caps & IEEE80211_C_IBSS) ADD(media, mword, mopt | IFM_IEEE80211_ADHOC); if (caps & IEEE80211_C_HOSTAP) ADD(media, mword, mopt | IFM_IEEE80211_HOSTAP); if (caps & IEEE80211_C_AHDEMO) ADD(media, mword, mopt | IFM_IEEE80211_ADHOC | IFM_FLAG0); if (caps & IEEE80211_C_MONITOR) ADD(media, mword, mopt | IFM_IEEE80211_MONITOR); if (caps & IEEE80211_C_WDS) ADD(media, mword, mopt | IFM_IEEE80211_WDS); /* Add rate to the collection of all rates. */ r = rate & IEEE80211_RATE_VAL; for (j = 0; j < allrates.rs_nrates; j++) if (allrates.rs_rates[j] == r) break; if (j == allrates.rs_nrates) { /* Unique, add to the set */ allrates.rs_rates[j] = r; allrates.rs_nrates++; } rate = (rate & IEEE80211_RATE_VAL) / 2; if (rate > maxrate) maxrate = rate; } } for (i = 0; i < allrates.rs_nrates; i++) { mword = ieee80211_rate2media(ic, allrates.rs_rates[i], IEEE80211_MODE_AUTO); if (mword == 0) continue; mword = IFM_SUBTYPE(mword); /* remove media options */ ADD(media, mword, 0); if (caps & IEEE80211_C_IBSS) ADD(media, mword, IFM_IEEE80211_ADHOC); if (caps & IEEE80211_C_HOSTAP) ADD(media, mword, IFM_IEEE80211_HOSTAP); if (caps & IEEE80211_C_AHDEMO) ADD(media, mword, IFM_IEEE80211_ADHOC | IFM_FLAG0); if (caps & IEEE80211_C_MONITOR) ADD(media, mword, IFM_IEEE80211_MONITOR); if (caps & IEEE80211_C_WDS) ADD(media, mword, IFM_IEEE80211_WDS); } return maxrate;#undef ADD}/* * Perform the DFS action (channel switch) using scan cache or a randomly * chosen channel. The choice of the random channel is done in * ieee80211_scan_dfs_action(). * * This was moved out of ieee80211_mark_dfs(), because the same functionality * is used also in ieee80211_ioctl_chanswitch(). */voidieee80211_dfs_action(struct ieee80211com *ic) { struct ieee80211vap *vap; /* Get an AP mode VAP */ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { if (vap->iv_state == IEEE80211_S_RUN) { break; } } if (vap == NULL) { /* * No running VAP was found, check * if any one is scanning. */ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { if (vap->iv_state == IEEE80211_S_SCAN) { break; } } /* No running/scanning VAP was found, so they're all in * INIT state, no channel change needed. */ if (vap == NULL) return; /* Is it really Scanning */ /* XXX: Race condition? */ if (ic->ic_flags & IEEE80211_F_SCAN) return; /* It is not scanning, but waiting for ath driver to move the * vap to RUN. */ } /* Check the scan results using only cached results */ if (!(ieee80211_check_scan(vap, IEEE80211_SCAN_NOSSID | IEEE80211_SCAN_KEEPMODE | IEEE80211_SCAN_USECACHE, 0, vap->iv_des_nssid, vap->iv_des_ssid, ieee80211_scan_dfs_action))) { /* No channel was found, so call the scan action with no * result. */ ieee80211_scan_dfs_action(vap, NULL); }}voidieee80211_expire_excl_restrictions(struct ieee80211com *ic){ struct ieee80211_channel *c = NULL; struct net_device *dev = ic->ic_dev; struct timeval tv_now; int i; do_gettimeofday(&tv_now); for (i = 0; i < ic->ic_nchans; i++) { c = &ic->ic_channels[i]; if (c->ic_flags & IEEE80211_CHAN_RADAR) { if (timeval_compare(&ic->ic_chan_non_occupy[i], &tv_now) < 0) { if_printf(dev, "Returning channel %3d (%4d MHz) " "radar avoidance marker expired. " "Channel now available again. -- " "Time: %10ld.%06ld\n", c->ic_ieee, c->ic_freq, tv_now.tv_sec, tv_now.tv_usec); c->ic_flags &= ~IEEE80211_CHAN_RADAR; } else { if_printf(dev, "Channel %3d (%4d MHz) is still " "marked for radar. Channel will " "become usable in %u seconds at " "Time: %10ld.%06ld\n", c->ic_ieee, c->ic_freq, ic->ic_chan_non_occupy[i].tv_sec - tv_now.tv_sec, ic->ic_chan_non_occupy[i].tv_sec, ic->ic_chan_non_occupy[i].tv_usec); } } }}EXPORT_SYMBOL(ieee80211_expire_excl_restrictions);/* Update the Non-Occupancy Period timer with the first Non-Occupancy Period * that will expire */static voidieee80211_update_dfs_excl_timer(struct ieee80211com *ic){ struct ieee80211_channel * chan; struct timeval tv_now, tv_next; int i; unsigned long jiffies_tmp; do_gettimeofday(&tv_now); jiffies_tmp = jiffies; tv_next.tv_sec = 0; tv_next.tv_usec = 0; for (i = 0; i < ic->ic_nchans; i++) { chan = &ic->ic_channels[i]; if (chan->ic_flags & IEEE80211_CHAN_RADAR) { if ((tv_next.tv_sec == 0) && (tv_next.tv_usec == 0)) { tv_next = ic->ic_chan_non_occupy[i]; } if (timeval_compare(&ic->ic_chan_non_occupy[i], &tv_next) < 0) { tv_next = ic->ic_chan_non_occupy[i]; } } } if ((tv_next.tv_sec == 0) && (tv_next.tv_usec == 0)) { del_timer(&ic->ic_dfs_excl_timer); } else { mod_timer(&ic->ic_dfs_excl_timer, jiffies_tmp + (tv_next.tv_sec - tv_now.tv_sec + 1) * HZ); }}/* Periodically expire radar avoidance marks. */static voidieee80211_expire_dfs_excl_timer(unsigned long data){ struct ieee80211com *ic = (struct ieee80211com *)data; struct ieee80211vap *vap; printk(KERN_INFO "%s: %s: expiring Non-Occupancy Period\n", DEV_NAME(ic->ic_dev), __func__); if (ic->ic_flags_ext & IEEE80211_FEXT_MARKDFS) { /* Make sure there are no channels that have just become * available. */ ieee80211_expire_excl_restrictions(ic); /* Go through and clear any interference flag we have, if we * just got it cleared up for us */ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { /* We need to check for the special value IEEE80211_CHAN_ANYC before using vap->iv_des_chan since it will cause a kernel panic */ if ((vap->iv_state == IEEE80211_S_RUN) && ((vap->iv_opmode == IEEE80211_M_HOSTAP) || (vap->iv_opmode == IEEE80211_M_IBSS)) && /* Operating on channel other than desired. */ (vap->iv_des_chan != IEEE80211_CHAN_ANYC) && (vap->iv_des_chan->ic_freq > 0) && (vap->iv_des_chan->ic_freq !=
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -