📄 wlan_node.c
字号:
/* * Copyright (c) 2001 Atsushi Onoe * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting * Copyright (c) 2004-2006 Atheros Communications * * Wireless Network driver for Atheros AR6001 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * *//* * IEEE 802.11 node handling support. */#include "../include/athdefs.h"#include "../include/athtypes.h"#include "../include/osapi.h"#include "../include/ieee80211.h"#include "../include/wlan_api.h"#include "../include/ieee80211_node.h"#include "../include/htc.h"#include "../include/wmi.h"#include "../include/wmi_api.h"#ifdef DEBUGstatic int wlan_node_debug= 1;#define ND_PRINTF if (wlan_node_debug) A_PRINTF#else#define ND_PRINTF(args...)#endifstatic void wlan_node_timeout(unsigned long arg);static bss_t * _ieee80211_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr);bss_t *wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size){ bss_t *ni; ni = A_MALLOC_NOWAIT(sizeof(bss_t)); if (ni != NULL) { ni->ni_buf = A_MALLOC_NOWAIT(wh_size); if (ni->ni_buf == NULL) { A_FREE(ni); ni = NULL; } } /* Make sure our lists are clean */ ni->ni_list_next = NULL; ni->ni_list_prev = NULL; ni->ni_hash_next = NULL; ni->ni_hash_prev = NULL; return ni;}voidwlan_node_free(bss_t *ni){ if (ni->ni_buf != NULL) { A_FREE(ni->ni_buf); } A_FREE(ni);}voidwlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni, const A_UINT8 *macaddr){ int hash; A_MEMCPY(ni->ni_macaddr, macaddr, IEEE80211_ADDR_LEN); hash = IEEE80211_NODE_HASH(macaddr); ieee80211_node_initref(ni); /* mark referenced */ ni->ni_tstamp = jiffies + (WLAN_NODE_INACT_TIMEOUT_MSEC / 1000) * HZ; IEEE80211_NODE_LOCK_BH(nt); /* Insert at the end of the node list */ ni->ni_list_next = NULL; ni->ni_list_prev = nt->nt_node_last; if(nt->nt_node_last != NULL) { nt->nt_node_last->ni_list_next = ni; } nt->nt_node_last = ni; if(nt->nt_node_first == NULL) { nt->nt_node_first = ni; } /* Insert into the hash list i.e. the bucket */ if((ni->ni_hash_next = nt->nt_hash[hash]) != NULL) { nt->nt_hash[hash]->ni_hash_prev = ni; } ni->ni_hash_prev = NULL; nt->nt_hash[hash] = ni; IEEE80211_NODE_UNLOCK_BH(nt);}static bss_t *_ieee80211_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr){ bss_t *ni; int hash; IEEE80211_NODE_LOCK_ASSERT(nt); hash = IEEE80211_NODE_HASH(macaddr); for(ni = nt->nt_hash[hash]; ni; ni = ni->ni_hash_next) { if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) { ieee80211_node_incref(ni); /* mark referenced */ return ni; } } return NULL;}bss_t *wlan_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr){ bss_t *ni; IEEE80211_NODE_LOCK(nt); ni = _ieee80211_find_node(nt, macaddr); IEEE80211_NODE_UNLOCK(nt); return ni;}/* * Reclaim a node. If this is the last reference count then * do the normal free work. Otherwise remove it from the node * table and mark it gone by clearing the back-reference. */voidwlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni){ IEEE80211_NODE_LOCK(nt); if(ni->ni_list_prev == NULL) { /* First in list so fix the list head */ nt->nt_node_first = ni->ni_list_next; } else { ni->ni_list_prev->ni_list_next = ni->ni_list_next; } if(ni->ni_list_next == NULL) { /* Last in list so fix list tail */ nt->nt_node_last = ni->ni_list_prev; } else { ni->ni_list_next->ni_list_prev = ni->ni_list_prev; } if(ni->ni_hash_prev == NULL) { /* First in list so fix the list head */ int hash; hash = IEEE80211_NODE_HASH(ni->ni_macaddr); nt->nt_hash[hash] = ni->ni_hash_next; } else { ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next; } if(ni->ni_hash_next != NULL) { ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev; } wlan_node_free(ni); IEEE80211_NODE_UNLOCK(nt);}static voidwlan_node_dec_free(bss_t *ni){ if (ieee80211_node_dectestref(ni)) { wlan_node_free(ni); }}voidwlan_free_allnodes(struct ieee80211_node_table *nt){ bss_t *ni; while ((ni = nt->nt_node_first) != NULL) { wlan_node_reclaim(nt, ni); }}voidwlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f, void *arg){ bss_t *ni; A_UINT32 gen; gen = nt->nt_scangen++; IEEE80211_NODE_LOCK(nt); for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { if (ni->ni_scangen != gen) { ni->ni_scangen = gen; (void) ieee80211_node_incref(ni); (*f)(arg, ni); wlan_node_dec_free(ni); } } IEEE80211_NODE_UNLOCK(nt);}/* * Node table support. */voidwlan_node_table_init(void *wmip, struct ieee80211_node_table *nt){ int i; ND_PRINTF("node table = 0x%x\n", (A_UINT32)nt); IEEE80211_NODE_LOCK_INIT(nt); nt->nt_node_first = nt->nt_node_last = NULL; for(i = 0; i < IEEE80211_NODE_HASHSIZE; i++) { nt->nt_hash[i] = NULL; } A_INIT_TIMER(&nt->nt_inact_timer, wlan_node_timeout, nt); A_TIMEOUT_MS(&nt->nt_inact_timer, WLAN_NODE_INACT_TIMEOUT_MSEC, 0); nt->nt_wmip = wmip;}static voidwlan_node_timeout(unsigned long arg){ struct ieee80211_node_table *nt = (struct ieee80211_node_table *)arg; bss_t *bss, *nextBss; A_UINT8 myBssid[IEEE80211_ADDR_LEN]; wmi_get_current_bssid(nt->nt_wmip, myBssid); bss = nt->nt_node_first; while (bss != NULL) { nextBss = bss->ni_list_next; if ((A_MEMCMP(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0) && (bss->ni_tstamp <= jiffies)) { /* * free up all but the current bss - if set */ wlan_node_reclaim(nt, bss); } bss = nextBss; } A_TIMEOUT_MS(&nt->nt_inact_timer, WLAN_NODE_INACT_TIMEOUT_MSEC, 0);}voidwlan_node_table_cleanup(struct ieee80211_node_table *nt){ A_UNTIMEOUT(&nt->nt_inact_timer); wlan_free_allnodes(nt); IEEE80211_NODE_LOCK_DESTROY(nt);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -