📄 ieee80211_node.c.svn-base
字号:
ni->ni_flags |= IEEE80211_NODE_ERP;}static voidcount_suppchans(struct ieee80211com *ic, struct ieee80211_node *ni, int inc){ int i, tmp1, tmp2 = 0; if (ni->ni_suppchans == NULL) return; CHANNEL_FOREACH(i, ic, tmp1, tmp2) if (isset(ni->ni_suppchans, i)) ic->ic_chan_nodes[i] += inc; ic->ic_cn_total += inc;}static voidremove_worse_nodes(void *arg, struct ieee80211_node *ni){ struct ieee80211_node *better = (struct ieee80211_node *)arg; int i; if (ni->ni_suppchans == NULL) return; if (ni == better) return; for (i = 0; i < better->ni_n_needed_chans; i++) if (isclr(ni->ni_suppchans, better->ni_needed_chans[i])) { /* this is the one of the nodes to be killed, do it now */ IEEE80211_NOTE_MAC(ni->ni_vap, IEEE80211_MSG_ASSOC|IEEE80211_MSG_DOTH, better->ni_macaddr, "forcing [" MAC_FMT "] (aid %d) to leave", MAC_ADDR(ni->ni_macaddr), IEEE80211_NODE_AID(ni)); IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DISASSOC, IEEE80211_REASON_SUPPCHAN_UNACCEPTABLE); ni->ni_vap->iv_stats.is_node_fdisassoc++; ieee80211_node_leave(ni); return; }}voidieee80211_node_join(struct ieee80211_node *ni, int resp){ struct ieee80211com *ic = ni->ni_ic; struct ieee80211vap *vap = ni->ni_vap; int newassoc; if (ni->ni_associd == 0) { u_int16_t aid; KASSERT(vap->iv_aid_bitmap != NULL, ("no aid bitmap")); /* * It would be good to search the bitmap * more efficiently, but this will do for now. */ for (aid = 1; aid < vap->iv_max_aid; aid++) if (!IEEE80211_AID_ISSET(vap, aid)) break; if (aid >= vap->iv_max_aid) { IEEE80211_SEND_MGMT(ni, resp, IEEE80211_REASON_ASSOC_TOOMANY); ieee80211_node_leave(ni); return; } ni->ni_associd = aid | 0xc000; IEEE80211_LOCK_IRQ(ic); IEEE80211_AID_SET(vap, ni->ni_associd); vap->iv_sta_assoc++; ic->ic_sta_assoc++;#ifdef ATH_SUPERG_XR if (ni->ni_vap->iv_flags & IEEE80211_F_XR) ic->ic_xr_sta_assoc++;#endif if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_ATHC_TURBOP)) ic->ic_dt_sta_assoc++; if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) ieee80211_node_join_11g(ni); KASSERT(ni->ni_suppchans == NULL, ("not a reassociation, but suppchans bitmap not NULL")); /* Use node's new suppchans as the current */ ni->ni_suppchans = ni->ni_suppchans_new; ni->ni_suppchans_new = NULL; /* Add node's suppchans to ic->ic_chan_nodes */ count_suppchans(ic, ni, 1); IEEE80211_UNLOCK_IRQ(ic); newassoc = 1; } else { IEEE80211_LOCK_IRQ(ic); /* Remove node's previous suppchans from ic->ic_chan_nodes */ count_suppchans(ic, ni, -1); if (ni->ni_suppchans != NULL) { FREE(ni->ni_suppchans, M_DEVBUF); ni->ni_suppchans = NULL; } /* Use node's new suppchans as the current */ ni->ni_suppchans = ni->ni_suppchans_new; ni->ni_suppchans_new = NULL; /* Add node's new suppchans to ic->ic_chan_nodes */ count_suppchans(ic, ni, 1); IEEE80211_UNLOCK_IRQ(ic); newassoc = 0; } IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni, "station %sassociated at aid %d: %s preamble, %s slot time" "%s%s%s%s%s%s%s", newassoc ? "" : "re", IEEE80211_NODE_AID(ni), (ic->ic_flags & IEEE80211_F_SHPREAMBLE) && (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) ? "short" : "long", ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long", ic->ic_flags & IEEE80211_F_USEPROT ? ", protection" : "", ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "", IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_TURBOP) ? ", turbo" : "", IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_COMP) ? ", compression" : "", IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_FF) ? ", fast-frames" : "", IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_XR) ? ", XR" : "", IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_AR) ? ", AR" : "" ); /* give driver a chance to setup state like ni_txrate */ if (ic->ic_newassoc != NULL) ic->ic_newassoc(ni, newassoc); ni->ni_inact_reload = vap->iv_inact_auth; ni->ni_inact = ni->ni_inact_reload; IEEE80211_SEND_MGMT(ni, resp, IEEE80211_STATUS_SUCCESS); if (ni->ni_needed_chans != NULL) { /* remove nodes which don't support one of ni->ni_needed_chans */ ieee80211_iterate_nodes(&ic->ic_sta, &remove_worse_nodes, (void *)ni); FREE(ni->ni_needed_chans, M_DEVBUF); ni->ni_needed_chans = NULL; } /* tell the authenticator about new station */ if (vap->iv_auth->ia_node_join != NULL) vap->iv_auth->ia_node_join(ni); ieee80211_notify_node_join(ni, newassoc);}/* * Handle a station leaving an 11g network. */static voidieee80211_node_leave_11g(struct ieee80211_node *ni){ struct ieee80211com *ic = ni->ni_ic; struct ieee80211vap *vap = ni->ni_vap; IEEE80211_LOCK_ASSERT(ic); KASSERT(IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan), ("not in 11g, bss %u:0x%x, curmode %u", ic->ic_bsschan->ic_freq, ic->ic_bsschan->ic_flags, ic->ic_curmode)); /* * If a long slot station do the slot time bookkeeping. */ if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) { /* this can be 0 on mode changes from B -> G */ if (ic->ic_longslotsta > 0) ic->ic_longslotsta--; IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni, "long slot time station leaves, count now %d", ic->ic_longslotsta); if (ic->ic_longslotsta == 0) { /* * Re-enable use of short slot time if supported * and not operating in IBSS mode (per spec). */ if ((ic->ic_caps & IEEE80211_C_SHSLOT) && vap->iv_opmode != IEEE80211_M_IBSS) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC, "%s: re-enable use of short slot time\n", __func__); ieee80211_set_shortslottime(ic, 1); } } } /* * If a non-ERP station do the protection-related bookkeeping. */ if ((ni->ni_flags & IEEE80211_NODE_ERP) == 0) { /* this can be 0 on mode changes from B -> G */ if (ic->ic_nonerpsta > 0) ic->ic_nonerpsta--; IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni, "non-ERP station leaves, count now %d", ic->ic_nonerpsta); if (ic->ic_nonerpsta == 0) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC, "%s: disable use of protection\n", __func__); ic->ic_flags &= ~IEEE80211_F_USEPROT; /* XXX verify mode? */ if (ic->ic_caps & IEEE80211_C_SHPREAMBLE) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC, "%s: re-enable use of short preamble\n", __func__); ic->ic_flags |= IEEE80211_F_SHPREAMBLE; ic->ic_flags &= ~IEEE80211_F_USEBARKER; } ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE; } }}/* * Handle bookkeeping for a station/neighbor leaving * the bss when operating in ap or adhoc modes. */voidieee80211_node_leave(struct ieee80211_node *ni){ struct ieee80211com *ic = ni->ni_ic; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_node_table *nt = ni->ni_table; if (IEEE80211_NODE_AID(ni) != 0) IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni, "station with aid %d leaves (refcnt %u)", IEEE80211_NODE_AID(ni), atomic_read(&ni->ni_refcnt)); /* From this point onwards we can no longer find the node, * so no more references are generated */ ieee80211_remove_wds_addr(nt, ni->ni_macaddr); ieee80211_del_wds_node(nt, ni); IEEE80211_NODE_TABLE_LOCK_IRQ(nt); node_table_leave_locked(nt, ni); IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); /* * If node wasn't previously associated all * we need to do is reclaim the reference. * This also goes for nodes that are auth'ed but * not associated. */ /* XXX ibss mode bypasses 11g and notification */ if (ni->ni_associd == 0) goto done; /* * Tell the authenticator the station is leaving. * Note that we must do this before yanking the * association id as the authenticator uses the * associd to locate its state block. */ if (vap->iv_auth->ia_node_leave != NULL) vap->iv_auth->ia_node_leave(ni); ieee80211_notify_sta_stats(ni); IEEE80211_LOCK_IRQ(ic); if (vap->iv_aid_bitmap != NULL) IEEE80211_AID_CLR(vap, ni->ni_associd); ni->ni_associd = 0; vap->iv_sta_assoc--; ic->ic_sta_assoc--;#ifdef ATH_SUPERG_XR if (ni->ni_vap->iv_flags & IEEE80211_F_XR) ic->ic_xr_sta_assoc--;#endif if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_ATHC_TURBOP)) ic->ic_dt_sta_assoc--; if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) ieee80211_node_leave_11g(ni); /* Remove node's suppchans from ic->ic_chan_nodes */ if (ni->ni_suppchans != NULL) count_suppchans(ic, ni, -1); IEEE80211_UNLOCK_IRQ(ic); /* * Cleanup station state. In particular clear various * state that might otherwise be reused if the node * is reused before the reference count goes to zero * (and memory is reclaimed). */ ieee80211_sta_leave(ni);done: /* Run a cleanup */ ic->ic_node_cleanup(ni);}EXPORT_SYMBOL(ieee80211_node_leave);u_int8_tieee80211_getrssi(struct ieee80211com *ic){#define NZ(x) ((x) == 0 ? 1 : (x)) struct ieee80211_node_table *nt = &ic->ic_sta; struct ieee80211vap *vap; u_int32_t rssi_samples, rssi_total; struct ieee80211_node *ni; rssi_total = 0; rssi_samples = 0; switch (ic->ic_opmode) { case IEEE80211_M_IBSS: /* average of all ibss neighbors */ /* XXX locking */ TAILQ_FOREACH(ni, &nt->nt_node, ni_list) if (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) { rssi_samples++; rssi_total += ic->ic_node_getrssi(ni); } break; case IEEE80211_M_AHDEMO: /* average of all neighbors */ /* XXX locking */ TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { if (memcmp(ni->ni_vap->iv_myaddr, ni->ni_macaddr, IEEE80211_ADDR_LEN)!=0) { rssi_samples++; rssi_total += ic->ic_node_getrssi(ni); } } break; case IEEE80211_M_HOSTAP: /* average of all associated stations */ /* XXX locking */ TAILQ_FOREACH(ni, &nt->nt_node, ni_list) if (IEEE80211_AID(ni->ni_associd) != 0) { rssi_samples++; rssi_total += ic->ic_node_getrssi(ni); } break; case IEEE80211_M_MONITOR: /* XXX */ case IEEE80211_M_STA: /* use stats from associated ap */ default: TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) if (vap->iv_bss != NULL) { rssi_samples++; rssi_total += ic->ic_node_getrssi(vap->iv_bss); } break; } return rssi_total / NZ(rssi_samples);#undef NZ}EXPORT_SYMBOL(ieee80211_getrssi);voidieee80211_node_reset(struct ieee80211_node *ni, struct ieee80211vap *vap){ /* XXX: Untested use of iv_bssid. */ IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_bssid); ni->ni_prev_vap = ni->ni_vap; ni->ni_vap = vap; ni->ni_ic = vap->iv_ic;}EXPORT_SYMBOL(ieee80211_node_reset);struct ieee80211_node *ieee80211_ref_node(struct ieee80211_node *ni){ if (ni == NULL) { printk(KERN_ERR "%s: NULL node.\n", __func__); dump_stack(); }else if (atomic_read(&ni->ni_refcnt) < 1) { node_print_message(IEEE80211_MSG_ANY, 0 /* show counter */, 0 /* adjust refcount */, ni, "attempt to access node with invalid " "refcount of %d. No changes made.", atomic_read(&ni->ni_refcnt)); } else { atomic_inc(&ni->ni_refcnt); node_print_message(IEEE80211_MSG_NODE_REF, 0 /* show counter */, 0 /* adjust refcount */, ni, "ref"); } return ni;}EXPORT_SYMBOL(ieee80211_ref_node);voidieee80211_unref_node(struct ieee80211_node **pni){ struct ieee80211_node *ni = NULL; if (pni == NULL) { printk(KERN_ERR "%s: NULL ieee80211_node **\n", __func__); dump_stack(); return; } ni = *pni; if (ni == NULL) { printk(KERN_ERR "%s: NULL ieee80211_node *\n", __func__); dump_stack(); return; } if (atomic_read(&ni->ni_refcnt) < 1) { node_print_message(IEEE80211_MSG_ANY, 0 /* show counter */, 0 /* adjust refcount */, ni, "attempt to access node with invalid " "refcount of %d. No changes made.", atomic_read(&ni->ni_refcnt)); dump_stack(); return; } node_print_message(IEEE80211_MSG_NODE_REF, 0 /* show counter */, -1 /* adjust refcount */, ni, "unref" /* message */); if (atomic_dec_and_test(&ni->ni_refcnt)) ieee80211_free_node(ni); *pni = NULL;}EXPORT_SYMBOL(ieee80211_unref_node);int32_t ieee80211_get_node_count(struct ieee80211com *ic){ return node_count(ic);}EXPORT_SYMBOL(ieee80211_get_node_count);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -