Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/net80211 Add ieee80211_find_rxnode and its helper ieee80...
details: https://anonhg.NetBSD.org/src/rev/d83d8ae239c2
branches: trunk
changeset: 554560:d83d8ae239c2
user: dyoung <dyoung%NetBSD.org@localhost>
date: Wed Oct 29 21:50:57 2003 +0000
description:
Add ieee80211_find_rxnode and its helper ieee80211_needs_rxnode.
802.11 drivers will use ieee80211_find_rxnode to match each received
packet with the ieee80211_node belonging to the sender. The driver
will use the ieee80211_node to track the sender's RSSI and other
statistics for, e.g., rate adaptation.
ieee80211_find_rxnode "fakes-up" missing ieee80211_nodes in IBSS
mode and in ad-hoc demo mode when it is appropriate. See the comments
in the source.
Also add ieee80211_find_txnode, which looks up the ieee80211_node
belonging to a MAC destination. ieee80211_find_txnode will also
fake-up missing nodes in IBSS/ad-hoc demo mode.
In ieee80211_encap, use ieee80211_find_txnode. This fixes the bug
in ad hoc packet-transmission reported by Greg Troxel, Urban Boquist,
and Kurt Schreiner.
diffstat:
sys/net80211/ieee80211_node.c | 141 +++++++++++++++++++++++++++++++++++++++-
sys/net80211/ieee80211_node.h | 6 +-
sys/net80211/ieee80211_output.c | 24 +-----
3 files changed, 149 insertions(+), 22 deletions(-)
diffs (227 lines):
diff -r 9057daf85c60 -r d83d8ae239c2 sys/net80211/ieee80211_node.c
--- a/sys/net80211/ieee80211_node.c Wed Oct 29 21:44:41 2003 +0000
+++ b/sys/net80211/ieee80211_node.c Wed Oct 29 21:50:57 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ieee80211_node.c,v 1.6 2003/10/15 11:43:51 dyoung Exp $ */
+/* $NetBSD: ieee80211_node.c,v 1.7 2003/10/29 21:50:57 dyoung Exp $ */
/*-
* Copyright (c) 2001 Atsushi Onoe
* Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
@@ -35,7 +35,7 @@
#ifdef __FreeBSD__
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_node.c,v 1.6 2003/08/19 22:17:03 sam Exp $");
#else
-__KERNEL_RCSID(0, "$NetBSD: ieee80211_node.c,v 1.6 2003/10/15 11:43:51 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ieee80211_node.c,v 1.7 2003/10/29 21:50:57 dyoung Exp $");
#endif
#include "opt_inet.h"
@@ -526,6 +526,143 @@
return ni;
}
+struct ieee80211_node *
+ieee80211_find_txnode(struct ieee80211com *ic, u_int8_t *macaddr)
+{
+ struct ieee80211_node *ni;
+ ieee80211_node_critsec_decl(s);
+
+ /*
+ * The destination address should be in the node table
+ * unless this is a multicast/broadcast frames or we are
+ * in station mode.
+ */
+ if (IEEE80211_IS_MULTICAST(macaddr) ||
+ ic->ic_opmode == IEEE80211_M_STA)
+ ni = ic->ic_bss;
+ else {
+ ieee80211_node_critsec_begin(ic, s);
+ ni = ieee80211_find_node(ic, macaddr);
+ if (ni == NULL) {
+ if (ic->ic_opmode != IEEE80211_M_MONITOR)
+ ni = ieee80211_dup_bss(ic, macaddr);
+ IEEE80211_DPRINTF(("%s: faked-up node %p for %s\n",
+ __func__, ni, ether_sprintf(macaddr)));
+ if (ni == NULL) {
+ ieee80211_node_critsec_end(ic, s);
+ /* ic->ic_stats.st_tx_nonode++; XXX statistic */
+ return NULL;
+ }
+ (void)ieee80211_ref_node(ni);
+ }
+ ieee80211_node_critsec_end(ic, s);
+ }
+ return ni;
+}
+
+/*
+ * For some types of packet and for some operating modes, it is
+ * desirable to process a Rx packet using its sender's node-record
+ * instead of the BSS record, when that is possible.
+ *
+ * - AP mode: it is desirable to keep a node-record for every
+ * authenticated/associated station *in the BSS*. For future use,
+ * we also track neighboring APs, since they might belong to the
+ * same ESSID.
+ *
+ * - IBSS mode: it is desirable to keep a node-record for every
+ * station *in the BSS*.
+ *
+ * - monitor mode: it is desirable to keep a node-record for every
+ * sender, regardless of BSS.
+ *
+ * - STA mode: the only available node-record is the BSS record,
+ * ic->ic_bss.
+ *
+ * Of all the 802.11 Control packets, only the node-records for
+ * RTS packets node-record can be looked up.
+ *
+ * Return non-zero if the packet's node-record is kept, zero
+ * otherwise.
+ */
+static __inline int
+ieee80211_needs_rxnode(struct ieee80211com *ic, struct ieee80211_frame *wh,
+ u_int8_t **bssid)
+{
+ struct ieee80211_node *bss = ic->ic_bss;
+ int needsnode, rc = 0;
+
+ if (ic->ic_opmode == IEEE80211_M_STA)
+ return 0;
+
+ needsnode = (ic->ic_opmode == IEEE80211_M_MONITOR);
+
+ *bssid = NULL;
+
+ switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
+ case IEEE80211_FC0_TYPE_CTL:
+ return (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
+ IEEE80211_FC0_SUBTYPE_RTS;
+
+ case IEEE80211_FC0_TYPE_MGT:
+ *bssid = wh->i_addr3;
+ rc = IEEE80211_ADDR_EQ(*bssid, bss->ni_bssid);
+ break;
+ case IEEE80211_FC0_TYPE_DATA:
+ switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
+ case IEEE80211_FC1_DIR_NODS:
+ *bssid = wh->i_addr3;
+ if (ic->ic_opmode == IEEE80211_M_IBSS ||
+ ic->ic_opmode == IEEE80211_M_AHDEMO)
+ rc = IEEE80211_ADDR_EQ(*bssid, bss->ni_bssid);
+ break;
+ case IEEE80211_FC1_DIR_TODS:
+ *bssid = wh->i_addr1;
+ if (ic->ic_opmode == IEEE80211_M_HOSTAP)
+ rc = IEEE80211_ADDR_EQ(*bssid, bss->ni_bssid);
+ break;
+ case IEEE80211_FC1_DIR_FROMDS:
+ case IEEE80211_FC1_DIR_DSTODS:
+ *bssid = wh->i_addr2;
+ rc = (ic->ic_opmode == IEEE80211_M_HOSTAP);
+ break;
+ }
+ break;
+ }
+ return needsnode || rc;
+}
+
+struct ieee80211_node *
+ieee80211_find_rxnode(struct ieee80211com *ic, struct ieee80211_frame *wh)
+{
+ struct ieee80211_node *ni;
+ const static u_int8_t zero[IEEE80211_ADDR_LEN];
+ u_int8_t *bssid;
+ ieee80211_node_critsec_decl(s);
+
+ ieee80211_node_critsec_begin(ic, s);
+
+ if (!ieee80211_needs_rxnode(ic, wh, &bssid))
+ return ieee80211_ref_node(ic->ic_bss);
+
+ ni = ieee80211_find_node(ic, wh->i_addr2);
+
+ if (ni == NULL) {
+ if (ic->ic_opmode != IEEE80211_M_HOSTAP) {
+ if ((ni = ieee80211_dup_bss(ic, wh->i_addr2)) != NULL)
+ IEEE80211_ADDR_COPY(ni->ni_bssid,
+ (bssid != NULL) ? bssid : zero);
+
+ IEEE80211_DPRINTF(("%s: faked-up node %p for %s\n",
+ __func__, ni, ether_sprintf(wh->i_addr2)));
+ }
+ ni = ieee80211_ref_node((ni == NULL) ? ic->ic_bss : ni);
+ }
+ ieee80211_node_critsec_end(ic, s);
+ KASSERT(ni != NULL, ("%s: null node", __func__));
+ return ni;
+}
+
/*
* Like find but search based on the channel too.
*/
diff -r 9057daf85c60 -r d83d8ae239c2 sys/net80211/ieee80211_node.h
--- a/sys/net80211/ieee80211_node.h Wed Oct 29 21:44:41 2003 +0000
+++ b/sys/net80211/ieee80211_node.h Wed Oct 29 21:50:57 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ieee80211_node.h,v 1.6 2003/10/15 11:43:51 dyoung Exp $ */
+/* $NetBSD: ieee80211_node.h,v 1.7 2003/10/29 21:50:57 dyoung Exp $ */
/*-
* Copyright (c) 2001 Atsushi Onoe
* Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
@@ -170,6 +170,10 @@
u_int8_t *);
extern struct ieee80211_node *ieee80211_find_node(struct ieee80211com *,
u_int8_t *);
+extern struct ieee80211_node *ieee80211_find_rxnode(struct ieee80211com *,
+ struct ieee80211_frame *);
+extern struct ieee80211_node *ieee80211_find_txnode(struct ieee80211com *,
+ u_int8_t *);
extern struct ieee80211_node * ieee80211_lookup_node(struct ieee80211com *,
u_int8_t *macaddr, struct ieee80211_channel *);
extern void ieee80211_free_node(struct ieee80211com *,
diff -r 9057daf85c60 -r d83d8ae239c2 sys/net80211/ieee80211_output.c
--- a/sys/net80211/ieee80211_output.c Wed Oct 29 21:44:41 2003 +0000
+++ b/sys/net80211/ieee80211_output.c Wed Oct 29 21:50:57 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ieee80211_output.c,v 1.7 2003/10/15 11:43:51 dyoung Exp $ */
+/* $NetBSD: ieee80211_output.c,v 1.8 2003/10/29 21:50:57 dyoung Exp $ */
/*-
* Copyright (c) 2001 Atsushi Onoe
* Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
@@ -35,7 +35,7 @@
#ifdef __FreeBSD__
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_output.c,v 1.5 2003/09/01 02:55:09 sam Exp $");
#else
-__KERNEL_RCSID(0, "$NetBSD: ieee80211_output.c,v 1.7 2003/10/15 11:43:51 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ieee80211_output.c,v 1.8 2003/10/29 21:50:57 dyoung Exp $");
#endif
#include "opt_inet.h"
@@ -194,23 +194,9 @@
}
memcpy(&eh, mtod(m, caddr_t), sizeof(struct ether_header));
- if (ic->ic_opmode != IEEE80211_M_STA) {
- ni = ieee80211_find_node(ic, eh.ether_dhost);
- if (ni == NULL) {
- /*
- * When not in station mode the
- * destination address should always be
- * in the node table unless this is a
- * multicast/broadcast frame.
- */
- if (!IEEE80211_IS_MULTICAST(eh.ether_dhost)) {
- /* ic->ic_stats.st_tx_nonode++; XXX statistic */
- goto bad;
- }
- ni = ic->ic_bss;
- }
- } else
- ni = ic->ic_bss;
+ if ((ni = ieee80211_find_txnode(ic, eh.ether_dhost)) == NULL)
+ goto bad;
+
ni->ni_inact = 0;
m_adj(m, sizeof(struct ether_header) - sizeof(struct llc));
Home |
Main Index |
Thread Index |
Old Index