Subject: ath(4) rate choices for 'bss' in IBSS mode
To: None <tech-net@netbsd.org>
From: Greg Troxel <gdt@ir.bbn.com>
List: tech-net
Date: 09/23/2004 15:33:03
I have a 7 systems running the 2.0 branch and significant local
changes, all with ath(4) hardware.  The systems are IBM T41s and X31s
with IBM minipci adaptors (some a/b/g and some b/g).  I found that
while I got decent range for unicast traffic, multicast traffic
performed very poorly.

On reading sys/dev/ath.c, I found that there is per-'node' rate
control, and in IBSS mode a node is kept for each neighbor.  This
seems to work pretty well.  There is also a 'node' for the 'bss', used
in STA mode to rate adapt the link to the AP.  But, it seems that in
IBSS mode the bss node is used to send multicast packets.  The
existing code (as in -current) initializes the bss node to the highest
rate.  In IBSS mode, nothing adapts this rate (other than making sure
it is a 'supported rate' in the IBSS).

I changed this to use the lowest, trading off speed for range, and now
the range I can get with multicast packets is similar to that for
unicast.

It's not clear what should happen for multicast packets, but since in
an IBSS there is no crisp notion of group membership, I would argue
that any station which could be reached in unicast mode at the lowest
rate should get multicast traffic (e.g., one generally has to ARP
before sending unicast IP).

In HOSTAP mode, arguably multicasts should get sent at the minimum
rate of any associated STA.

[Line  numbers are off because I changed a lot of other things.]
Index: sys/dev/ic/ath.c
===================================================================
RCS file: /SINEW-CVS/netbsd/src/sys/dev/ic/ath.c,v
retrieving revision 1.1.1.4
retrieving revision 1.9
diff -u -r1.1.1.4 -r1.9
--- dev/ic/ath.c	22 Aug 2004 13:37:22 -0000	1.1.1.4
+++ dev/ic/ath.c	23 Sep 2004 17:05:46 -0000	1.9
@@ -3400,7 +3470,7 @@
 	ni = ic->ic_bss;
 	an = (struct ath_node *) ni;
 	an->an_tx_ok = an->an_tx_err = an->an_tx_retr = an->an_tx_upper = 0;
-	if (state == IEEE80211_S_RUN) {
+	if (state == IEEE80211_S_RUN && ic->ic_opmode != IEEE80211_M_IBSS) {
 		/* start with highest negotiated rate */
 		KASSERT(ni->ni_rates.rs_nrates > 0,
 			("transition to RUN state w/ no rates!"));


Here is the whole (patched) code snipped in ath_rate_ctl_reset:

	/*
	 * Reset local xmit state; this is really only meaningful
	 * when operating in station or adhoc mode.
	 */
	ni = ic->ic_bss;
	an = (struct ath_node *) ni;
	an->an_tx_ok = an->an_tx_err = an->an_tx_retr = an->an_tx_upper = 0;
	if (state == IEEE80211_S_RUN && ic->ic_opmode != IEEE80211_M_IBSS) {
		/* start with highest negotiated rate */
		KASSERT(ni->ni_rates.rs_nrates > 0,
			("transition to RUN state w/ no rates!"));
		ni->ni_txrate = ni->ni_rates.rs_nrates - 1;
	} else {
		/* use lowest rate */
		ni->ni_txrate = 0;
	}