Signed-Off-By: Georg Lukas diff -x foo/ -uNr -x .svn -x .o madwifi-ng/ath/if_ath.c madwifi-ng-refcount/ath/if_ath.c --- madwifi-ng/ath/if_ath.c 2007-02-05 10:13:49.402432000 +0100 +++ madwifi-ng-refcount/ath/if_ath.c 2007-02-07 12:55:37.830095000 +0100 @@ -159,8 +159,7 @@ static int ath_desc_alloc(struct ath_softc *); static void ath_desc_free(struct ath_softc *); static void ath_desc_swap(struct ath_desc *); -static struct ieee80211_node *ath_node_alloc(struct ieee80211_node_table *, - struct ieee80211vap *); +static struct ieee80211_node *ath_node_alloc(struct ieee80211vap *); static void ath_node_cleanup(struct ieee80211_node *); static void ath_node_free(struct ieee80211_node *); static u_int8_t ath_node_getrssi(const struct ieee80211_node *); @@ -2460,7 +2459,7 @@ if (ath_tx_start(sc->sc_dev, ni, bf_ff, bf_ff->bf_skb, 0) == 0) continue; bad: - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); if (bf_ff->bf_skb != NULL) { dev_kfree_skb(bf_ff->bf_skb); bf_ff->bf_skb = NULL; @@ -2601,7 +2600,7 @@ ATH_FF_MAGIC_PUT(skb); /* decrement extra node reference made when an_tx_ffbuf[] was set */ - //ieee80211_free_node(ni); /* XXX where was it set ? */ + //ieee80211_unref_node(&ni); /* XXX where was it set ? */ DPRINTF(sc, ATH_DEBUG_XMIT | ATH_DEBUG_FF, "%s: aggregating fast-frame\n", __func__); @@ -2660,7 +2659,7 @@ ff_flushbad: DPRINTF(sc, ATH_DEBUG_XMIT | ATH_DEBUG_FF, "%s: ff stageq flush failure\n", __func__); - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); if (bf_ff->bf_skb) { dev_kfree_skb(bf_ff->bf_skb); bf_ff->bf_skb = NULL; @@ -2785,7 +2784,7 @@ tbf->bf_node = NULL; if (ni != NULL) - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); STAILQ_INSERT_TAIL(&sc->sc_txbuf, tbf, bf_list); } @@ -2867,7 +2866,7 @@ /* fall thru... */ bad: if (ni != NULL) - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); if (bf != NULL) { bf->bf_skb = NULL; bf->bf_node = NULL; @@ -3253,7 +3252,7 @@ */ ni = sc->sc_keyixmap[keyix]; if (ni != NULL) { - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); sc->sc_keyixmap[keyix] = NULL; } /* @@ -3264,7 +3263,7 @@ ath_hal_keyreset(ah, keyix + 32); /* RX key */ ni = sc->sc_keyixmap[keyix + 32]; if (ni != NULL) { /* as above... */ - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); sc->sc_keyixmap[keyix + 32] = NULL; } } @@ -3277,7 +3276,7 @@ ath_hal_keyreset(ah, keyix + rxkeyoff); ni = sc->sc_keyixmap[keyix + rxkeyoff]; if (ni != NULL) { /* as above... */ - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); sc->sc_keyixmap[keyix + rxkeyoff] = NULL; } } @@ -3833,10 +3832,8 @@ dev_kfree_skb(bf->bf_skb); bf->bf_skb = NULL; } - if (bf->bf_node != NULL) { - ieee80211_free_node(bf->bf_node); - bf->bf_node = NULL; - } + if (bf->bf_node != NULL) + ieee80211_unref_node(&bf->bf_node); /* * NB: the beacon data buffer must be 32-bit aligned; @@ -4380,10 +4377,8 @@ dev_kfree_skb(bf->bf_skb); bf->bf_skb = NULL; } - if (bf->bf_node != NULL) { - ieee80211_free_node(bf->bf_node); - bf->bf_node = NULL; - } + if (bf->bf_node != NULL) + ieee80211_unref_node(&bf->bf_node); STAILQ_INSERT_TAIL(&sc->sc_bbuf, bf, bf_list); } @@ -4402,10 +4397,8 @@ dev_kfree_skb(bf->bf_skb); bf->bf_skb = NULL; } - if (bf->bf_node != NULL) { - ieee80211_free_node(bf->bf_node); - bf->bf_node = NULL; - } + if (bf->bf_node != NULL) + ieee80211_unref_node(&bf->bf_node); } } @@ -4706,7 +4683,7 @@ /* * Reclaim node reference. */ - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); } } @@ -4765,37 +4742,39 @@ } static struct ieee80211_node * -ath_node_alloc(struct ieee80211_node_table *nt,struct ieee80211vap *vap) +ath_node_alloc(struct ieee80211vap *vap) { - struct ath_softc *sc = nt->nt_ic->ic_dev->priv; + struct ath_softc *sc = vap->iv_ic->ic_dev->priv; const size_t space = sizeof(struct ath_node) + sc->sc_rc->arc_space; struct ath_node *an; an = kmalloc(space, GFP_ATOMIC); - if (an == NULL) - return NULL; - memset(an, 0, space); - an->an_decomp_index = INVALID_DECOMP_INDEX; - an->an_avgrssi = ATH_RSSI_DUMMY_MARKER; - an->an_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; - an->an_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER; - an->an_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; - /* - * ath_rate_node_init needs a VAP pointer in node - * to decide which mgt rate to use - */ - an->an_node.ni_vap = vap; - sc->sc_rc->ops->node_init(sc, an); - - /* U-APSD init */ - STAILQ_INIT(&an->an_uapsd_q); - an->an_uapsd_qdepth = 0; - STAILQ_INIT(&an->an_uapsd_overflowq); - an->an_uapsd_overflowqdepth = 0; - ATH_NODE_UAPSD_LOCK_INIT(an); + if (an != NULL) { + memset(an, 0, space); + an->an_decomp_index = INVALID_DECOMP_INDEX; + an->an_avgrssi = ATH_RSSI_DUMMY_MARKER; + an->an_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; + an->an_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER; + an->an_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; + /* + * ath_rate_node_init needs a vap pointer in node + * to decide which mgt rate to use + */ + an->an_node.ni_vap = vap; + sc->sc_rc->ops->node_init(sc, an); - DPRINTF(sc, ATH_DEBUG_NODE, "%s: an %p\n", __func__, an); - return &an->an_node; + /* U-APSD init */ + STAILQ_INIT(&an->an_uapsd_q); + an->an_uapsd_qdepth = 0; + STAILQ_INIT(&an->an_uapsd_overflowq); + an->an_uapsd_overflowqdepth = 0; + ATH_NODE_UAPSD_LOCK_INIT(an); + + DPRINTF(sc, ATH_DEBUG_NODE, "%s: an %p\n", __func__, an); + return &an->an_node; + } else { + return NULL; + } } static void @@ -4805,6 +4784,7 @@ struct ath_softc *sc = ni->ni_ic->ic_dev->priv; struct ath_node *an = ATH_NODE(ni); struct ath_buf *bf; + struct ieee80211_cb *cb = NULL; /* * U-APSD cleanup @@ -4819,15 +4799,18 @@ while (an->an_uapsd_qdepth) { bf = STAILQ_FIRST(&an->an_uapsd_q); STAILQ_REMOVE_HEAD(&an->an_uapsd_q, bf_list); - bf->bf_desc->ds_link = (u_int32_t)NULL; + cb = (struct ieee80211_cb *) bf->bf_skb->cb; + ieee80211_unref_node(&cb->ni); dev_kfree_skb_any(bf->bf_skb); + + bf->bf_desc->ds_link = 0; bf->bf_skb = NULL; bf->bf_node = NULL; + ATH_TXBUF_LOCK_IRQ(sc); STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list); ATH_TXBUF_UNLOCK_IRQ(sc); - ieee80211_free_node(ni); an->an_uapsd_qdepth--; } @@ -4835,19 +4818,25 @@ while (an->an_uapsd_overflowqdepth) { bf = STAILQ_FIRST(&an->an_uapsd_overflowq); STAILQ_REMOVE_HEAD(&an->an_uapsd_overflowq, bf_list); - bf->bf_desc->ds_link = (u_int32_t)NULL; + cb = (struct ieee80211_cb *) bf->bf_skb->cb; + ieee80211_unref_node(&cb->ni); dev_kfree_skb_any(bf->bf_skb); + bf->bf_skb = NULL; bf->bf_node = NULL; + bf->bf_desc->ds_link = 0; + ATH_TXBUF_LOCK_IRQ(sc); STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list); ATH_TXBUF_UNLOCK_IRQ(sc); - ieee80211_free_node(ni); an->an_uapsd_overflowqdepth--; } + // Clean up node-specific rate things - this currently appears to always be a no-op + sc->sc_rc->ops->node_cleanup(sc, ATH_NODE(ni)); + ATH_NODE_UAPSD_LOCK_IRQ(an); sc->sc_node_cleanup(ni); ATH_NODE_UAPSD_UNLOCK_IRQ(an); @@ -4858,7 +4847,6 @@ { struct ath_softc *sc = ni->ni_ic->ic_dev->priv; - sc->sc_rc->ops->node_cleanup(sc, ATH_NODE(ni)); sc->sc_node_free(ni); #ifdef ATH_SUPERG_XR ath_grppoll_period_update(sc); @@ -5741,7 +5729,7 @@ ATH_RSSI_LPF(an->an_avgrssi, ds->ds_rxstat.rs_rssi); type = ieee80211_input(ni, skb, ds->ds_rxstat.rs_rssi, ds->ds_rxstat.rs_tstamp); - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); } else { /* * No key index or no entry, do a lookup and @@ -5766,7 +5754,7 @@ if (keyix != IEEE80211_KEYIX_NONE && sc->sc_keyixmap[keyix] == NULL) sc->sc_keyixmap[keyix] = ieee80211_ref_node(ni); - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); } else type = ieee80211_input_all(ic, skb, ds->ds_rxstat.rs_rssi, @@ -6566,8 +6554,7 @@ STAILQ_REMOVE_HEAD(&an->an_uapsd_q, bf_list); dev_kfree_skb(lastbuf->bf_skb); lastbuf->bf_skb = NULL; - ieee80211_free_node(lastbuf->bf_node); - lastbuf->bf_node = NULL; + ieee80211_unref_node(&lastbuf->bf_node); ATH_TXBUF_LOCK_IRQ(sc); STAILQ_INSERT_TAIL(&sc->sc_txbuf, lastbuf, bf_list); ATH_TXBUF_UNLOCK_IRQ(sc); @@ -7318,7 +7305,7 @@ * this is a DEAUTH message that was sent and the * node was timed out due to inactivity. */ - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); } bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr, @@ -7566,7 +7553,7 @@ } #endif /* ATH_SUPERG_FF */ if (bf->bf_node) - ieee80211_free_node(bf->bf_node); + ieee80211_unref_node(&bf->bf_node); bf->bf_skb = NULL; bf->bf_node = NULL; diff -x foo/ -uNr -x .svn -x .o madwifi-ng/net80211/ieee80211_debug.h madwifi-ng-refcount/net80211/ieee80211_debug.h --- madwifi-ng/net80211/ieee80211_debug.h 1970-01-01 01:00:00.000000000 +0100 +++ madwifi-ng-refcount/net80211/ieee80211_debug.h 2007-02-07 12:13:54.901572000 +0100 @@ -0,0 +1,119 @@ +/*- + * Copyright (c) 2001 Atsushi Onoe + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id: ieee80211_var.h 1969 2007-01-16 03:05:18Z scottr $ + */ +#ifndef _NET80211_IEEE80211_DEBUG_H_ +#define _NET80211_IEEE80211_DEBUG_H_ + +#define IEEE80211_DEBUG +#define IEEE80211_DEBUG_REFCNT /* node refcnt stuff */ + +#include + +#define IEEE80211_MSG_DEBUG 0x40000000 /* IFF_DEBUG equivalent */ +#define IEEE80211_MSG_DUMPPKTS 0x20000000 /* IFF_LINK2 equivalent */ +#define IEEE80211_MSG_CRYPTO 0x10000000 /* crypto work */ +#define IEEE80211_MSG_INPUT 0x08000000 /* input handling */ +#define IEEE80211_MSG_XRATE 0x04000000 /* rate set handling */ +#define IEEE80211_MSG_ELEMID 0x02000000 /* element id parsing */ +#define IEEE80211_MSG_NODE 0x01000000 /* node handling */ +#define IEEE80211_MSG_ASSOC 0x00800000 /* association handling */ +#define IEEE80211_MSG_AUTH 0x00400000 /* authentication handling */ +#define IEEE80211_MSG_SCAN 0x00200000 /* scanning */ +#define IEEE80211_MSG_OUTPUT 0x00100000 /* output handling */ +#define IEEE80211_MSG_STATE 0x00080000 /* state machine */ +#define IEEE80211_MSG_POWER 0x00040000 /* power save handling */ +#define IEEE80211_MSG_DOT1X 0x00020000 /* 802.1x authenticator */ +#define IEEE80211_MSG_DOT1XSM 0x00010000 /* 802.1x state machine */ +#define IEEE80211_MSG_RADIUS 0x00008000 /* 802.1x radius client */ +#define IEEE80211_MSG_RADDUMP 0x00004000 /* dump 802.1x radius packets */ +#define IEEE80211_MSG_RADKEYS 0x00002000 /* dump 802.1x keys */ +#define IEEE80211_MSG_WPA 0x00001000 /* WPA/RSN protocol */ +#define IEEE80211_MSG_ACL 0x00000800 /* ACL handling */ +#define IEEE80211_MSG_WME 0x00000400 /* WME protocol */ +#define IEEE80211_MSG_SUPG 0x00000200 /* SUPERG */ +#define IEEE80211_MSG_DOTH 0x00000100 /* 11.h */ +#define IEEE80211_MSG_INACT 0x00000080 /* inactivity handling */ +#define IEEE80211_MSG_ROAM 0x00000040 /* sta-mode roaming */ + +#define IEEE80211_MSG_ANY 0xffffffff /* anything */ + +#ifdef IEEE80211_DEBUG +int ieee80211_msg_is_reported(struct ieee80211vap *, unsigned int msg); +#define IEEE80211_DPRINTF(_vap, _m, _fmt, ...) do { \ + if (ieee80211_msg_is_reported(_vap, _m)) \ + ieee80211_note(_vap, _fmt, __VA_ARGS__); \ +} while (0) +#define IEEE80211_NOTE(_vap, _m, _ni, _fmt, ...) do { \ + if (ieee80211_msg_is_reported(_vap, _m)) \ + ieee80211_note_mac(_vap, (_ni)->ni_macaddr, _fmt, __VA_ARGS__);\ +} while (0) +#define IEEE80211_NOTE_MAC(_vap, _m, _mac, _fmt, ...) do { \ + if (ieee80211_msg_is_reported(_vap, _m)) \ + ieee80211_note_mac(_vap, _mac, _fmt, __VA_ARGS__); \ +} while (0) +#define IEEE80211_NOTE_FRAME(_vap, _m, _wh, _fmt, ...) do { \ + if (ieee80211_msg_is_reported(_vap, _m)) \ + ieee80211_note_frame(_vap, _wh, _fmt, __VA_ARGS__); \ +} while (0) +struct ieee80211vap; +struct ieee80211_frame; +void ieee80211_note(struct ieee80211vap *, const char *, ...); +void ieee80211_note_mac(struct ieee80211vap *, + const u_int8_t mac[IEEE80211_ADDR_LEN], const char *, ...); +void ieee80211_note_frame(struct ieee80211vap *, + const struct ieee80211_frame *, const char *, ...); +#define ieee80211_msg_debug(_vap) \ + ieee80211_msg_is_reported(_vap, IEEE80211_MSG_DEBUG) +#define ieee80211_msg_dumppkts(_vap) \ + ieee80211_msg_is_reported(_vap, IEEE80211_MSG_DUMPPKTS) +#define ieee80211_msg_input(_vap) \ + ieee80211_msg_is_reported(_vap, IEEE80211_MSG_INPUT) +#define ieee80211_msg_radius(_vap) \ + ieee80211_msg_is_reported(_vap, IEEE80211_MSG_RADIUS) +#define ieee80211_msg_dumpradius(_vap) \ + ieee80211_msg_is_reported(_vap, IEEE80211_MSG_RADDUMP) +#define ieee80211_msg_dumpradkeys(_vap) \ + ieee80211_msg_is_reported(_vap, IEEE80211_MSG_RADKEYS) +#define ieee80211_msg_scan(_vap) \ + ieee80211_msg_is_reported(_vap, IEEE80211_MSG_SCAN) +#define ieee80211_msg_assoc(_vap) \ + ieee80211_msg_is_reported(_vap, IEEE80211_MSG_ASSOC) +#else /* IEEE80211_DEBUG */ +#define IEEE80211_DPRINTF(_vap, _m, _fmt, ...) +#define IEEE80211_NOTE(_vap, _m, _wh, _fmt, ...) +#define IEEE80211_NOTE_FRAME(_vap, _m, _wh, _fmt, ...) +#define IEEE80211_NOTE_MAC(_vap, _m, _mac, _fmt, ...) +#endif /* IEEE80211_DEBUG */ + +#endif /* _NET80211_IEEE80211_DEBUG_H_ */ + diff -x foo/ -uNr -x .svn -x .o madwifi-ng/net80211/ieee80211_input.c madwifi-ng-refcount/net80211/ieee80211_input.c --- madwifi-ng/net80211/ieee80211_input.c 2007-02-05 10:13:45.517292000 +0100 +++ madwifi-ng-refcount/net80211/ieee80211_input.c 2007-02-07 12:55:41.540368000 +0100 @@ -489,7 +489,7 @@ nt = &ic->ic_sta; ni_wds = ieee80211_find_wds_node(nt, wh->i_addr3); if (ni_wds) { - ieee80211_free_node(ni_wds); /* Decr ref count */ + ieee80211_unref_node(&ni_wds); /* Decr ref count */ IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, wh, NULL, "%s", "multicast echo originated from node behind me"); @@ -569,7 +569,7 @@ if (ni_wds == NULL) ieee80211_add_wds_addr(nt, ni, wh4->i_addr4, 0); else - ieee80211_free_node(ni_wds); /* Decr ref count */ + ieee80211_unref_node(&ni_wds); /* Decr ref count */ } /* @@ -928,7 +928,7 @@ } ni = ieee80211_ref_node(vap->iv_bss); type = ieee80211_input(ni, skb1, rssi, rstamp); - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); } if (skb != NULL) /* no vaps, reclaim skb */ dev_kfree_skb(skb); @@ -978,22 +978,14 @@ } /* - * Use this lock to make sure ni->ni_rxfrag is - * not freed by the timer process while we use it. - * XXX bogus - */ - IEEE80211_NODE_LOCK_IRQ(ni->ni_table); - - /* * Update the time stamp. As a side effect, it * also makes sure that the timer will not change * ni->ni_rxfrag for at least 1 second, or in * other words, for the remaining of this function. + * XXX HUGE HORRIFIC HACK */ ni->ni_rxfragstamp = jiffies; - IEEE80211_NODE_UNLOCK_IRQ(ni->ni_table); - /* * Validate that fragment is in order and * related to the previous ones. @@ -1122,7 +1114,7 @@ skb = NULL; } /* XXX statistic? */ - ieee80211_free_node(ni1); + ieee80211_unref_node(&ni1); } } if (skb1 != NULL) { @@ -1246,6 +1238,7 @@ int rssi, u_int32_t rstamp, u_int16_t seq, u_int16_t status) { struct ieee80211vap *vap = ni->ni_vap; + unsigned int tmpnode = 0; if (ni->ni_authmode == IEEE80211_AUTH_SHARED) { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH, @@ -1253,22 +1246,21 @@ "bad sta auth mode %u", ni->ni_authmode); vap->iv_stats.is_rx_bad_auth++; /* XXX maybe a unique error? */ if (vap->iv_opmode == IEEE80211_M_HOSTAP) { - /* XXX hack to workaround calling convention */ - - /* XXX To send the frame to the requesting STA, we have to - * create a node for the station that we're going to reject. - * The node will be freed automatically */ if (ni == vap->iv_bss) { - ni = ieee80211_dup_bss(vap, wh->i_addr2); + ni = ieee80211_dup_bss(vap, wh->i_addr2, 0); if (ni == NULL) return; IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, "%s: %p<%s> refcnt %d\n", __func__, ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)); + tmpnode = 1; } IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_AUTH, (seq + 1) | (IEEE80211_STATUS_ALG << 16)); + + if (tmpnode) + ieee80211_unref_node(&ni); return; } } @@ -1296,23 +1288,16 @@ } /* always accept open authentication requests */ if (ni == vap->iv_bss) { - ni = ieee80211_dup_bss(vap, wh->i_addr2); + ni = ieee80211_dup_bss(vap, wh->i_addr2, 0); if (ni == NULL) return; IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, "%s: %p<%s> refcnt %d\n", __func__, ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)); - - } else if ((ni->ni_flags & IEEE80211_NODE_AREF) == 0) - (void) ieee80211_ref_node(ni); - /* - * Mark the node as referenced to reflect that it's - * reference count has been bumped to ensure it remains - * after the transaction completes. - */ - ni->ni_flags |= IEEE80211_NODE_AREF; - + tmpnode = 1; + } + IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_AUTH, seq + 1); IEEE80211_NOTE(vap, IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH, ni, "station authenticated (%s)", "open"); @@ -1322,6 +1307,8 @@ */ if (ni->ni_authmode != IEEE80211_AUTH_8021X) ieee80211_node_authorize(ni); + if (tmpnode) + ieee80211_unref_node(&ni); break; case IEEE80211_M_STA: @@ -1360,7 +1347,7 @@ int istmp; if (ni == vap->iv_bss) { - ni = ieee80211_tmp_node(vap, mac); + ni = ieee80211_dup_bss(vap, mac, 1); if (ni == NULL) { /* XXX msg */ return; @@ -1370,7 +1357,7 @@ istmp = 0; IEEE80211_SEND_MGMT(ni, subtype, arg); if (istmp) - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); } static int @@ -1396,7 +1383,7 @@ { struct ieee80211vap *vap = ni->ni_vap; u_int8_t *challenge; - int allocbs, estatus; + int allocbs = 0, estatus = 0; /* * NB: this can happen as we allow pre-shared key @@ -1406,7 +1393,6 @@ * ordering in which case this check would just be * for sanity/consistency. */ - estatus = 0; /* NB: silence compiler */ if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH, ni->ni_macaddr, "shared key auth", @@ -1486,7 +1472,7 @@ switch (seq) { case IEEE80211_AUTH_SHARED_REQUEST: if (ni == vap->iv_bss) { - ni = ieee80211_dup_bss(vap, wh->i_addr2); + ni = ieee80211_dup_bss(vap, wh->i_addr2, 0); if (ni == NULL) { /* NB: no way to return an error */ return; @@ -1497,17 +1483,8 @@ ieee80211_node_refcnt(ni)); allocbs = 1; - } else { - if ((ni->ni_flags & IEEE80211_NODE_AREF) == 0) - (void) ieee80211_ref_node(ni); - allocbs = 0; } - /* - * Mark the node as referenced to reflect that it's - * reference count has been bumped to ensure it remains - * after the transaction completes. - */ - ni->ni_flags |= IEEE80211_NODE_AREF; + ni->ni_rssi = rssi; ni->ni_rstamp = rstamp; ni->ni_last_rx = jiffies; @@ -1601,14 +1578,13 @@ } return; bad: - /* - * Send an error response; but only when operating as an AP. - */ + /* Send an error response; but only when operating as an AP. */ if (vap->iv_opmode == IEEE80211_M_HOSTAP) { /* XXX hack to workaround calling convention */ ieee80211_send_error(ni, wh->i_addr2, IEEE80211_FC0_SUBTYPE_AUTH, (seq + 1) | (estatus<<16)); + ieee80211_node_leave(ni); } else if (vap->iv_opmode == IEEE80211_M_STA) { /* * Kick the state machine. This short-circuits @@ -2072,7 +2048,7 @@ /* optional RSN capabilities */ if (len > 2) rsn_parm->rsn_caps = LE_READ_2(frm); - /* XXXPMKID */ + /* XXX PMKID */ return 0; } @@ -2566,7 +2542,7 @@ u_int8_t *frm, *efrm; u_int8_t *ssid, *rates, *xrates, *wpa, *rsn, *wme, *ath; u_int8_t rate; - int reassoc, resp, allocbs; + int reassoc, resp, allocbs = 0; u_int8_t qosinfo; wh = (struct ieee80211_frame *) skb->data; @@ -2962,13 +2938,13 @@ ni = ieee80211_fakeup_adhoc_node(vap, wh->i_addr2); } else { - ni = ieee80211_tmp_node(vap, wh->i_addr2); + ni = ieee80211_dup_bss(vap, wh->i_addr2, 1); } if (ni == NULL) return; allocbs = 1; - } else - allocbs = 0; + } + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_INPUT, wh->i_addr2, "%s", "recv probe req"); ni->ni_rssi = rssi; @@ -2991,7 +2967,7 @@ * Temporary node created just to send a * response, reclaim immediately */ - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); } else if (ath != NULL) ieee80211_saveath(ni, ath); break; @@ -3021,6 +2997,9 @@ ni = vap->iv_xrvap->iv_bss; else { ieee80211_node_leave(ni); + /* This would be a stupid place to add a node to the table + * XR stuff needs work anyway + */ ieee80211_node_reset(ni, vap->iv_xrvap); } vap = vap->iv_xrvap; @@ -3033,9 +3012,7 @@ #endif IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_AUTH, wh->i_addr2, "recv auth frame with algorithm %d seq %d", algo, seq); - /* - * Consult the ACL policy module if setup. - */ + /* Consult the ACL policy module if setup. */ if (vap->iv_acl != NULL && !vap->iv_acl->iac_check(vap, wh->i_addr2)) { IEEE80211_DISCARD(vap, IEEE80211_MSG_ACL, @@ -3068,7 +3045,7 @@ /* XXX not right */ ieee80211_send_error(ni, wh->i_addr2, IEEE80211_FC0_SUBTYPE_AUTH, - (seq+1) | (IEEE80211_STATUS_ALG << 16)); + (seq + 1) | (IEEE80211_STATUS_ALG << 16)); } return; } diff -x foo/ -uNr -x .svn -x .o madwifi-ng/net80211/ieee80211_linux.h madwifi-ng-refcount/net80211/ieee80211_linux.h --- madwifi-ng/net80211/ieee80211_linux.h 2007-01-31 17:30:13.845519000 +0100 +++ madwifi-ng-refcount/net80211/ieee80211_linux.h 2007-02-07 12:13:56.788792000 +0100 @@ -63,6 +63,12 @@ #define IEEE80211_RESCHEDULE schedule +/* Locking */ +/* NB: beware, spin_is_locked() is not usefully defined for !(DEBUG || SMP) + * because spinlocks do not exist in this configuration. Instead IRQs + * or pre-emption are simply disabled, as this is all that is needed. + */ + /* * Beacon handler locking definitions. * Beacon locking @@ -85,14 +91,14 @@ #define IEEE80211_LOCK(_ic) spin_lock(&(_ic)->ic_comlock) #define IEEE80211_UNLOCK(_ic) spin_unlock(&(_ic)->ic_comlock) -/* NB: beware, spin_is_locked() is unusable for !SMP */ -#if defined(CONFIG_SMP) +#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked) #define IEEE80211_LOCK_ASSERT(_ic) \ KASSERT(spin_is_locked(&(_ic)->ic_comlock),("ieee80211com not locked!")) #else #define IEEE80211_LOCK_ASSERT(_ic) #endif + #define IEEE80211_VAPS_LOCK_INIT(_ic, _name) \ spin_lock_init(&(_ic)->ic_vapslock) #define IEEE80211_VAPS_LOCK_DESTROY(_ic) @@ -108,11 +114,10 @@ } while (0) #define IEEE80211_VAPS_UNLOCK_IRQ_EARLY(_ic) spin_unlock_irqrestore(&(_ic)->ic_vapslock, _vaps_lockflags) - -/* NB: beware, spin_is_locked() is unusable for !SMP */ -#if defined(CONFIG_SMP) +#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked) #define IEEE80211_VAPS_LOCK_ASSERT(_ic) \ - KASSERT(spin_is_locked(&(_ic)->ic_vapslock),("ieee80211com_vaps not locked!")) + KASSERT(spin_is_locked(&(_ic)->ic_vapslock), \ + ("ieee80211com_vaps not locked!")) #else #define IEEE80211_VAPS_LOCK_ASSERT(_ic) #endif @@ -121,29 +126,63 @@ /* * Node locking definitions. */ +#if 0 + typedef spinlock_t ieee80211_node_lock_t; -#define IEEE80211_NODE_LOCK_INIT(_nt, _name) spin_lock_init(&(_nt)->nt_nodelock) -#define IEEE80211_NODE_LOCK_DESTROY(_nt) -#define IEEE80211_NODE_LOCK(_nt) spin_lock(&(_nt)->nt_nodelock) -#define IEEE80211_NODE_UNLOCK(_nt) spin_unlock(&(_nt)->nt_nodelock) -#define IEEE80211_NODE_LOCK_BH(_nt) spin_lock_bh(&(_nt)->nt_nodelock) -#define IEEE80211_NODE_UNLOCK_BH(_nt) spin_unlock_bh(&(_nt)->nt_nodelock) -#define IEEE80211_NODE_LOCK_IRQ(_nt) do { \ +#define IEEE80211_NODE_LOCK_INIT(_ni, _name) spin_lock_init(&(_ni)->ni_nodelock) +#define IEEE80211_NODE_LOCK_DESTROY(_ni) +#if 0 /* We should always be contesting in the same contexts */ +#define IEEE80211_NODE_LOCK(_ni) spin_lock(&(_ni)->ni_nodelock) +#define IEEE80211_NODE_UNLOCK(_ni) spin_unlock(&(_ni)->ni_nodelock) +#define IEEE80211_NODE_LOCK_BH(_ni) spin_lock_bh(&(_ni)->ni_nodelock) +#define IEEE80211_NODE_UNLOCK_BH(_ni) spin_unlock_bh(&(_ni)->ni_nodelock) +#endif +#define IEEE80211_NODE_LOCK_IRQ(_ni) do { \ + unsigned long __node_lockflags; \ + spin_lock_irqsave(&(_ni)->ni_nodelock, __node_lockflags); +#define IEEE80211_NODE_UNLOCK_IRQ(_ni) \ + spin_unlock_irqrestore(&(_ni)->ni_nodelock, __node_lockflags); \ +} while(0) +#define IEEE80211_NODE_UNLOCK_IRQ_EARLY(_ni) \ + spin_unlock_irqrestore(&(_ni)->ni_nodelock, __node_lockflags); + +#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked) +#define IEEE80211_NODE_LOCK_ASSERT(_nt) \ + KASSERT(spin_is_locked(&(_ni)->ni_nodelock), \ + ("802.11 node not locked!")) +#else +#define IEEE80211_NODE_LOCK_ASSERT(_ni) +#endif + +#endif /* node lock */ + +/* + * Node table locking definitions. + */ +typedef spinlock_t ieee80211_node_table_lock_t; +#define IEEE80211_NODE_TABLE_LOCK_INIT(_nt, _name) spin_lock_init(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_TABLE_LOCK_DESTROY(_nt) +#if 0 /* We should always be contesting in the same contexts */ +#define IEEE80211_NODE_TABLE_LOCK(_nt) spin_lock(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_TABLE_UNLOCK(_nt) spin_unlock(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_TABLE_LOCK_BH(_nt) spin_lock_bh(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_TABLE_UNLOCK_BH(_nt) spin_unlock_bh(&(_nt)->nt_nodelock) +#endif +#define IEEE80211_NODE_TABLE_LOCK_IRQ(_nt) do { \ unsigned long __node_lockflags; \ spin_lock_irqsave(&(_nt)->nt_nodelock, __node_lockflags); -#define IEEE80211_NODE_UNLOCK_IRQ(_nt) \ +#define IEEE80211_NODE_TABLE_UNLOCK_IRQ(_nt) \ spin_unlock_irqrestore(&(_nt)->nt_nodelock, __node_lockflags); \ } while(0) -#define IEEE80211_NODE_UNLOCK_IRQ_EARLY(_nt) \ +#define IEEE80211_NODE_TABLE_UNLOCK_IRQ_EARLY(_nt) \ spin_unlock_irqrestore(&(_nt)->nt_nodelock, __node_lockflags); -/* NB: beware, *_is_locked() are bogusly defined for UP+!PREEMPT */ -#if (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)) && defined(spinlock_is_locked) -#define IEEE80211_NODE_LOCK_ASSERT(_nt) \ - KASSERT(spinlock_is_locked(&(_nt)->nt_nodelock), \ +#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked) +#define IEEE80211_NODE_TABLE_LOCK_ASSERT(_nt) \ + KASSERT(spin_is_locked(&(_nt)->nt_nodelock), \ ("802.11 node table not locked!")) #else -#define IEEE80211_NODE_LOCK_ASSERT(_nt) +#define IEEE80211_NODE_TABLE_LOCK_ASSERT(_nt) #endif /* @@ -163,8 +202,7 @@ #define IEEE80211_SCAN_UNLOCK_IRQ_EARLY(_nt) \ spin_unlock_irqrestore(&(_nt)->nt_scanlock, __scan_lockflags); -/* NB: beware, spin_is_locked() is unusable for !SMP */ -#if defined(CONFIG_SMP) +#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked) #define IEEE80211_SCAN_LOCK_ASSERT(_nt) \ KASSERT(spin_is_locked(&(_nt)->nt_scanlock), ("scangen not locked!")) #else @@ -182,8 +220,7 @@ #define ACL_LOCK_BH(_as) spin_lock_bh(&(_as)->as_lock) #define ACL_UNLOCK_BH(_as) spin_unlock_bh(&(_as)->as_lock) -/* NB: beware, spin_is_locked() is unusable for !SMP */ -#if defined(CONFIG_SMP) +#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked) #define ACL_LOCK_ASSERT(_as) \ KASSERT(spin_is_locked(&(_as)->as_lock), ("ACL not locked!")) #else @@ -299,6 +336,7 @@ * is the last reference, otherwise 0 * ieee80211_node_refcnt reference count for printing (only) */ +typedef atomic_t ieee80211_node_ref_count_t; #define ieee80211_node_initref(_ni) atomic_set(&(_ni)->ni_refcnt, 1) #define ieee80211_node_incref(_ni) atomic_inc(&(_ni)->ni_refcnt) #define ieee80211_node_decref(_ni) atomic_dec(&(_ni)->ni_refcnt) @@ -379,8 +417,8 @@ /* msecs_to_jiffies appeared in 2.6.7 and 2.4.29 */ #include #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7)) || \ - LINUX_VERSION_CODE < KERNEL_VERSION(2,4,29) + LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7)) || \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,4,29) /* The following definitions and inline functions are * copied from the kernel src, include/linux/jiffies.h */ diff -x foo/ -uNr -x .svn -x .o madwifi-ng/net80211/ieee80211_node.c madwifi-ng-refcount/net80211/ieee80211_node.c --- madwifi-ng/net80211/ieee80211_node.c 2007-02-07 11:32:15.749860000 +0100 +++ madwifi-ng-refcount/net80211/ieee80211_node.c 2007-02-07 13:27:08.868804000 +0100 @@ -65,16 +65,17 @@ #define IEEE80211_AID_ISSET(_vap, _b) \ ((_vap)->iv_aid_bitmap[IEEE80211_AID(_b) / 32] & (1 << (IEEE80211_AID(_b) % 32))) +static struct ieee80211_node *ieee80211_alloc_node(struct ieee80211vap *, const u_int8_t *); + static int ieee80211_sta_join1(struct ieee80211_node *); -static struct ieee80211_node *node_alloc(struct ieee80211_node_table *, - struct ieee80211vap *); +static struct ieee80211_node *node_alloc(struct ieee80211vap *); static void node_cleanup(struct ieee80211_node *); static void node_free(struct ieee80211_node *); static u_int8_t node_getrssi(const struct ieee80211_node *); -static void _ieee80211_free_node(struct ieee80211_node *); -static void node_reclaim(struct ieee80211_node_table *, struct ieee80211_node*); +static void _node_table_leave(struct ieee80211_node_table *, struct ieee80211_node *); +static void _node_table_join(struct ieee80211_node_table *, struct ieee80211_node *); static void ieee80211_node_timeout(unsigned long); @@ -194,8 +195,7 @@ ieee80211_node_table_reset(&ic->ic_sta, vap); if (vap->iv_bss != NULL) { - ieee80211_free_node(vap->iv_bss); - vap->iv_bss = NULL; + ieee80211_unref_node(&vap->iv_bss); } if (vap->iv_aid_bitmap != NULL) { FREE(vap->iv_aid_bitmap, M_DEVBUF); @@ -263,17 +263,17 @@ "%s: creating ibss on channel %u\n", __func__, ieee80211_chan2ieee(ic, chan)); - /* Check to see if we already have a node for this mac */ + /* Check to see if we already have a node for this mac + * NB: we gain a node reference here + */ ni = ieee80211_find_node(&ic->ic_sta, vap->iv_myaddr); if (ni == NULL) { - ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr); + ni = ieee80211_alloc_node_table(vap, vap->iv_myaddr); if (ni == NULL) { /* XXX recovery? */ return; } } - else - ieee80211_free_node(ni); IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, "%s: %p<%s> refcnt %d\n", __func__, vap->iv_bss, ether_sprintf(vap->iv_bss->ni_macaddr), @@ -345,7 +345,7 @@ else if (IEEE80211_IS_CHAN_QUARTER(chan)) ni->ni_rates = ic->ic_sup_quarter_rates; - (void) ieee80211_sta_join1(ieee80211_ref_node(ni)); + (void) ieee80211_sta_join1(PASS_NODE(ni)); } EXPORT_SYMBOL(ieee80211_create_ibss); @@ -369,9 +369,10 @@ /* XXX multi-bss wrong */ ieee80211_reset_erp(ic, ic->ic_curmode); - ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr); + ni = ieee80211_alloc_node_table(vap, vap->iv_myaddr); KASSERT(ni != NULL, ("unable to setup inital BSS node")); obss = vap->iv_bss; + // Caller's reference vap->iv_bss = ieee80211_ref_node(ni); IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, "%s: new bss %p<%s> refcnt %d\n", @@ -381,7 +382,8 @@ if (obss != NULL) { copy_bss(ni, obss); ni->ni_intval = ic->ic_lintval; - ieee80211_free_node(obss); + // Caller's reference + ieee80211_unref_node(&obss); } } @@ -587,7 +589,7 @@ vap->iv_state == IEEE80211_S_RUN && ssid_equal(obss, selbs)); vap->iv_bss = selbs; if (obss != NULL) - ieee80211_free_node(obss); + ieee80211_unref_node(&obss); ic->ic_bsschan = selbs->ni_chan; ic->ic_curchan = ic->ic_bsschan; ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan); @@ -644,19 +646,18 @@ ni = ieee80211_find_node(&ic->ic_sta, se->se_macaddr); if (ni == NULL) { - ni = ieee80211_alloc_node(&ic->ic_sta, vap, se->se_macaddr); + ni = ieee80211_alloc_node_table(vap, se->se_macaddr); if (ni == NULL) { /* XXX msg */ return 0; } - } else - ieee80211_free_node(ni); + } /* * Expand scan state into node's format. * XXX may not need all this stuff */ - ni->ni_authmode = vap->iv_bss->ni_authmode; /* inherit authmode from iv_bss */ + ni->ni_authmode = vap->iv_bss->ni_authmode; /* inherit authmode from iv_bss */ /* inherit the WPA setup as well (structure copy!) */ ni->ni_rsn = vap->iv_bss->ni_rsn; IEEE80211_ADDR_COPY(ni->ni_bssid, se->se_bssid); @@ -690,9 +691,9 @@ IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, "%s: %p<%s> refcnt %d\n", __func__, ni, ether_sprintf(ni->ni_macaddr), - ieee80211_node_refcnt(ni)+1); + ieee80211_node_refcnt(ni)); - return ieee80211_sta_join1(ieee80211_ref_node(ni)); + return ieee80211_sta_join1(PASS_NODE(ni)); } EXPORT_SYMBOL(ieee80211_sta_join); @@ -704,15 +705,13 @@ ieee80211_sta_leave(struct ieee80211_node *ni) { struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211com *ic = vap->iv_ic; /* WDS/Repeater: Stop software beacon timer for STA */ if (vap->iv_opmode == IEEE80211_M_STA && vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) { del_timer(&vap->iv_swbmiss); } - - ic->ic_node_cleanup(ni); + ieee80211_notify_node_leave(ni); } @@ -721,11 +720,11 @@ */ static void -ieee80211_node_table_init(struct ieee80211com *ic, - struct ieee80211_node_table *nt, const char *name, int inact) +ieee80211_node_table_init(struct ieee80211com *ic, struct ieee80211_node_table *nt, + const char *name, int inact) { nt->nt_ic = ic; - IEEE80211_NODE_LOCK_INIT(nt, ic->ic_dev->name); + IEEE80211_NODE_TABLE_LOCK_INIT(nt, ic->ic_dev->name); IEEE80211_SCAN_LOCK_INIT(nt, ic->ic_dev->name); TAILQ_INIT(&nt->nt_node); nt->nt_name = name; @@ -737,8 +736,31 @@ mod_timer(&nt->nt_wds_aging_timer, jiffies + HZ * WDS_AGING_TIMER_VAL); } +static __inline void _node_table_join(struct ieee80211_node_table *nt, struct ieee80211_node *ni) { + IEEE80211_NODE_TABLE_LOCK_ASSERT(nt); + + ni->ni_table = nt; + TAILQ_INSERT_TAIL(&nt->nt_node, ieee80211_ref_node(ni), ni_list); + LIST_INSERT_HEAD(&nt->nt_hash[IEEE80211_NODE_HASH(ni->ni_macaddr)], ni, ni_hash); +} + +static __inline void _node_table_leave(struct ieee80211_node_table *nt, struct ieee80211_node *ni) { + struct ieee80211_node *hni; + IEEE80211_NODE_TABLE_LOCK_ASSERT(nt); + + TAILQ_REMOVE(&nt->nt_node, ni, ni_list); + LIST_FOREACH(hni, &nt->nt_hash[IEEE80211_NODE_HASH(ni->ni_macaddr)], ni_hash) { + LIST_REMOVE(ni, ni_hash); + } + ni->ni_table = NULL; + _ieee80211_unref_node(ni); +} + +/* This is overridden by ath_node_alloc in ath/if_ath.c, and so + * should never get called. + */ static struct ieee80211_node * -node_alloc(struct ieee80211_node_table *nt, struct ieee80211vap *vap) +node_alloc(struct ieee80211vap *vap) { struct ieee80211_node *ni; @@ -777,13 +799,6 @@ IEEE80211_UNLOCK_IRQ(ni->ni_ic); } } - /* - * Clear AREF flag that marks the authorization refcnt bump - * has happened. This is probably not needed as the node - * should always be removed from the table so not found but - * do it just in case. - */ - ni->ni_flags &= ~IEEE80211_NODE_AREF; /* * Drain power save queue and, if needed, clear TIM. @@ -792,10 +807,7 @@ vap->iv_set_tim(ni, 0); ni->ni_associd = 0; - if (ni->ni_challenge != NULL) { - FREE(ni->ni_challenge, M_DEVBUF); - ni->ni_challenge = NULL; - } + /* * Preserve SSID, WPA, and WME ie's so the bss node is * reusable during a re-auth/re-assoc state transition. @@ -820,9 +832,16 @@ static void node_free(struct ieee80211_node *ni) { +#if 0 + // We should 'cleanup' and then free'ing should be done automatically on decref struct ieee80211com *ic = ni->ni_ic; ic->ic_node_cleanup(ni); +#endif + KASSERT(ieee80211_node_refcnt(ni) == 0, ("node being free whilst still referenced")); + + if (ni->ni_challenge != NULL) + FREE(ni->ni_challenge, M_DEVBUF); if (ni->ni_wpa_ie != NULL) FREE(ni->ni_wpa_ie, M_DEVBUF); if (ni->ni_rsn_ie != NULL) @@ -832,6 +851,7 @@ if (ni->ni_ath_ie != NULL) FREE(ni->ni_ath_ie, M_DEVBUF); IEEE80211_NODE_SAVEQ_DESTROY(ni); + FREE(ni, M_80211_NODE); } @@ -848,55 +868,70 @@ * This interface is not intended for general use, it is * used by the routines below to create entries with a * specific purpose. + * Dont assume a BSS? */ struct ieee80211_node * -ieee80211_alloc_node(struct ieee80211_node_table *nt, - struct ieee80211vap *vap, const u_int8_t *macaddr) +ieee80211_alloc_node_table(struct ieee80211vap *vap, + const u_int8_t *macaddr) { - struct ieee80211com *ic = nt->nt_ic; + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_node_table *nt = &ic->ic_sta; struct ieee80211_node *ni; - int hash; - ni = ic->ic_node_alloc(nt, vap); - if (ni == NULL) { - /* XXX msg */ - vap->iv_stats.is_rx_nodealloc++; - return NULL; - } + ni = ieee80211_alloc_node(vap, macaddr); + if (ni != NULL) { + ni->ni_inact = ni->ni_inact_reload = nt->nt_inact_init; - IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, - "%s: %p<%s> in %s table, refcnt %d\n", __func__, ni, - ether_sprintf(macaddr), nt->nt_name, - ieee80211_node_refcnt(ni)+1); + WME_UAPSD_NODE_TRIGSEQINIT(ni); + IEEE80211_NODE_SAVEQ_INIT(ni, "unknown"); - IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr); - hash = IEEE80211_NODE_HASH(macaddr); - ieee80211_node_initref(ni); /* mark referenced */ - ni->ni_chan = IEEE80211_CHAN_ANYC; - ni->ni_authmode = IEEE80211_AUTH_OPEN; - ni->ni_txpower = ic->ic_txpowlimit; /* max power */ - ieee80211_crypto_resetkey(vap, &ni->ni_ucastkey, IEEE80211_KEYIX_NONE); - ni->ni_inact_reload = nt->nt_inact_init; - ni->ni_inact = ni->ni_inact_reload; - ni->ni_ath_defkeyindex = IEEE80211_INVAL_DEFKEY; - ni->ni_rxkeyoff = 0; - IEEE80211_NODE_SAVEQ_INIT(ni, "unknown"); + IEEE80211_NODE_TABLE_LOCK_IRQ(nt); + _node_table_join(nt, ni); + IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); + } - IEEE80211_NODE_LOCK_IRQ(nt); - ni->ni_vap = vap; - ni->ni_ic = ic; - ni->ni_table = nt; - TAILQ_INSERT_TAIL(&nt->nt_node, ni, ni_list); - LIST_INSERT_HEAD(&nt->nt_hash[hash], ni, ni_hash); - ni->ni_rxfrag = NULL; - ni->ni_challenge = NULL; - IEEE80211_NODE_UNLOCK_IRQ(nt); + return ni; +} +EXPORT_SYMBOL(ieee80211_alloc_node_table); + +/* Allocate a node structure and initialise specialised structures + * This function does not add the node to the node table, thus this + * node will not be found using ieee80211_find_*node. + * This is useful when sending one off errors or request denials. + */ +static struct ieee80211_node * +ieee80211_alloc_node(struct ieee80211vap *vap, const u_int8_t *macaddr) +{ + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_node *ni; + + /* This always allocates zeroed memoery */ + ni = ic->ic_node_alloc(vap); + if (ni != NULL) { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, + "%s: %p<%s> refcnt %d\n", __func__, ni, ether_sprintf(macaddr), + ieee80211_node_refcnt(ni)+1); - WME_UAPSD_NODE_TRIGSEQINIT(ni); + ieee80211_node_initref(ni); /* mark referenced */ + + IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr); + + ni->ni_chan = IEEE80211_CHAN_ANYC; + ni->ni_authmode = IEEE80211_AUTH_OPEN; + ni->ni_txpower = ic->ic_txpowlimit; + + ieee80211_crypto_resetkey(vap, &ni->ni_ucastkey, + IEEE80211_KEYIX_NONE); + ni->ni_ath_defkeyindex = IEEE80211_INVAL_DEFKEY; + ni->ni_vap = vap; + ni->ni_ic = ic; + } else { + /* XXX msg */ + vap->iv_stats.is_rx_nodealloc++; + } return ni; } -EXPORT_SYMBOL(ieee80211_alloc_node); /* Add wds address to the node table */ int @@ -918,11 +953,11 @@ wds->wds_agingcount = WDS_AGING_COUNT; hash = IEEE80211_NODE_HASH(macaddr); IEEE80211_ADDR_COPY(wds->wds_macaddr, macaddr); - ieee80211_ref_node(ni); /* Reference node */ - wds->wds_ni = ni; - IEEE80211_NODE_LOCK_IRQ(nt); + + IEEE80211_NODE_TABLE_LOCK_IRQ(nt); + wds->wds_ni = ieee80211_ref_node(ni); LIST_INSERT_HEAD(&nt->nt_wds_hash[hash], wds, wds_hash); - IEEE80211_NODE_UNLOCK_IRQ(nt); + IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); return 0; } EXPORT_SYMBOL(ieee80211_add_wds_addr); @@ -935,18 +970,16 @@ struct ieee80211_wds_addr *wds; hash = IEEE80211_NODE_HASH(macaddr); - IEEE80211_NODE_LOCK_IRQ(nt); + IEEE80211_NODE_TABLE_LOCK_IRQ(nt); LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) { if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) { - if (ieee80211_node_dectestref(wds->wds_ni)) { - _ieee80211_free_node(wds->wds_ni); - LIST_REMOVE(wds, wds_hash); - FREE(wds, M_80211_WDS); - break; - } + LIST_REMOVE(wds, wds_hash); + ieee80211_unref_node(&wds->wds_ni); + FREE(wds, M_80211_WDS); + break; } } - IEEE80211_NODE_UNLOCK_IRQ(nt); + IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); } EXPORT_SYMBOL(ieee80211_remove_wds_addr); @@ -958,19 +991,17 @@ int hash; struct ieee80211_wds_addr *wds; - IEEE80211_NODE_LOCK_IRQ(nt); + IEEE80211_NODE_TABLE_LOCK_IRQ(nt); for (hash = 0; hash < IEEE80211_NODE_HASHSIZE; hash++) { LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) { if (wds->wds_ni == ni) { - if (ieee80211_node_dectestref(ni)) { - _ieee80211_free_node(ni); - LIST_REMOVE(wds, wds_hash); - FREE(wds, M_80211_WDS); - } + LIST_REMOVE(wds, wds_hash); + ieee80211_unref_node(&wds->wds_ni); + FREE(wds, M_80211_WDS); } } } - IEEE80211_NODE_UNLOCK_IRQ(nt); + IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); } EXPORT_SYMBOL(ieee80211_del_wds_node); @@ -981,88 +1012,46 @@ int hash; struct ieee80211_wds_addr *wds; - IEEE80211_NODE_LOCK_IRQ(nt); + IEEE80211_NODE_TABLE_LOCK_IRQ(nt); for (hash = 0; hash < IEEE80211_NODE_HASHSIZE; hash++) { LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) { if (wds->wds_agingcount != WDS_AGING_STATIC) { if (!wds->wds_agingcount) { - if (ieee80211_node_dectestref(wds->wds_ni)) { - _ieee80211_free_node(wds->wds_ni); - LIST_REMOVE(wds, wds_hash); - FREE(wds, M_80211_WDS); - } + LIST_REMOVE(wds, wds_hash); + ieee80211_unref_node(&wds->wds_ni); + FREE(wds, M_80211_WDS); } else wds->wds_agingcount--; } } } - IEEE80211_NODE_UNLOCK_IRQ(nt); + IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); mod_timer(&nt->nt_wds_aging_timer, jiffies + HZ * WDS_AGING_TIMER_VAL); } /* - * Craft a temporary node suitable for sending a management frame - * to the specified station. We craft only as much state as we - * need to do the work since the node will be immediately reclaimed - * once the send completes. - */ -struct ieee80211_node * -ieee80211_tmp_node(struct ieee80211vap *vap, const u_int8_t *macaddr) -{ - struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_node *ni; - - ni = ic->ic_node_alloc(&ic->ic_sta,vap); - if (ni != NULL) { - IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, - "%s: %p<%s> refcnt %d\n", __func__, ni, ether_sprintf(macaddr), - ieee80211_node_refcnt(ni)+1); - - IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr); - IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_bss->ni_bssid); - ieee80211_node_initref(ni); /* mark referenced */ - ni->ni_txpower = vap->iv_bss->ni_txpower; - ni->ni_vap = vap; - /* NB: required by ieee80211_fix_rate */ - ieee80211_node_set_chan(ic, ni); - ieee80211_crypto_resetkey(vap, &ni->ni_ucastkey, - IEEE80211_KEYIX_NONE); - /* XXX optimize away */ - IEEE80211_NODE_SAVEQ_INIT(ni, "unknown"); - - ni->ni_table = NULL; /* NB: pedantic */ - ni->ni_ic = ic; - ni->ni_rxfrag = NULL; - ni->ni_challenge = NULL; - } else { - /* XXX msg */ - vap->iv_stats.is_rx_nodealloc++; - } - return ni; -} - -/* * Add the specified station to the station table. */ struct ieee80211_node * -ieee80211_dup_bss(struct ieee80211vap *vap, const u_int8_t *macaddr) +ieee80211_dup_bss(struct ieee80211vap *vap, const u_int8_t *macaddr, + unsigned char tmp) { - struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node *ni; + + // HACK + if (tmp) + ni = ieee80211_alloc_node(vap, macaddr); + else + ni = ieee80211_alloc_node_table(vap, macaddr); - ni = ieee80211_alloc_node(&ic->ic_sta, vap, macaddr); if (ni != NULL) { - /* - * Inherit from iv_bss. - */ - ni->ni_authmode = vap->iv_bss->ni_authmode; - ni->ni_txpower = vap->iv_bss->ni_txpower; - ni->ni_vlan = vap->iv_bss->ni_vlan; /* XXX?? */ + copy_bss(ni, vap->iv_bss); IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_bss->ni_bssid); - ieee80211_node_set_chan(ic, ni); - ni->ni_rsn = vap->iv_bss->ni_rsn; - ni->ni_rxfrag = NULL; + /* Do this only for nodes that already have a BSS. Otherwise + * ic_bsschan is not set and we get a KASSERT failure. + * Required by ieee80211_fix_rate */ + ieee80211_node_set_chan(vap->iv_ic, ni); } return ni; } @@ -1070,19 +1059,16 @@ static struct ieee80211_node * _ieee80211_find_wds_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr) { - struct ieee80211_node *ni; struct ieee80211_wds_addr *wds; int hash; - IEEE80211_NODE_LOCK_ASSERT(nt); + IEEE80211_NODE_TABLE_LOCK_ASSERT(nt); hash = IEEE80211_NODE_HASH(macaddr); LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) { if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) { - ni = wds->wds_ni; if (wds->wds_agingcount != WDS_AGING_STATIC) wds->wds_agingcount = WDS_AGING_COUNT; /* reset the aging count */ - ieee80211_ref_node(ni); - return ni; + return ieee80211_ref_node(wds->wds_ni); } } return NULL; @@ -1100,7 +1086,7 @@ int hash; struct ieee80211_wds_addr *wds; - IEEE80211_NODE_LOCK_ASSERT(nt); + IEEE80211_NODE_TABLE_LOCK_ASSERT(nt); hash = IEEE80211_NODE_HASH(macaddr); LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) { @@ -1121,9 +1107,7 @@ nodes. */ LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) { if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) { - ni = wds->wds_ni; - ieee80211_ref_node(ni); - return ni; + return ieee80211_ref_node(wds->wds_ni); } } return NULL; @@ -1138,9 +1122,9 @@ { struct ieee80211_node *ni; - IEEE80211_NODE_LOCK_IRQ(nt); + IEEE80211_NODE_TABLE_LOCK_IRQ(nt); ni = _ieee80211_find_wds_node(nt, macaddr); - IEEE80211_NODE_UNLOCK_IRQ(nt); + IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); return ni; } EXPORT_SYMBOL(ieee80211_find_wds_node); @@ -1155,9 +1139,9 @@ { struct ieee80211_node *ni; - IEEE80211_NODE_LOCK_IRQ(nt); + IEEE80211_NODE_TABLE_LOCK_IRQ(nt); ni = _ieee80211_find_node(nt, macaddr); - IEEE80211_NODE_UNLOCK_IRQ(nt); + IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); return ni; } #ifdef IEEE80211_DEBUG_REFCNT @@ -1180,7 +1164,7 @@ { struct ieee80211_node *ni; - ni = ieee80211_dup_bss(vap, macaddr); + ni = ieee80211_dup_bss(vap, macaddr, 0); if (ni != NULL) { /* XXX no rate negotiation; just dup */ ni->ni_rates = vap->iv_bss->ni_rates; @@ -1203,14 +1187,13 @@ * driver has an opportunity to setup it's private state. */ struct ieee80211_node * -ieee80211_add_neighbor(struct ieee80211vap *vap, const struct ieee80211_frame *wh, +ieee80211_add_neighbor(struct ieee80211vap *vap, const struct ieee80211_frame *wh, const struct ieee80211_scanparams *sp) { struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node *ni; - ni = ieee80211_dup_bss(vap, wh->i_addr2); /* XXX alloc_node? */ - /* TODO: not really putting itself in a table */ + ni = ieee80211_dup_bss(vap, wh->i_addr2, 1); if (ni != NULL) { ni->ni_esslen = sp->ssid[1]; memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]); @@ -1285,12 +1268,12 @@ /* XXX check ic_bss first in station mode */ /* XXX 4-address frames? */ nt = &ic->ic_sta; - IEEE80211_NODE_LOCK_IRQ(nt); + IEEE80211_NODE_TABLE_LOCK_IRQ(nt); if (IS_CTL(wh) && !IS_PSPOLL(wh) /*&& !IS_RTS(ah)*/) ni = _ieee80211_find_node(nt, wh->i_addr1); else ni = _ieee80211_find_node(nt, wh->i_addr2); - IEEE80211_NODE_UNLOCK_IRQ(nt); + IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); return ni; #undef IS_PSPOLL @@ -1327,9 +1310,9 @@ /* XXX can't hold lock across dup_bss due to recursive locking */ nt = &vap->iv_ic->ic_sta; - IEEE80211_NODE_LOCK_IRQ(nt); + IEEE80211_NODE_TABLE_LOCK_IRQ(nt); ni = _ieee80211_find_node(nt, mac); - IEEE80211_NODE_UNLOCK_IRQ(nt); + IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); if (ni == NULL) { if (vap->iv_opmode == IEEE80211_M_IBSS || @@ -1356,11 +1339,9 @@ EXPORT_SYMBOL(ieee80211_find_txnode); #endif -/* Caller must lock the IEEE80211_NODE_LOCK - * - * Context: hwIRQ, softIRQ and process context +/* Context: hwIRQ, softIRQ and process context */ -static void +void _ieee80211_free_node(struct ieee80211_node *ni) { struct ieee80211vap *vap = ni->ni_vap; @@ -1374,90 +1355,10 @@ if (vap->iv_aid_bitmap != NULL) IEEE80211_AID_CLR(vap, ni->ni_associd); - if (nt != NULL) { - TAILQ_REMOVE(&nt->nt_node, ni, ni_list); - LIST_REMOVE(ni, ni_hash); - } - vap->iv_ic->ic_node_free(ni); -} -void -#ifdef IEEE80211_DEBUG_REFCNT -ieee80211_free_node_debug(struct ieee80211_node *ni, const char *func, int line) -#else -ieee80211_free_node(struct ieee80211_node *ni) -#endif -{ - struct ieee80211_node_table *nt = ni->ni_table; - struct ieee80211com *ic = ni->ni_ic; - -#ifdef IEEE80211_DEBUG_REFCNT - IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE, - "%s (%s:%u) %p<%s> refcnt %d\n", __func__, func, line, ni, - ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni) - 1); -#endif - /* - * XXX: may need to lock out the following race. we dectestref - * and determine it's time to free the node. between the if() - * and lock, we take an rx intr to receive a frame from this - * node. the rx path (tasklet or intr) bumps this node's - * refcnt and xmits a response frame. eventually that response - * will get reaped, and the reaping code will attempt to use - * the node. the code below will delete the node prior - * to the reap and we could get a crash. - * - * as a stopgap before delving deeper, lock intrs to - * prevent this case. - */ - IEEE80211_LOCK_IRQ(ic); - if (ieee80211_node_dectestref(ni)) { - /* - * Beware; if the node is marked gone then it's already - * been removed from the table and we cannot assume the - * table still exists. Regardless, there's no need to lock - * the table. - */ - if (ni->ni_table != NULL) { - IEEE80211_NODE_LOCK(nt); - _ieee80211_free_node(ni); - IEEE80211_NODE_UNLOCK(nt); - } else - _ieee80211_free_node(ni); - } - IEEE80211_UNLOCK_IRQ(ic); -} -#ifdef IEEE80211_DEBUG_REFCNT -EXPORT_SYMBOL(ieee80211_free_node_debug); -#else -EXPORT_SYMBOL(ieee80211_free_node); -#endif - -/* - * 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. - */ -static void -node_reclaim(struct ieee80211_node_table *nt, struct ieee80211_node *ni) -{ - - IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE, - "%s: remove %p<%s> from %s table, refcnt %d\n", - __func__, ni, ether_sprintf(ni->ni_macaddr), - nt->nt_name, ieee80211_node_refcnt(ni)-1); - if (!ieee80211_node_dectestref(ni)) { - /* - * Other references are present, just remove the - * node from the table so it cannot be found. When - * the references are dropped storage will be - * reclaimed. This normally only happens for ic_bss. - */ - TAILQ_REMOVE(&nt->nt_node, ni, ni_list); - LIST_REMOVE(ni, ni_hash); - ni->ni_table = NULL; /* clear reference */ - } else - _ieee80211_free_node(ni); + vap->iv_ic->ic_node_free(ni); } +EXPORT_SYMBOL(_ieee80211_free_node); static void ieee80211_node_table_reset(struct ieee80211_node_table *nt, @@ -1465,7 +1366,7 @@ { struct ieee80211_node *ni, *next; - IEEE80211_NODE_LOCK_IRQ(nt); + IEEE80211_NODE_TABLE_LOCK_IRQ(nt); TAILQ_FOREACH_SAFE(ni, &nt->nt_node, ni_list, next) { if (match != NULL && ni->ni_vap != match) continue; @@ -1477,14 +1378,15 @@ if (vap->iv_aid_bitmap != NULL) IEEE80211_AID_CLR(vap, ni->ni_associd); } - node_reclaim(nt, ni); + ieee80211_node_leave(ni); } - IEEE80211_NODE_UNLOCK_IRQ(nt); + IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); } static void ieee80211_node_table_cleanup(struct ieee80211_node_table *nt) { + struct ieee80211com *ic = nt->nt_ic; struct ieee80211_node *ni, *next; TAILQ_FOREACH_SAFE(ni, &nt->nt_node, ni_list, next) { @@ -1496,11 +1398,11 @@ if (vap->iv_aid_bitmap != NULL) IEEE80211_AID_CLR(vap, ni->ni_associd); } - node_reclaim(nt, ni); + ic->ic_node_cleanup(ni); } del_timer(&nt->nt_wds_aging_timer); IEEE80211_SCAN_LOCK_DESTROY(nt); - IEEE80211_NODE_LOCK_DESTROY(nt); + IEEE80211_NODE_TABLE_LOCK_DESTROY(nt); } /* @@ -1528,19 +1430,22 @@ IEEE80211_SCAN_LOCK_IRQ(nt); gen = ++nt->nt_scangen; restart: - IEEE80211_NODE_LOCK_IRQ(nt); + IEEE80211_NODE_TABLE_LOCK_IRQ(nt); TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { if (ni->ni_scangen == gen) /* previously handled */ continue; + /* Temporary entries should no longer be in the node table */ /* * Ignore entries for which have yet to receive an * authentication frame. These are transient and * will be reclaimed when the last reference to them * goes away (when frame xmits complete). */ - if (ic->ic_opmode == IEEE80211_M_HOSTAP && - (ni->ni_flags & IEEE80211_NODE_AREF) == 0) - continue; + /* + *if (ic->ic_opmode == IEEE80211_M_HOSTAP && + * (ni->ni_flags & IEEE80211_NODE_AREF) == 0) + * continue; + */ ni->ni_scangen = gen; /* * Free fragment if not needed anymore @@ -1592,7 +1497,7 @@ * ref for us as needed. */ ieee80211_ref_node(ni); - IEEE80211_NODE_UNLOCK_IRQ_EARLY(nt); + IEEE80211_NODE_TABLE_UNLOCK_IRQ_EARLY(nt); ieee80211_send_nulldata(ni); /* XXX stat? */ goto restart; @@ -1615,18 +1520,18 @@ */ ni->ni_vap->iv_stats.is_node_timeout++; ieee80211_ref_node(ni); - IEEE80211_NODE_UNLOCK_IRQ_EARLY(nt); + IEEE80211_NODE_TABLE_UNLOCK_IRQ_EARLY(nt); if (ni->ni_associd != 0) { IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DEAUTH, IEEE80211_REASON_AUTH_EXPIRE); } ieee80211_node_leave(ni); - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); goto restart; } } - IEEE80211_NODE_UNLOCK_IRQ(nt); + IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); IEEE80211_SCAN_UNLOCK_IRQ(nt); } @@ -1656,26 +1561,29 @@ void ieee80211_iterate_dev_nodes(struct net_device *dev, struct ieee80211_node_table *nt, ieee80211_iter_func *f, void *arg) { - struct ieee80211_node *ni; + struct ieee80211_node *tni, *ni; u_int gen; IEEE80211_SCAN_LOCK_IRQ(nt); gen = ++nt->nt_scangen; restart: - IEEE80211_NODE_LOCK(nt); - TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { - if (dev != NULL && ni->ni_vap->iv_dev != dev) + IEEE80211_NODE_TABLE_LOCK_IRQ(nt); + TAILQ_FOREACH(tni, &nt->nt_node, ni_list) { + if (dev != NULL && tni->ni_vap->iv_dev != dev) continue; /* skip node not for this vap */ - if (ni->ni_scangen != gen) { - ni->ni_scangen = gen; - (void) ieee80211_ref_node(ni); - IEEE80211_NODE_UNLOCK(nt); + if (tni->ni_scangen != gen) { + tni->ni_scangen = gen; + + ni = ieee80211_ref_node(tni); + IEEE80211_NODE_TABLE_UNLOCK_IRQ_EARLY(nt); + (*f)(arg, ni); - ieee80211_free_node(ni); + + ieee80211_unref_node(&ni); goto restart; } } - IEEE80211_NODE_UNLOCK(nt); + IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); IEEE80211_SCAN_UNLOCK_IRQ(nt); } @@ -1684,7 +1592,6 @@ void ieee80211_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)); @@ -1949,9 +1856,20 @@ "station with aid %d leaves (refcnt %u)", IEEE80211_NODE_AID(ni), ieee80211_node_refcnt(ni)); + /* 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(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) @@ -1969,9 +1887,11 @@ 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--; @@ -1982,6 +1902,7 @@ 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 @@ -1991,19 +1912,10 @@ 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); + * Run a cleanup and then drop the caller's reference + */ + ic->ic_node_cleanup(ni); + ieee80211_unref_node(&ni); } EXPORT_SYMBOL(ieee80211_node_leave); @@ -2063,25 +1975,8 @@ void ieee80211_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); - } - } + 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; } diff -x foo/ -uNr -x .svn -x .o madwifi-ng/net80211/ieee80211_node.h madwifi-ng-refcount/net80211/ieee80211_node.h --- madwifi-ng/net80211/ieee80211_node.h 2007-02-07 11:32:15.833656000 +0100 +++ madwifi-ng-refcount/net80211/ieee80211_node.h 2007-02-07 12:55:41.713905000 +0100 @@ -52,14 +52,14 @@ * authorized. The latter timeout is shorter to more aggressively * reclaim nodes that leave part way through the 802.1x exchange. */ -#define IEEE80211_INACT_WAIT 15 /* inactivity interval (secs) */ +#define IEEE80211_INACT_WAIT 15 /* inactivity interval (secs) */ #define IEEE80211_INACT_INIT (30/IEEE80211_INACT_WAIT) /* initial */ #define IEEE80211_INACT_AUTH (180/IEEE80211_INACT_WAIT) /* associated but not authorized */ #define IEEE80211_INACT_RUN (300/IEEE80211_INACT_WAIT) /* authorized */ #define IEEE80211_INACT_PROBE (30/IEEE80211_INACT_WAIT) /* probe */ #define IEEE80211_INACT_SCAN (300/IEEE80211_INACT_WAIT) /* scanned */ -#define IEEE80211_TRANS_WAIT 5 /* mgt frame tx timer (secs) */ +#define IEEE80211_TRANS_WAIT 5 /* mgt frame tx timer (secs) */ #define IEEE80211_NODE_HASHSIZE 32 /* simple hash is enough for variation of macaddr */ @@ -94,7 +94,8 @@ struct ieee80211_node_table *ni_table; TAILQ_ENTRY(ieee80211_node) ni_list; LIST_ENTRY(ieee80211_node) ni_hash; - atomic_t ni_refcnt; + // ieee80211_node_lock_t ni_nodelock; /* on node - notably for ref counting */ + ieee80211_node_ref_count_t ni_refcnt; u_int ni_scangen; /* gen# for timeout scan */ u_int8_t ni_authmode; /* authentication algorithm */ u_int16_t ni_flags; /* special-purpose state */ @@ -121,13 +122,13 @@ u_int16_t ni_associd; /* assoc response */ u_int16_t ni_txpower; /* current transmit power (in 0.5 dBm) */ u_int16_t ni_vlan; /* vlan tag */ - u_int32_t *ni_challenge; /* shared-key challenge */ + u_int32_t *ni_challenge; /* shared-key challenge */ u_int8_t *ni_wpa_ie; /* captured WPA ie */ u_int8_t *ni_rsn_ie; /* captured RSN ie */ u_int8_t *ni_wme_ie; /* captured WME ie */ u_int8_t *ni_ath_ie; /* captured Atheros ie */ - u_int16_t ni_txseqs[17]; /* tx seq per-tid */ - u_int16_t ni_rxseqs[17]; /* rx seq previous per-tid*/ + u_int16_t ni_txseqs[17]; /* tx seq per-tid */ + u_int16_t ni_rxseqs[17]; /* rx seq previous per-tid*/ u_int32_t ni_rxfragstamp; /* time stamp of last rx frag */ struct sk_buff *ni_rxfrag; /* rx frag reassembly */ struct ieee80211_rsnparms ni_rsn; /* RSN/WPA parameters */ @@ -156,7 +157,7 @@ struct ieee80211_channel *ni_chan; u_int16_t ni_fhdwell; /* FH only */ u_int8_t ni_fhindex; /* FH only */ - u_int8_t ni_erp; /* ERP from beacon/probe resp */ + u_int8_t ni_erp; /* ERP from beacon/probe resp */ u_int16_t ni_timoff; /* byte offset to TIM ie */ /* others */ @@ -168,7 +169,7 @@ struct ieee80211vap *ni_prev_vap; /* previously associated vap */ u_int8_t ni_uapsd; /* U-APSD per-node flags matching WMM STA Qos Info field */ u_int8_t ni_uapsd_maxsp; /* maxsp from flags above */ - u_int16_t ni_uapsd_trigseq[WME_NUM_AC]; /* trigger suppression on retry */ + u_int16_t ni_uapsd_trigseq[WME_NUM_AC]; /* trigger suppression on retry */ __le16 ni_pschangeseq; }; MALLOC_DECLARE(M_80211_NODE); @@ -186,20 +187,6 @@ #define WME_UAPSD_NODE_INVALIDSEQ 0xffff #define WME_UAPSD_NODE_TRIGSEQINIT(_ni) (memset(&(_ni)->ni_uapsd_trigseq[0], 0xff, sizeof((_ni)->ni_uapsd_trigseq))) -static __inline struct ieee80211_node * -ieee80211_ref_node(struct ieee80211_node *ni) -{ - ieee80211_node_incref(ni); - return ni; -} - -static __inline void -ieee80211_unref_node(struct ieee80211_node **ni) -{ - ieee80211_node_decref(*ni); - *ni = NULL; /* guard against use */ -} - void ieee80211_node_attach(struct ieee80211com *); void ieee80211_node_detach(struct ieee80211com *); void ieee80211_node_vattach(struct ieee80211vap *); @@ -242,43 +229,39 @@ * is a second table for associated stations or neighbors. */ struct ieee80211_node_table { + const char *nt_name; /* for debugging */ struct ieee80211com *nt_ic; /* back reference */ - ieee80211_node_lock_t nt_nodelock; /* on node table */ + ieee80211_node_table_lock_t nt_nodelock; /* on node table */ TAILQ_HEAD(, ieee80211_node) nt_node; /* information of all nodes */ ATH_LIST_HEAD(, ieee80211_node) nt_hash[IEEE80211_NODE_HASHSIZE]; ATH_LIST_HEAD(, ieee80211_wds_addr) nt_wds_hash[IEEE80211_NODE_HASHSIZE]; - const char *nt_name; /* for debugging */ ieee80211_scan_lock_t nt_scanlock; /* on nt_scangen */ u_int nt_scangen; /* gen# for timeout scan */ int nt_inact_init; /* initial node inact setting */ struct timer_list nt_wds_aging_timer; /* timer to age out wds entries */ }; -struct ieee80211_node *ieee80211_alloc_node(struct ieee80211_node_table *, - struct ieee80211vap *, const u_int8_t *); -struct ieee80211_node *ieee80211_tmp_node(struct ieee80211vap *, - const u_int8_t *); -struct ieee80211_node *ieee80211_dup_bss(struct ieee80211vap *, +struct ieee80211_node *ieee80211_alloc_node_table(struct ieee80211vap *, const u_int8_t *); +struct ieee80211_node *ieee80211_dup_bss(struct ieee80211vap *, + const u_int8_t *, unsigned char); void ieee80211_node_reset(struct ieee80211_node *, struct ieee80211vap *); #ifdef IEEE80211_DEBUG_REFCNT -void ieee80211_free_node_debug(struct ieee80211_node *, const char *, int); struct ieee80211_node *ieee80211_find_node_debug(struct ieee80211_node_table *, const u_int8_t *, const char *, int); struct ieee80211_node *ieee80211_find_rxnode_debug(struct ieee80211com *, const struct ieee80211_frame_min *, const char *, int); struct ieee80211_node *ieee80211_find_txnode_debug(struct ieee80211vap *, const u_int8_t *, const char *, int); -#define ieee80211_free_node(ni) \ - ieee80211_free_node_debug(ni, __func__, __LINE__) -#define ieee80211_find_node(nt, mac) \ - ieee80211_find_node_debug(nt, mac, __func__, __LINE__) -#define ieee80211_find_rxnode(nt, wh) \ - ieee80211_find_rxnode_debug(nt, wh, __func__, __LINE__) -#define ieee80211_find_txnode(nt, mac) \ - ieee80211_find_txnode_debug(nt, mac, __func__, __LINE__) +#define ieee80211_unref_node(_ni) \ + ieee80211_unref_node_debug(_ni, __func__, __LINE__) +#define ieee80211_find_node(_nt, _mac) \ + ieee80211_find_node_debug(_nt, _mac, __func__, __LINE__) +#define ieee80211_find_rxnode(_nt, _wh) \ + ieee80211_find_rxnode_debug(_nt, _wh, __func__, __LINE__) +#define ieee80211_find_txnode(_nt, _mac) \ + ieee80211_find_txnode_debug(_nt, _mac, __func__, __LINE__) #else -void ieee80211_free_node(struct ieee80211_node *); struct ieee80211_node *ieee80211_find_node(struct ieee80211_node_table *, const u_int8_t *); @@ -287,6 +270,53 @@ struct ieee80211_node *ieee80211_find_txnode(struct ieee80211vap *, const u_int8_t *); #endif + +void _ieee80211_free_node(struct ieee80211_node *); + +static __inline struct ieee80211_node * +ieee80211_ref_node(struct ieee80211_node *ni) +{ + ieee80211_node_incref(ni); + return ni; +} + +static __inline struct ieee80211_node * +_ieee80211_pass_node(struct ieee80211_node **pni) { + struct ieee80211_node *tmp = *pni; + *pni = NULL; + return (tmp); +} + +#define PASS_NODE(_ni) \ + _ieee80211_pass_node(&_ni) + +static __inline int +_ieee80211_unref_node(struct ieee80211_node *ni) { + if (ieee80211_node_dectestref(ni)) { + _ieee80211_free_node(ni); + return 1; + } else { + return 0; + } +} + +static __inline void +#ifdef IEEE80211_DEBUG_REFCNT +ieee80211_unref_node_debug(struct ieee80211_node **pni, const char *func, int line) +#else +ieee80211_unref_node(struct ieee80211_node **pni) +#endif +{ + struct ieee80211_node *ni = *pni; +#ifdef IEEE80211_DEBUG_REFCNT + IEEE80211_DPRINTF(NULL, IEEE80211_MSG_NODE, + "%s (%s:%u) %p<%s> refcnt %d\n", __func__, func, line, ni, + ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni) - 1); +#endif + _ieee80211_unref_node(ni); + *pni = NULL; /* guard against use */ +} + int ieee80211_add_wds_addr(struct ieee80211_node_table *, struct ieee80211_node *, const u_int8_t *, u_int8_t); void ieee80211_remove_wds_addr(struct ieee80211_node_table *, const u_int8_t *); diff -x foo/ -uNr -x .svn -x .o madwifi-ng/net80211/ieee80211_output.c madwifi-ng-refcount/net80211/ieee80211_output.c --- madwifi-ng/net80211/ieee80211_output.c 2007-02-06 16:32:36.619628000 +0100 +++ madwifi-ng-refcount/net80211/ieee80211_output.c 2007-02-07 12:44:01.545153000 +0100 @@ -254,7 +254,7 @@ goto bad; } - cb->ni = ni; + cb->ni = ieee80211_ref_node(ni); /* power-save checks */ if (WME_UAPSD_AC_CAN_TRIGGER(skb->priority, ni)) { @@ -293,13 +293,14 @@ } #endif ieee80211_parent_queue_xmit(skb); + ieee80211_unref_node(&ni); return 0; bad: if (skb != NULL) dev_kfree_skb(skb); if (ni != NULL) - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); return 0; } @@ -453,7 +454,7 @@ if (skb == NULL) { /* XXX debug msg */ vap->iv_stats.is_tx_nobuf++; - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); return -ENOMEM; } cb = (struct ieee80211_cb *)skb->cb; @@ -507,16 +508,14 @@ u_int8_t *frm; int tid; - ieee80211_ref_node(ni); skb = ieee80211_getmgtframe(&frm, 2); if (skb == NULL) { /* XXX debug msg */ vap->iv_stats.is_tx_nobuf++; - ieee80211_free_node(ni); return -ENOMEM; } cb = (struct ieee80211_cb *)skb->cb; - cb->ni = ni; + cb->ni = ieee80211_ref_node(ni); skb->priority = ac; qwh = (struct ieee80211_qosframe *)skb_push(skb, sizeof(struct ieee80211_qosframe)); @@ -865,7 +864,7 @@ nt = &ic->ic_sta; ni_wds = ieee80211_find_wds_node(nt, eh.ether_shost); if (ni_wds) - ieee80211_free_node(ni_wds); /* Decr ref count */ + ieee80211_unref_node(&ni_wds); /* Decr ref count */ else ieee80211_add_wds_addr(nt, ni, eh.ether_shost, 0); } @@ -1719,7 +1718,6 @@ __func__, __LINE__, ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni) + 1); - ieee80211_ref_node(ni); /* * prreq frame format @@ -1735,7 +1733,6 @@ vap->app_ie[IEEE80211_APPIE_FRAME_PROBE_REQ].length); if (skb == NULL) { vap->iv_stats.is_tx_nobuf++; - ieee80211_free_node(ni); return -ENOMEM; } @@ -1758,7 +1755,7 @@ skb_trim(skb, frm - skb->data); cb = (struct ieee80211_cb *)skb->cb; - cb->ni = ni; + cb->ni = ieee80211_ref_node(ni); wh = (struct ieee80211_frame *) skb_push(skb, sizeof(struct ieee80211_frame)); @@ -2233,7 +2230,7 @@ mod_timer(&vap->iv_mgtsend, jiffies + timer * HZ); return 0; bad: - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); return ret; #undef senderr } diff -x foo/ -uNr -x .svn -x .o madwifi-ng/net80211/ieee80211_power.c madwifi-ng-refcount/net80211/ieee80211_power.c --- madwifi-ng/net80211/ieee80211_power.c 2006-10-04 11:12:34.705966000 +0200 +++ madwifi-ng-refcount/net80211/ieee80211_power.c 2007-02-07 12:13:56.247707000 +0100 @@ -109,13 +109,15 @@ int ieee80211_node_saveq_drain(struct ieee80211_node *ni) { + struct ieee80211_cb *cb = NULL; struct sk_buff *skb; int qlen; IEEE80211_NODE_SAVEQ_LOCK(ni); qlen = skb_queue_len(&ni->ni_savedq); while ((skb = __skb_dequeue(&ni->ni_savedq)) != NULL) { - ieee80211_free_node(ni); + cb = (struct ieee80211_cb *) skb->cb; + ieee80211_unref_node(&cb->ni); dev_kfree_skb_any(skb); } IEEE80211_NODE_SAVEQ_UNLOCK(ni); diff -x foo/ -uNr -x .svn -x .o madwifi-ng/net80211/ieee80211_proto.c madwifi-ng-refcount/net80211/ieee80211_proto.c --- madwifi-ng/net80211/ieee80211_proto.c 2006-12-12 13:23:23.031787000 +0100 +++ madwifi-ng-refcount/net80211/ieee80211_proto.c 2007-02-07 12:13:56.698929000 +0100 @@ -1456,7 +1456,7 @@ */ if (vap->iv_opmode == IEEE80211_M_WDS) { struct ieee80211_node *wds_ni; - wds_ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->wds_mac); + wds_ni = ieee80211_alloc_node_table(vap, vap->wds_mac); if (wds_ni != NULL) { if (ieee80211_add_wds_addr(&ic->ic_sta, wds_ni, vap->wds_mac, 1) == 0) { ieee80211_node_authorize(wds_ni); diff -x foo/ -uNr -x .svn -x .o madwifi-ng/net80211/ieee80211_scan_sta.c madwifi-ng-refcount/net80211/ieee80211_scan_sta.c --- madwifi-ng/net80211/ieee80211_scan_sta.c 2006-10-04 11:12:33.408688000 +0200 +++ madwifi-ng-refcount/net80211/ieee80211_scan_sta.c 2007-02-07 12:13:55.006918000 +0100 @@ -762,7 +762,7 @@ if (se->se_rssi < STA_RSSI_MIN) fail |= 0x100; #ifdef IEEE80211_DEBUG - if (ieee80211_msg(vap, IEEE80211_MSG_SCAN | IEEE80211_MSG_ROAM)) { + if (ieee80211_msg_is_reported(vap, IEEE80211_MSG_SCAN | IEEE80211_MSG_ROAM)) { printf(" %03x", fail); printf(" %c %s", fail & 0x40 ? '=' : fail & 0x80 ? '^' : fail ? '-' : '+', diff -x foo/ -uNr -x .svn -x .o madwifi-ng/net80211/ieee80211_var.h madwifi-ng-refcount/net80211/ieee80211_var.h --- madwifi-ng/net80211/ieee80211_var.h 2007-01-31 17:30:13.664441000 +0100 +++ madwifi-ng-refcount/net80211/ieee80211_var.h 2007-02-07 12:13:56.416113000 +0100 @@ -37,8 +37,7 @@ /* * Definitions for IEEE 802.11 drivers. */ -#define IEEE80211_DEBUG -#undef IEEE80211_DEBUG_REFCNT /* node refcnt stuff */ +#include #include @@ -230,8 +229,7 @@ /* new station association callback/notification */ void (*ic_newassoc)(struct ieee80211_node *, int); /* node state management */ - struct ieee80211_node *(*ic_node_alloc)(struct ieee80211_node_table *, - struct ieee80211vap *); + struct ieee80211_node *(*ic_node_alloc)(struct ieee80211vap *); void (*ic_node_free)(struct ieee80211_node *); void (*ic_node_cleanup)(struct ieee80211_node *); u_int8_t (*ic_node_getrssi)(const struct ieee80211_node *); @@ -406,6 +404,12 @@ u_int32_t app_filter; /* filters which management frames are forwarded to app */ }; + +static __inline int ieee80211_is_printed(struct ieee80211vap *vap, unsigned m) +{ + return !!(vap->iv_debug & m); +} + MALLOC_DECLARE(M_80211_VAP); #define IEEE80211_ADDR_NULL(a1) (memcmp(a1, "\x00\x00\x00\x00\x00\x00", \ @@ -613,79 +617,4 @@ size = roundup(size, sizeof(u_int32_t)); return size; } - -#define IEEE80211_MSG_DEBUG 0x40000000 /* IFF_DEBUG equivalent */ -#define IEEE80211_MSG_DUMPPKTS 0x20000000 /* IFF_LINK2 equivalent */ -#define IEEE80211_MSG_CRYPTO 0x10000000 /* crypto work */ -#define IEEE80211_MSG_INPUT 0x08000000 /* input handling */ -#define IEEE80211_MSG_XRATE 0x04000000 /* rate set handling */ -#define IEEE80211_MSG_ELEMID 0x02000000 /* element id parsing */ -#define IEEE80211_MSG_NODE 0x01000000 /* node handling */ -#define IEEE80211_MSG_ASSOC 0x00800000 /* association handling */ -#define IEEE80211_MSG_AUTH 0x00400000 /* authentication handling */ -#define IEEE80211_MSG_SCAN 0x00200000 /* scanning */ -#define IEEE80211_MSG_OUTPUT 0x00100000 /* output handling */ -#define IEEE80211_MSG_STATE 0x00080000 /* state machine */ -#define IEEE80211_MSG_POWER 0x00040000 /* power save handling */ -#define IEEE80211_MSG_DOT1X 0x00020000 /* 802.1x authenticator */ -#define IEEE80211_MSG_DOT1XSM 0x00010000 /* 802.1x state machine */ -#define IEEE80211_MSG_RADIUS 0x00008000 /* 802.1x radius client */ -#define IEEE80211_MSG_RADDUMP 0x00004000 /* dump 802.1x radius packets */ -#define IEEE80211_MSG_RADKEYS 0x00002000 /* dump 802.1x keys */ -#define IEEE80211_MSG_WPA 0x00001000 /* WPA/RSN protocol */ -#define IEEE80211_MSG_ACL 0x00000800 /* ACL handling */ -#define IEEE80211_MSG_WME 0x00000400 /* WME protocol */ -#define IEEE80211_MSG_SUPG 0x00000200 /* SUPERG */ -#define IEEE80211_MSG_DOTH 0x00000100 /* 11.h */ -#define IEEE80211_MSG_INACT 0x00000080 /* inactivity handling */ -#define IEEE80211_MSG_ROAM 0x00000040 /* sta-mode roaming */ - -#define IEEE80211_MSG_ANY 0xffffffff /* anything */ - -#ifdef IEEE80211_DEBUG -#define ieee80211_msg(_vap, _m) ((_vap)->iv_debug & (_m)) -#define IEEE80211_DPRINTF(_vap, _m, _fmt, ...) do { \ - if (ieee80211_msg(_vap, _m)) \ - ieee80211_note(_vap, _fmt, __VA_ARGS__); \ -} while (0) -#define IEEE80211_NOTE(_vap, _m, _ni, _fmt, ...) do { \ - if (ieee80211_msg(_vap, _m)) \ - ieee80211_note_mac(_vap, (_ni)->ni_macaddr, _fmt, __VA_ARGS__);\ -} while (0) -#define IEEE80211_NOTE_MAC(_vap, _m, _mac, _fmt, ...) do { \ - if (ieee80211_msg(_vap, _m)) \ - ieee80211_note_mac(_vap, _mac, _fmt, __VA_ARGS__); \ -} while (0) -#define IEEE80211_NOTE_FRAME(_vap, _m, _wh, _fmt, ...) do { \ - if (ieee80211_msg(_vap, _m)) \ - ieee80211_note_frame(_vap, _wh, _fmt, __VA_ARGS__); \ -} while (0) -void ieee80211_note(struct ieee80211vap *, const char *, ...); -void ieee80211_note_mac(struct ieee80211vap *, - const u_int8_t mac[IEEE80211_ADDR_LEN], const char *, ...); -void ieee80211_note_frame(struct ieee80211vap *, - const struct ieee80211_frame *, const char *, ...); -#define ieee80211_msg_debug(_vap) \ - ieee80211_msg(_vap, IEEE80211_MSG_DEBUG) -#define ieee80211_msg_dumppkts(_vap) \ - ieee80211_msg(_vap, IEEE80211_MSG_DUMPPKTS) -#define ieee80211_msg_input(_vap) \ - ieee80211_msg(_vap, IEEE80211_MSG_INPUT) -#define ieee80211_msg_radius(_vap) \ - ieee80211_msg(_vap, IEEE80211_MSG_RADIUS) -#define ieee80211_msg_dumpradius(_vap) \ - ieee80211_msg(_vap, IEEE80211_MSG_RADDUMP) -#define ieee80211_msg_dumpradkeys(_vap) \ - ieee80211_msg(_vap, IEEE80211_MSG_RADKEYS) -#define ieee80211_msg_scan(_vap) \ - ieee80211_msg(_vap, IEEE80211_MSG_SCAN) -#define ieee80211_msg_assoc(_vap) \ - ieee80211_msg(_vap, IEEE80211_MSG_ASSOC) -#else /* IEEE80211_DEBUG */ -#define IEEE80211_DPRINTF(_vap, _m, _fmt, ...) -#define IEEE80211_NOTE(_vap, _m, _wh, _fmt, ...) -#define IEEE80211_NOTE_FRAME(_vap, _m, _wh, _fmt, ...) -#define IEEE80211_NOTE_MAC(_vap, _m, _mac, _fmt, ...) -#endif /* IEEE80211_DEBUG */ - #endif /* _NET80211_IEEE80211_VAR_H_ */ diff -x foo/ -uNr -x .svn -x .o madwifi-ng/net80211/ieee80211_wireless.c madwifi-ng-refcount/net80211/ieee80211_wireless.c --- madwifi-ng/net80211/ieee80211_wireless.c 2007-02-07 11:32:16.051231000 +0100 +++ madwifi-ng-refcount/net80211/ieee80211_wireless.c 2007-02-07 13:30:06.772974000 +0100 @@ -3179,7 +3179,7 @@ error = -ENXIO; ieee80211_key_update_end(vap); if (ni != NULL) - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); #ifdef ATH_SUPERG_XR /* set the same params on the xr vap device if exists */ if (vap->iv_xrvap && !(vap->iv_flags & IEEE80211_F_XR)) @@ -3239,7 +3239,7 @@ memset(ik.ik_keydata, 0, sizeof(ik.ik_keydata)); } if (ni != NULL) - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); return (copy_to_user(iwr->u.data.pointer, &ik, sizeof(ik)) ? -EFAULT : 0); } @@ -3262,7 +3262,7 @@ return -EINVAL; /* XXX */ /* XXX error return */ ieee80211_crypto_delkey(vap, &ni->ni_ucastkey, ni); - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); } else { if (kid >= IEEE80211_WEP_NKID) return -EINVAL; @@ -3365,7 +3365,7 @@ return -EINVAL; if (dev == ni->ni_vap->iv_dev) domlme(mlme, ni); - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); } else ieee80211_iterate_dev_nodes(dev, &ic->ic_sta, domlme, mlme); break; @@ -3384,7 +3384,7 @@ ieee80211_node_authorize(ni); else ieee80211_node_unauthorize(ni); - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); break; case IEEE80211_MLME_CLEAR_STATS: if (vap->iv_opmode != IEEE80211_M_HOSTAP) @@ -3395,7 +3395,7 @@ /* clear statistics */ memset(&ni->ni_stats, 0, sizeof(struct ieee80211_nodestats)); - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); break; default: return -EINVAL; @@ -3765,7 +3765,7 @@ ielen = sizeof(wpaie.rsn_ie); memcpy(wpaie.rsn_ie, ni->ni_rsn_ie, ielen); } - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); return (copy_to_user(iwr->u.data.pointer, &wpaie, sizeof(wpaie)) ? -EFAULT : 0); } @@ -3792,7 +3792,7 @@ /* NB: copy out only the statistics */ error = copy_to_user(iwr->u.data.pointer + off, &ni->ni_stats, iwr->u.data.length - off); - ieee80211_free_node(ni); + ieee80211_unref_node(&ni); return (error ? -EFAULT : 0); }