📄 ieee80211_node.c
字号:
IEEE80211_NODE_UNLOCK(nt); (*f)(arg, ni); ieee80211_free_node(ni); goto restart; } } IEEE80211_NODE_UNLOCK(nt); IEEE80211_SCAN_UNLOCK_IRQ(nt);}EXPORT_SYMBOL(ieee80211_iterate_nodes);voidieee80211_dump_node(struct ieee80211_node_table *nt, struct ieee80211_node *ni){ int i; printf("0x%p: mac %s refcnt %d\n", ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)); printf("\tscangen %u authmode %u flags 0x%x\n", ni->ni_scangen, ni->ni_authmode, ni->ni_flags); printf("\tassocid 0x%x txpower %u vlan %u\n", ni->ni_associd, ni->ni_txpower, ni->ni_vlan); printf ("rxfragstamp %u\n", ni->ni_rxfragstamp); for (i = 0; i < 17; i++) { printf("\t%d: txseq %u rxseq %u fragno %u\n", i, ni->ni_txseqs[i], ni->ni_rxseqs[i] >> IEEE80211_SEQ_SEQ_SHIFT, ni->ni_rxseqs[i] & IEEE80211_SEQ_FRAG_MASK); } printf("\trstamp %u rssi %u intval %u capinfo 0x%x\n", ni->ni_rstamp, ni->ni_rssi, ni->ni_intval, ni->ni_capinfo); printf("\tbssid %s essid \"%.*s\" channel %u:0x%x\n", ether_sprintf(ni->ni_bssid), ni->ni_esslen, ni->ni_essid, ni->ni_chan != IEEE80211_CHAN_ANYC ? ni->ni_chan->ic_freq : IEEE80211_CHAN_ANY, ni->ni_chan != IEEE80211_CHAN_ANYC ? ni->ni_chan->ic_flags : 0); printf("\tinact %u txrate %u\n", ni->ni_inact, ni->ni_txrate);}voidieee80211_dump_nodes(struct ieee80211_node_table *nt){ ieee80211_iterate_nodes(nt, (ieee80211_iter_func *) ieee80211_dump_node, nt);}/* * Handle a station joining an 11g network. */static voidieee80211_node_join_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)); /* * Station isn't capable of short slot time. Bump * the count of long slot time stations and disable * use of short slot time. Note that the actual switch * over to long slot time use may not occur until the * next beacon transmission (per sec. 7.3.1.4 of 11g). */ if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) { ic->ic_longslotsta++; IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni, "station needs long slot time, count %d", ic->ic_longslotsta); /* XXX vap's w/ conflicting needs won't work */ if (!IEEE80211_IS_CHAN_108G(ic->ic_bsschan)) { /* * Don't force slot time when switched to turbo * mode as non-ERP stations won't be present; this * need only be done when on the normal G channel. */ ieee80211_set_shortslottime(ic, 0); } } /* * If the new station is not an ERP station * then bump the counter and enable protection * if configured. */ if (!ieee80211_iserp_rateset(ic, &ni->ni_rates)) { ic->ic_nonerpsta++; IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni, "station is !ERP, %d non-ERP stations associated", ic->ic_nonerpsta); /* * If protection is configured, enable it. */ if (ic->ic_protmode != IEEE80211_PROT_NONE) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC, "%s: enable use of protection\n", __func__); ic->ic_flags |= IEEE80211_F_USEPROT; } /* * If station does not support short preamble * then we must enable use of Barker preamble. */ if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) == 0) { IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni, "%s", "station needs long preamble"); ic->ic_flags |= IEEE80211_F_USEBARKER; ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE; } /* Update ERP element if this is first non ERP station */ if (ic->ic_nonerpsta == 1) ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE; } else ni->ni_flags |= IEEE80211_NODE_ERP;}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); IEEE80211_UNLOCK_IRQ(ic); newassoc = 1; } else 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 ? "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); /* 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; IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni, "station with aid %d leaves (refcnt %u)", IEEE80211_NODE_AID(ni), ieee80211_node_refcnt(ni)); /* * If node wasn't previously associated all * we need to do is reclaim the reference. */ /* 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 it's state block. */ if (vap->iv_auth->ia_node_leave != NULL) vap->iv_auth->ia_node_leave(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); 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: /* * Remove the node from any table it's recorded in and * drop the caller's reference. Removal from the table * is important to ensure the node is not reprocessed * for inactivity. */ if (nt != NULL) { IEEE80211_NODE_LOCK_IRQ(nt); node_reclaim(nt, ni); IEEE80211_NODE_UNLOCK_IRQ(nt); ieee80211_remove_wds_addr(nt,ni->ni_macaddr); ieee80211_del_wds_node(nt,ni); } else ieee80211_free_node(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){ if (ni != NULL) { struct ieee80211_node_table *nt = ni->ni_table; if (!nt) nt = &vap->iv_ic->ic_sta; IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_bss->ni_bssid); ni->ni_prev_vap = ni->ni_vap; ni->ni_vap = vap; ni->ni_ic = vap->iv_ic; /* * if node not found in the node table * add it to the node table . */ if(nt && ieee80211_find_node(nt, ni->ni_macaddr) != ni) { int hash = IEEE80211_NODE_HASH(ni->ni_macaddr); IEEE80211_NODE_LOCK_IRQ(nt); TAILQ_INSERT_TAIL(&nt->nt_node, ni, ni_list); LIST_INSERT_HEAD(&nt->nt_hash[hash], ni, ni_hash); ni->ni_table = nt; IEEE80211_NODE_UNLOCK_IRQ(nt); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -