📄 ieee80211_beacon.c
字号:
wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON; wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; *(u_int16_t *)wh->i_dur = 0; IEEE80211_ADDR_COPY(wh->i_addr1, ic->ic_dev->broadcast); IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr); IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid); *(u_int16_t *)wh->i_seq = 0; return skb;}EXPORT_SYMBOL(ieee80211_beacon_alloc);/* * Update the dynamic parts of a beacon frame based on the current state. */intieee80211_beacon_update(struct ieee80211_node *ni, struct ieee80211_beacon_offsets *bo, struct sk_buff *skb, int mcast){ struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; int len_changed = 0; u_int16_t capinfo; IEEE80211_LOCK(ic); if ((ic->ic_flags & IEEE80211_F_DOTH) && (vap->iv_flags & IEEE80211_F_CHANSWITCH) && (vap->iv_chanchange_count == ic->ic_chanchange_tbtt)) { u_int8_t *frm; struct ieee80211_channel *c; vap->iv_chanchange_count = 0; IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, "%s: reinit beacon\n", __func__); /* * NB: ic_bsschan is in the DSPARMS beacon IE, so must set this * prior to the beacon re-init, below. */ c = ieee80211_doth_findchan(vap, ic->ic_chanchange_chan); if (c == NULL) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, "%s: find channel failure\n", __func__); return 0; } ic->ic_bsschan = c; skb_pull(skb, sizeof(struct ieee80211_frame)); skb_trim(skb, 0); frm = skb->data; skb_put(skb, ieee80211_beacon_init(ni, bo, frm) - frm); skb_push(skb, sizeof(struct ieee80211_frame)); vap->iv_flags &= ~IEEE80211_F_CHANSWITCH; ic->ic_flags &= ~IEEE80211_F_CHANSWITCH; /* NB: only for the first VAP to get here */ if (ic->ic_curchan != c) { ic->ic_curchan = c; ic->ic_set_channel(ic); } len_changed = 1; } /* XXX faster to recalculate entirely or just changes? */ if (vap->iv_opmode == IEEE80211_M_IBSS) capinfo = IEEE80211_CAPINFO_IBSS; else capinfo = IEEE80211_CAPINFO_ESS; if (vap->iv_flags & IEEE80211_F_PRIVACY) capinfo |= IEEE80211_CAPINFO_PRIVACY; if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && IEEE80211_IS_CHAN_2GHZ(ic->ic_bsschan)) capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; if (ic->ic_flags & IEEE80211_F_SHSLOT) capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME; if (ic->ic_flags & IEEE80211_F_DOTH) capinfo |= IEEE80211_CAPINFO_SPECTRUM_MGMT; *bo->bo_caps = htole16(capinfo); if (vap->iv_flags & IEEE80211_F_WME) { struct ieee80211_wme_state *wme = &ic->ic_wme; /* * Check for agressive mode change. When there is * significant high priority traffic in the BSS * throttle back BE traffic by using conservative * parameters. Otherwise BE uses agressive params * to optimize performance of legacy/non-QoS traffic. */ if (wme->wme_flags & WME_F_AGGRMODE) { if (wme->wme_hipri_traffic > wme->wme_hipri_switch_thresh) { IEEE80211_NOTE(vap, IEEE80211_MSG_WME, ni, "%s: traffic %u, disable aggressive mode", __func__, wme->wme_hipri_traffic); wme->wme_flags &= ~WME_F_AGGRMODE; ieee80211_wme_updateparams_locked(vap); wme->wme_hipri_traffic = wme->wme_hipri_switch_hysteresis; } else wme->wme_hipri_traffic = 0; } else { if (wme->wme_hipri_traffic <= wme->wme_hipri_switch_thresh) { IEEE80211_NOTE(vap, IEEE80211_MSG_WME, ni, "%s: traffic %u, enable aggressive mode", __func__, wme->wme_hipri_traffic); wme->wme_flags |= WME_F_AGGRMODE; ieee80211_wme_updateparams_locked(vap); wme->wme_hipri_traffic = 0; } else wme->wme_hipri_traffic = wme->wme_hipri_switch_hysteresis; } /* XXX multi-bss */ if (vap->iv_flags & IEEE80211_F_WMEUPDATE) { (void) ieee80211_add_wme_param(bo->bo_wme, wme, IEEE80211_VAP_UAPSD_ENABLED(vap)); vap->iv_flags &= ~IEEE80211_F_WMEUPDATE; } } if (vap->iv_opmode == IEEE80211_M_HOSTAP) { /* NB: no IBSS support*/ struct ieee80211_tim_ie *tie = (struct ieee80211_tim_ie *) bo->bo_tim; if (vap->iv_flags & IEEE80211_F_TIMUPDATE) { u_int timlen, timoff, i; /* * ATIM/DTIM needs updating. If it fits in the * current space allocated then just copy in the * new bits. Otherwise we need to move any trailing * data to make room. Note that we know there is * contiguous space because ieee80211_beacon_allocate * ensures there is space in the mbuf to write a * maximal-size virtual bitmap (based on ic_max_aid). */ /* * Calculate the bitmap size and offset, copy any * trailer out of the way, and then copy in the * new bitmap and update the information element. * Note that the tim bitmap must contain at least * one byte and any offset must be even. */ if (vap->iv_ps_pending != 0) { timoff = 128; /* impossibly large */ for (i = 0; i < vap->iv_tim_len; i++) if (vap->iv_tim_bitmap[i]) { timoff = i &~ 1; break; } KASSERT(timoff != 128, ("tim bitmap empty!")); for (i = vap->iv_tim_len-1; i >= timoff; i--) if (vap->iv_tim_bitmap[i]) break; timlen = 1 + (i - timoff); } else { timoff = 0; timlen = 1; } if (timlen != bo->bo_tim_len) { /* copy up/down trailer */ int trailer_adjust = (tie->tim_bitmap+timlen) - (bo->bo_tim_trailer); memmove(tie->tim_bitmap+timlen, bo->bo_tim_trailer, bo->bo_tim_trailerlen); bo->bo_tim_trailer = tie->tim_bitmap+timlen; bo->bo_chanswitch += trailer_adjust; bo->bo_wme += trailer_adjust; bo->bo_erp += trailer_adjust; bo->bo_ath_caps += trailer_adjust; bo->bo_xr += trailer_adjust; if (timlen > bo->bo_tim_len) skb_put(skb, timlen - bo->bo_tim_len); else skb_trim(skb, skb->len - (bo->bo_tim_len - timlen)); bo->bo_tim_len = timlen; /* update information element */ tie->tim_len = 3 + timlen; tie->tim_bitctl = timoff; len_changed = 1; } memcpy(tie->tim_bitmap, vap->iv_tim_bitmap + timoff, bo->bo_tim_len); vap->iv_flags &= ~IEEE80211_F_TIMUPDATE; IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni, "%s: TIM updated, pending %u, off %u, len %u", __func__, vap->iv_ps_pending, timoff, timlen); } /* count down DTIM period */ if (tie->tim_count == 0) tie->tim_count = tie->tim_period - 1; else tie->tim_count--; /* update state for buffered multicast frames on DTIM */ if (mcast && (tie->tim_count == 0)) tie->tim_bitctl |= 1; else tie->tim_bitctl &= ~1; if ((ic->ic_flags & IEEE80211_F_DOTH) && (ic->ic_flags & IEEE80211_F_CHANSWITCH)) { if (!vap->iv_chanchange_count) { vap->iv_flags |= IEEE80211_F_CHANSWITCH; /* copy out trailer to open up a slot */ memmove(bo->bo_chanswitch + IEEE80211_CHANSWITCHANN_BYTES, bo->bo_chanswitch, bo->bo_chanswitch_trailerlen); /* add ie in opened slot */ bo->bo_chanswitch[0] = IEEE80211_ELEMID_CHANSWITCHANN; bo->bo_chanswitch[1] = 3; /* fixed length */ bo->bo_chanswitch[2] = 1; /* stas get off for now */ bo->bo_chanswitch[3] = ic->ic_chanchange_chan; bo->bo_chanswitch[4] = ic->ic_chanchange_tbtt; /* update the trailer lens */ bo->bo_chanswitch_trailerlen += IEEE80211_CHANSWITCHANN_BYTES; bo->bo_tim_trailerlen += IEEE80211_CHANSWITCHANN_BYTES; bo->bo_wme += IEEE80211_CHANSWITCHANN_BYTES; bo->bo_erp += IEEE80211_CHANSWITCHANN_BYTES; bo->bo_ath_caps += IEEE80211_CHANSWITCHANN_BYTES; bo->bo_xr += IEEE80211_CHANSWITCHANN_BYTES; /* indicate new beacon length so other layers may manage memory */ skb_put(skb, IEEE80211_CHANSWITCHANN_BYTES); len_changed = 1; } else bo->bo_chanswitch[4]--; vap->iv_chanchange_count++; IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, "%s: CHANSWITCH IE, change in %d\n", __func__, bo->bo_chanswitch[4]); }#ifdef ATH_SUPERG_XR if (vap->iv_flags & IEEE80211_F_XRUPDATE) { if (vap->iv_xrvap) (void) ieee80211_add_xr_param(bo->bo_xr, vap); vap->iv_flags &= ~IEEE80211_F_XRUPDATE; }#endif if (ic->ic_flags_ext & IEEE80211_FEXT_ERPUPDATE) { (void) ieee80211_add_erp(bo->bo_erp, ic); ic->ic_flags_ext &= ~IEEE80211_FEXT_ERPUPDATE; } } /* if it is a mode change beacon for dynamic turbo case */ if (((ic->ic_ath_cap & IEEE80211_ATHC_BOOST) != 0) ^ IEEE80211_IS_CHAN_TURBO(ic->ic_curchan)) ieee80211_add_athAdvCap(bo->bo_ath_caps, vap->iv_bss->ni_ath_flags, vap->iv_bss->ni_ath_defkeyindex); IEEE80211_UNLOCK(ic); return len_changed;}EXPORT_SYMBOL(ieee80211_beacon_update);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -