svn commit: r195083 - projects/mesh11s/sys/net80211
Sam Leffler
sam at FreeBSD.org
Fri Jun 26 22:58:22 UTC 2009
Author: sam
Date: Fri Jun 26 22:58:22 2009
New Revision: 195083
URL: http://svn.freebsd.org/changeset/base/195083
Log:
import the mac address hash function from bridge and use it for node
table hashing and calculating hash codes for mesh packets q'd waiting
path discovery
Modified:
projects/mesh11s/sys/net80211/ieee80211.c
projects/mesh11s/sys/net80211/ieee80211_hwmp.c
projects/mesh11s/sys/net80211/ieee80211_node.c
projects/mesh11s/sys/net80211/ieee80211_node.h
projects/mesh11s/sys/net80211/ieee80211_var.h
Modified: projects/mesh11s/sys/net80211/ieee80211.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211.c Fri Jun 26 22:26:07 2009 (r195082)
+++ projects/mesh11s/sys/net80211/ieee80211.c Fri Jun 26 22:58:22 2009 (r195083)
@@ -269,6 +269,7 @@ ieee80211_ifattach(struct ieee80211com *
ic->ic_update_mcast = null_update_mcast;
ic->ic_update_promisc = null_update_promisc;
+ ic->ic_hash_key = arc4random();
ic->ic_bintval = IEEE80211_BINTVAL_DEFAULT;
ic->ic_lintval = ic->ic_bintval;
ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX;
@@ -1574,3 +1575,39 @@ ieee80211_media2rate(int mword)
ieeerates[IFM_SUBTYPE(mword)] : 0;
#undef N
}
+
+/*
+ * The following hash function is adapted from "Hash Functions" by Bob Jenkins
+ * ("Algorithm Alley", Dr. Dobbs Journal, September 1997).
+ */
+#define mix(a, b, c) \
+do { \
+ a -= b; a -= c; a ^= (c >> 13); \
+ b -= c; b -= a; b ^= (a << 8); \
+ c -= a; c -= b; c ^= (b >> 13); \
+ a -= b; a -= c; a ^= (c >> 12); \
+ b -= c; b -= a; b ^= (a << 16); \
+ c -= a; c -= b; c ^= (b >> 5); \
+ a -= b; a -= c; a ^= (c >> 3); \
+ b -= c; b -= a; b ^= (a << 10); \
+ c -= a; c -= b; c ^= (b >> 15); \
+} while (/*CONSTCOND*/0)
+
+uint32_t
+ieee80211_mac_hash(const struct ieee80211com *ic,
+ const uint8_t addr[IEEE80211_ADDR_LEN])
+{
+ uint32_t a = 0x9e3779b9, b = 0x9e3779b9, c = ic->ic_hash_key;
+
+ b += addr[5] << 8;
+ b += addr[4];
+ a += addr[3] << 24;
+ a += addr[2] << 16;
+ a += addr[1] << 8;
+ a += addr[0];
+
+ mix(a, b, c);
+
+ return c;
+}
+#undef mix
Modified: projects/mesh11s/sys/net80211/ieee80211_hwmp.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_hwmp.c Fri Jun 26 22:26:07 2009 (r195082)
+++ projects/mesh11s/sys/net80211/ieee80211_hwmp.c Fri Jun 26 22:58:22 2009 (r195083)
@@ -804,11 +804,14 @@ hwmp_recv_prep(struct ieee80211vap *vap,
struct mbuf *m, *next;
/*
* Check for frames queued awaiting path discovery.
- * XXX how can we tell
+ * XXX probably can tell exactly and avoid remove call
+ * NB: hash may have false matches, if so they will get
+ * stuck back on the stageq because there won't be
+ * a path.
*/
m = ieee80211_ageq_remove(&ic->ic_stageq,
(struct ieee80211_node *)(uintptr_t)
- IEEE80211_NODE_HASH(fi->fi_dest));
+ ieee80211_mac_hash(ic, fi->fi_dest));
for (; m != NULL; m = next) {
next = m->m_nextpkt;
m->m_nextpkt = NULL;
@@ -1056,15 +1059,16 @@ done:
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_HWMP,
dest, NULL, "%s", "no valid path to this node");
if (sendpreq) {
+ struct ieee80211com *ic = vap->iv_ic;
/*
* Queue packet for transmit when path discovery
* completes. If discovery never completes the
* frame will be flushed by way of the aging timer.
*/
m->m_pkthdr.rcvif = (void *)(uintptr_t)
- IEEE80211_NODE_HASH(dest);
+ ieee80211_mac_hash(ic, dest);
/* XXX age chosen randomly */
- ieee80211_ageq_append(&vap->iv_ic->ic_stageq, m,
+ ieee80211_ageq_append(&ic->ic_stageq, m,
IEEE80211_INACT_WAIT);
} else
m_freem(m);
Modified: projects/mesh11s/sys/net80211/ieee80211_node.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_node.c Fri Jun 26 22:26:07 2009 (r195082)
+++ projects/mesh11s/sys/net80211/ieee80211_node.c Fri Jun 26 22:58:22 2009 (r195083)
@@ -55,6 +55,11 @@ __FBSDID("$FreeBSD$");
#include <net/bpf.h>
/*
+ * IEEE80211_NODE_HASHSIZE must be a power of 2.
+ */
+CTASSERT((IEEE80211_NODE_HASHSIZE & (IEEE80211_NODE_HASHSIZE-1)) == 0);
+
+/*
* Association id's are managed with a bit vector.
*/
#define IEEE80211_AID_SET(_vap, b) \
@@ -1083,7 +1088,7 @@ ieee80211_alloc_node(struct ieee80211_no
ether_sprintf(macaddr), nt->nt_name);
IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
- hash = IEEE80211_NODE_HASH(macaddr);
+ hash = IEEE80211_NODE_HASH(ic, macaddr);
ieee80211_node_initref(ni); /* mark referenced */
ni->ni_chan = IEEE80211_CHAN_ANYC;
ni->ni_authmode = IEEE80211_AUTH_OPEN;
@@ -1247,7 +1252,7 @@ ieee80211_find_node_locked(struct ieee80
IEEE80211_NODE_LOCK_ASSERT(nt);
- hash = IEEE80211_NODE_HASH(macaddr);
+ hash = IEEE80211_NODE_HASH(nt->nt_ic, macaddr);
LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) {
ieee80211_ref_node(ni); /* mark referenced */
@@ -1297,7 +1302,7 @@ ieee80211_find_vap_node_locked(struct ie
IEEE80211_NODE_LOCK_ASSERT(nt);
- hash = IEEE80211_NODE_HASH(macaddr);
+ hash = IEEE80211_NODE_HASH(nt->nt_ic, macaddr);
LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
if (ni->ni_vap == vap &&
IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) {
Modified: projects/mesh11s/sys/net80211/ieee80211_node.h
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_node.h Fri Jun 26 22:26:07 2009 (r195082)
+++ projects/mesh11s/sys/net80211/ieee80211_node.h Fri Jun 26 22:58:22 2009 (r195083)
@@ -57,11 +57,9 @@
/* threshold for aging overlapping non-ERP bss */
#define IEEE80211_NONERP_PRESENT_AGE msecs_to_ticks(60*1000)
-#define IEEE80211_NODE_HASHSIZE 32
-/* simple hash is enough for variation of macaddr */
-#define IEEE80211_NODE_HASH(addr) \
- (((const uint8_t *)(addr))[IEEE80211_ADDR_LEN - 1] % \
- IEEE80211_NODE_HASHSIZE)
+#define IEEE80211_NODE_HASHSIZE 32 /* NB: hash size must be pow2 */
+#define IEEE80211_NODE_HASH(ic, addr) \
+ (ieee80211_mac_hash(ic, addr) & (IEEE80211_NODE_HASHSIZE-1))
struct ieee80211_node_table;
struct ieee80211com;
Modified: projects/mesh11s/sys/net80211/ieee80211_var.h
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_var.h Fri Jun 26 22:26:07 2009 (r195082)
+++ projects/mesh11s/sys/net80211/ieee80211_var.h Fri Jun 26 22:58:22 2009 (r195083)
@@ -195,6 +195,7 @@ struct ieee80211com {
int ic_max_keyix; /* max h/w key index */
struct ieee80211_node_table ic_sta; /* stations/neighbors */
struct ieee80211_ageq ic_stageq; /* frame staging queue */
+ uint32_t ic_hash_key; /* random key for mac hash */
/* XXX multi-bss: split out common/vap parts */
struct ieee80211_wme_state ic_wme; /* WME/WMM state */
@@ -665,6 +666,8 @@ struct ieee80211_channel *ieee80211_find
int ieee, int flags);
int ieee80211_setmode(struct ieee80211com *, enum ieee80211_phymode);
enum ieee80211_phymode ieee80211_chan2mode(const struct ieee80211_channel *);
+uint32_t ieee80211_mac_hash(const struct ieee80211com *,
+ const uint8_t addr[IEEE80211_ADDR_LEN]);
void ieee80211_radiotap_attach(struct ieee80211com *,
struct ieee80211_radiotap_header *th, int tlen,
More information about the svn-src-projects
mailing list