📄 ieee80211.c.svn-base
字号:
ic->ic_bsschan->ic_freq)) { struct ieee80211_channel *des_chan = ieee80211_find_channel(ic, vap->iv_des_chan-> ic_freq, vap->iv_des_chan-> ic_flags); /* Can we switch to it? */ if (NULL == des_chan) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, "%s: Desired channel " "not found: %u/%x\n", __func__, vap->iv_des_chan-> ic_freq, vap->iv_des_chan-> ic_flags); } else if (!(des_chan->ic_flags & IEEE80211_CHAN_RADAR)) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, "%s: Desired channel " "found and available. " "Switching to %u/%x\n", __func__, vap->iv_des_chan-> ic_freq, vap->iv_des_chan-> ic_flags); ic->ic_chanchange_chan = des_chan->ic_ieee; ic->ic_chanchange_tbtt = IEEE80211_RADAR_CHANCHANGE_TBTT_COUNT; ic->ic_flags |= IEEE80211_F_CHANSWITCH; } else if (ieee80211_msg_is_reported(vap, IEEE80211_MSG_DOTH)) { /* Find the desired channel in * ic_channels, so we can find the * index into ic_chan_non_occupy. */ int i_des_chan = -1, i = 0; for (i = 0; i < ic->ic_nchans; i++) { if (&ic->ic_channels[i] == des_chan) { i_des_chan = i; break; } } IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, "%s: Desired channel " "found and not " "available until Time: " "%10ld.%06ld\n", __func__, ic->ic_chan_non_occupy [i_des_chan]. tv_sec, ic->ic_chan_non_occupy [i_des_chan]. tv_usec ); } } } } /* update the timer */ ieee80211_update_dfs_excl_timer(ic);}/* This function is called whenever a radar is detected on channel ichan */voidieee80211_mark_dfs(struct ieee80211com *ic, struct ieee80211_channel *ichan){ struct ieee80211_channel *c=NULL; struct net_device *dev = ic->ic_dev; struct timeval tv_now; unsigned int excl_period = ic->ic_get_dfs_excl_period(ic); int i; do_gettimeofday(&tv_now); if_printf(dev, "Radar found on channel %3d (%4d MHz) -- " "Time: %ld.%06ld\n", ichan->ic_ieee, ichan->ic_freq, tv_now.tv_sec, tv_now.tv_usec); if (IEEE80211_IS_MODE_DFS_MASTER(ic->ic_opmode)) { /* Mark the channel in the ic_chan list */ if (ic->ic_flags_ext & IEEE80211_FEXT_MARKDFS) { if_printf(dev, "Marking channel %3d (%4d MHz) in " "ic_chan list -- Time: %ld.%06ld\n", ichan->ic_ieee, ichan->ic_freq, tv_now.tv_sec, tv_now.tv_usec); for (i = 0; i < ic->ic_nchans; i++) { c = &ic->ic_channels[i]; if (c->ic_freq == ichan->ic_freq) { c->ic_flags |= IEEE80211_CHAN_RADAR; ic->ic_chan_non_occupy[i].tv_sec = tv_now.tv_sec + excl_period; ic->ic_chan_non_occupy[i].tv_usec = tv_now.tv_usec; if_printf(dev, "Channel %3d (%4d MHz) " "will become usable in %u " "seconds. Suspending use of " "the channel until: " "%ld.%06ld\n", ichan->ic_ieee, ichan->ic_freq, excl_period, ic->ic_chan_non_occupy[i].tv_sec, ic->ic_chan_non_occupy[i].tv_usec); } } /* Recompute the next time a Non-Occupancy Period * expires. */ ieee80211_update_dfs_excl_timer(ic); c = ieee80211_find_channel(ic, ichan->ic_freq, ichan->ic_flags); if (c == NULL) { if_printf(dev, "%s: Couldn't find matching " "channel for dfs chanchange " "(%d, 0x%x)\n", __func__, ichan->ic_freq, ichan->ic_flags); return; } if (ic->ic_curchan->ic_freq == c->ic_freq) { if_printf(dev, "%s: Invoking " "ieee80211_dfs_action " "(%d, 0x%x)\n", __func__, ichan->ic_freq, ichan->ic_flags); /* The current channel has been marked. We * need to move away from it. */ ieee80211_dfs_action(ic); } else if_printf(dev, "Unexpected channel frequency! " "ichan=%3d (%4d MHz) " "ic_curchan=%3d (%4d MHz). " "Not invoking " "ieee80211_dfs_action.\n", ichan->ic_ieee, ichan->ic_freq, ic->ic_curchan->ic_ieee, ic->ic_curchan->ic_freq); } else { /* Change to a radar free 11a channel for dfstesttime * seconds. */ ic->ic_chanchange_chan = IEEE80211_RADAR_TEST_MUTE_CHAN; ic->ic_chanchange_tbtt = IEEE80211_RADAR_CHANCHANGE_TBTT_COUNT; ic->ic_flags |= IEEE80211_F_CHANSWITCH; if_printf(dev, "Mute test - markdfs is off, we are " "in hostap mode, found radar on " "channel %3d (%4d MHz) " "ic->ic_curchan=%3d (%4d MHz). " "Not invoking ieee80211_dfs_action.\n", ichan->ic_ieee, ichan->ic_freq, ic->ic_curchan->ic_ieee, ic->ic_curchan->ic_freq); } } else { /* XXX: Are we in STA mode? If so, send an action msg. to AP * saying we found a radar? */ }}EXPORT_SYMBOL(ieee80211_mark_dfs);voidieee80211_dfs_test_return(struct ieee80211com *ic, u_int8_t ieeeChan){ struct net_device *dev = ic->ic_dev; /* Return to the original channel we were on before the test mute. */ if_printf(dev, "Returning to channel %d\n", ieeeChan); printk(KERN_DEBUG "Returning to chan %d\n", ieeeChan); ic->ic_chanchange_chan = ieeeChan; ic->ic_chanchange_tbtt = IEEE80211_RADAR_CHANCHANGE_TBTT_COUNT; ic->ic_flags |= IEEE80211_F_CHANSWITCH;}EXPORT_SYMBOL(ieee80211_dfs_test_return);voidieee80211_announce(struct ieee80211com *ic){/* Disabled - creates noise but no useful information. */#if 0 struct net_device *dev = ic->ic_dev; int i, mode, rate, mword; struct ieee80211_rateset *rs; for (mode = IEEE80211_MODE_11A; mode < IEEE80211_MODE_MAX; mode++) { if ((ic->ic_modecaps & (1 << mode)) == 0) continue; if_printf(dev, "%s rates: ", ieee80211_phymode_name[mode]); 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; printk("%s%d%sMbps", (i != 0 ? " " : ""), (rate & IEEE80211_RATE_VAL) / 2, ((rate & 0x1) != 0 ? ".5" : "")); } printk("\n"); } if_printf(dev, "H/W encryption support:"); if (ic->ic_caps & IEEE80211_C_WEP) printk(" WEP"); if (ic->ic_caps & IEEE80211_C_AES) printk(" AES"); if (ic->ic_caps & IEEE80211_C_AES_CCM) printk(" AES_CCM"); if (ic->ic_caps & IEEE80211_C_CKIP) printk(" CKIP"); if (ic->ic_caps & IEEE80211_C_TKIP) printk(" TKIP"); printk("\n");#endif}EXPORT_SYMBOL(ieee80211_announce);voidieee80211_announce_channels(struct ieee80211com *ic){ const struct ieee80211_channel *c; char type; int i; printk(KERN_INFO "Chan Freq RegPwr MinPwr MaxPwr\n"); for (i = 0; i < ic->ic_nchans; i++) { c = &ic->ic_channels[i]; if (IEEE80211_IS_CHAN_ST(c)) type = 'S'; else if (IEEE80211_IS_CHAN_108A(c)) type = 'T'; else if (IEEE80211_IS_CHAN_108G(c)) type = 'G'; else if (IEEE80211_IS_CHAN_A(c)) type = 'a'; else if (IEEE80211_IS_CHAN_ANYG(c)) type = 'g'; else if (IEEE80211_IS_CHAN_B(c)) type = 'b'; else type = 'f'; printk(KERN_INFO "%4d %4d%c %6d %6d %6d\n", c->ic_ieee, c->ic_freq, type, c->ic_maxregpower, c->ic_minpower, c->ic_maxpower ); }}EXPORT_SYMBOL(ieee80211_announce_channels);/* * Common code to calculate the media status word * from the operating mode and channel state. */static intmedia_status(enum ieee80211_opmode opmode, const struct ieee80211_channel *chan){ int status; status = IFM_IEEE80211; switch (opmode) { case IEEE80211_M_STA: break; case IEEE80211_M_AHDEMO: status |= IFM_IEEE80211_ADHOC | IFM_FLAG0; break; case IEEE80211_M_IBSS: status |= IFM_IEEE80211_ADHOC; break; case IEEE80211_M_HOSTAP: status |= IFM_IEEE80211_HOSTAP; break; case IEEE80211_M_MONITOR: status |= IFM_IEEE80211_MONITOR; break; case IEEE80211_M_WDS: status |= IFM_IEEE80211_WDS; break; } if (IEEE80211_IS_CHAN_A(chan)) { status |= IFM_IEEE80211_11A; if (IEEE80211_IS_CHAN_TURBO(chan)) status |= IFM_IEEE80211_TURBO; } else if (IEEE80211_IS_CHAN_B(chan)) { status |= IFM_IEEE80211_11B; } else if (IEEE80211_IS_CHAN_ANYG(chan)) { status |= IFM_IEEE80211_11G; if (IEEE80211_IS_CHAN_TURBO(chan)) status |= IFM_IEEE80211_TURBO; } else if (IEEE80211_IS_CHAN_FHSS(chan)) { status |= IFM_IEEE80211_FH; } /* XXX: Otherwise complain? */ return status;}/* * Handle a media requests on the base interface. */static voidieee80211com_media_status(struct net_device *dev, struct ifmediareq *imr){ struct ieee80211com *ic = netdev_priv(dev); /* XXX */ imr->ifm_status = IFM_AVALID; if (!TAILQ_EMPTY(&ic->ic_vaps)) imr->ifm_status |= IFM_ACTIVE; imr->ifm_active = media_status(ic->ic_opmode, ic->ic_curchan);}/* * Convert a media specification to an 802.11 PHY mode. */static intmedia2mode(const struct ifmedia_entry *ime, enum ieee80211_phymode *mode){ switch (IFM_MODE(ime->ifm_media)) { case IFM_IEEE80211_11A: *mode = IEEE80211_MODE_11A; break; case IFM_IEEE80211_11B: *mode = IEEE80211_MODE_11B; break; case IFM_IEEE80211_11G: *mode = IEEE80211_MODE_11G; break; case IFM_IEEE80211_FH: *mode = IEEE80211_MODE_FH; break; case IFM_AUTO: *mode = IEEE80211_MODE_AUTO; break; default: return 0; } /* * Turbo mode is an 'option'. * XXX: Turbo currently does not apply to AUTO */ if (ime->ifm_media & IFM_IEEE80211_TURBO) { if (*mode == IEEE80211_MODE_11A) *mode = IEEE80211_MODE_TURBO_A; else if (*mode == IEEE80211_MODE_11G) *mode = IEEE80211_MODE_TURBO_G; else return 0; } return 1;}static intieee80211com_media_change(struct net_device *dev){ struct ieee80211com *ic = netdev_priv(dev); /* XXX */ struct ieee80211vap *vap; struct ifmedia_entry *ime = ic->ic_media.ifm_cur; enum ieee80211_phymode newphymode; int j, error = 0; /* XXX: Is rtnl_lock held here? */ /* First, identify the phy mode. */ if (!media2mode(ime, &newphymode)) return -EINVAL; /* NB: Mode must be supported, no need to check */ /* * Autoselect doesn't make sense when operating as an AP. * If no phy mode has been selected, pick one and lock it * down so rate tables can be used in forming beacon frames * and the like. */ if ((ic->ic_opmode == IEEE80211_M_HOSTAP) && (newphymode == IEEE80211_MODE_AUTO)) { for (j = IEEE80211_MODE_11A; j < IEEE80211_MODE_MAX; j++) if (ic->ic_modecaps & (1 << j)) { newphymode = j; break; } } /* Handle PHY mode change. */ IEEE80211_LOCK_IRQ(ic); if (ic->ic_curmode != newphymode) { /* change PHY mode */ error = ieee80211_setmode(ic, newphymode); if (error != 0) { IEEE80211_UNLOCK_IRQ_EARLY(ic); return error; } TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { /* Reset WME state */ ieee80211_wme_initparams_locked(vap); /* * Setup an initial rate set according to the * current/default channel selected above. This * will be changed when scanning but must exist * now so drivers have a consistent state. */ KASSERT(vap->iv_bss != NULL, ("no bss node")); vap->iv_bss->ni_rates = ic->ic_sup_rates[newphymode]; } error = -ENETRESET; } IEEE80211_UNLOCK_IRQ(ic);#ifdef notdef if (error == 0) ifp->if_baudrate = ifmedia_baudrate(ime->ifm_media);#endif return error;}static intfindrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate){#define IEEERATE(_ic,_m,_i) \ ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL) int i, nrates = ic->ic_sup_rates[mode].rs_nrates; for (i = 0; i < nrates; i++) if (IEEERATE(ic, mode, i) == rate) return i; return -1;#undef IEEERATE}/* * Convert a media specification to a rate index and possibly a mode * (if the rate is fixed and the mode is specified as 'auto' then * we need to lock down the mode so the index is meaningful). */static intcheckrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate){ /* Check the rate table for the specified/current PHY. */ if (mode == IEEE80211_MODE_AUTO) { int i; /* In autoselect mode search for the rate. */ for (i = IEEE80211_MODE_11A; i < IEEE80211_MODE_MAX; i++) { if ((ic->ic_modecaps & (1 << i)) && findrate(ic, i, rate) != -1) return 1; } return 0; } else { /* Mode is fixed; check for rate. */ return (findrate(ic, mode, rate) != -1); }}/* * Handle a media change request; the only per-vap * information that is meaningful is the fixed rate * and desired PHY mode. */intieee80211_media_change(struct net_device *dev){ struct ieee80211vap *vap = netdev_priv(dev); struct ieee80211com *ic = vap->iv_ic; struct ifmedia_entry *ime = vap->iv_media.ifm_cur; enum ieee80211_phymode newmode; int newrate, error; /* First, identify the desired PHY mode. */ if (!media2mode(ime, &newmode)) return -EINVAL; /* Check for fixed/variable rate. */ if (IFM_SUBTYPE(ime->ifm_media) != IFM_AUTO) { /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -