All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] b43: multiple MAC addresses support
@ 2007-11-09  1:43 Johannes Berg
  2007-11-09 10:33 ` Johannes Berg
                   ` (5 more replies)
  0 siblings, 6 replies; 21+ messages in thread
From: Johannes Berg @ 2007-11-09  1:43 UTC (permalink / raw)
  To: Michael Buesch; +Cc: linux-wireless, Ben Greear, Michael Wu, Jiri Benc

This patch adds support for multiple virtual interfaces (up to 65536)
to b43. This requires modified firmware which is detected by an invalid
day in the firmware timestamp (254), and then the firmware time and the
rest of the date is used for feature bits.

The multi-MAC support works by having a mask of ignored bits, the
modified firmware will mask off these bits before comparing the address
on incoming frames with the address. This, however, means that when you
add three MAC virtual interfaces, the firmware will at least also ACK
frames on a fourth address. The required mask is calculated dynamically
to be the least restrictive mask possible, but you should take care to
allocate your MAC addresses in a way that minimises the mask to avoid
strange behaviour. For example, avoid using addresses 02:00:00:00:00:02
and 02:00:00:00:00:10 together because these two have only 46 bits in
common, use 02:00:00:00:00:12 and 02:00:00:00:00:10 instead as those
have 47 bits in common.

Note that the mask applies only to the lower 16 bits, so the first four
bytes of all addresses need to be identical.

The required tool to patch the firmware will be published separately.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Michael Wu <flamingice@sourmilk.net>
Cc: Jiri Benc <jbenc@suse.cz>
Cc: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/b43/b43.h  |   19 ++-
 drivers/net/wireless/b43/main.c |  200 +++++++++++++++++++++++++++++++++-------
 drivers/net/wireless/b43/xmit.c |    6 -
 3 files changed, 180 insertions(+), 45 deletions(-)

--- everything.orig/drivers/net/wireless/b43/main.c	2007-11-09 01:53:47.158996039 +0100
+++ everything/drivers/net/wireless/b43/main.c	2007-11-09 02:04:31.358978135 +0100
@@ -543,7 +543,21 @@ static void b43_write_mac_bssid_template
 static void b43_upload_card_macaddress(struct b43_wldev *dev)
 {
 	b43_write_mac_bssid_templates(dev);
-	b43_macfilter_set(dev, B43_MACFILTER_SELF, dev->wl->mac_addr);
+
+	if (dev->fw.features & B43_FW_FEATURE_MULTI_MAC_STA) {
+		u16 tmp;
+
+		tmp = ((u16 *)dev->wl->mac_addr)[0];
+		b43_shm_write16(dev, B43_SHM_SHARED, 0x320, cpu_to_le16(tmp));
+		tmp = ((u16 *)dev->wl->mac_addr)[1];
+		b43_shm_write16(dev, B43_SHM_SHARED, 0x322, cpu_to_le16(tmp));
+		tmp = ((u16 *)dev->wl->mac_addr)[2];
+		b43_shm_write16(dev, B43_SHM_SHARED, 0x324, cpu_to_le16(tmp));
+		/* swap here because we always treat the mask as big endian */
+		b43_shm_write16(dev, B43_SHM_SHARED, 0x326,
+				swab16(dev->wl->mac_mask));
+	} else
+		b43_macfilter_set(dev, B43_MACFILTER_SELF, dev->wl->mac_addr);
 }
 
 static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time)
@@ -1174,18 +1188,18 @@ static void b43_write_probe_resp_plcp(st
 {
 	struct b43_plcp_hdr4 plcp;
 	u32 tmp;
-	__le16 dur;
 
 	plcp.data = 0;
 	b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
-	dur = ieee80211_generic_frame_duration(dev->wl->hw,
-					       dev->wl->if_id, size,
-					       B43_RATE_TO_BASE100KBPS(rate));
 	/* Write PLCP in two parts and timing for packet transfer */
 	tmp = le32_to_cpu(plcp.data);
 	b43_shm_write16(dev, B43_SHM_SHARED, shm_offset, tmp & 0xFFFF);
 	b43_shm_write16(dev, B43_SHM_SHARED, shm_offset + 2, tmp >> 16);
-	b43_shm_write16(dev, B43_SHM_SHARED, shm_offset + 6, le16_to_cpu(dur));
+	/*
+	 * XXX: currently, the duration here doesn't matter, but
+	 * when we implement offload it needs to be fixed!
+	 */
+	b43_shm_write16(dev, B43_SHM_SHARED, shm_offset + 6, 0);
 }
 
 /* Instead of using custom probe response template, this function
@@ -1200,7 +1214,6 @@ static u8 *b43_generate_probe_resp(struc
 	const u8 *src_data;
 	u8 *dest_data;
 	u16 src_size, elem_size, src_pos, dest_pos;
-	__le16 dur;
 	struct ieee80211_hdr *hdr;
 
 	B43_WARN_ON(!dev->cached_beacon);
@@ -1235,10 +1248,11 @@ static u8 *b43_generate_probe_resp(struc
 	/* Set the frame control. */
 	hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 					 IEEE80211_STYPE_PROBE_RESP);
-	dur = ieee80211_generic_frame_duration(dev->wl->hw,
-					       dev->wl->if_id, *dest_size,
-					       B43_RATE_TO_BASE100KBPS(rate));
-	hdr->duration_id = dur;
+	/*
+	 * XXX: currently, the duration here doesn't matter, but
+	 * when we implement offload it needs to be fixed!
+	 */
+	hdr->duration_id = 0;
 
 	return dest_data;
 }
@@ -1792,11 +1806,23 @@ static int b43_upload_microcode(struct b
 		err = -EOPNOTSUPP;
 		goto out;
 	}
-	b43dbg(dev->wl, "Loading firmware version %u.%u "
-	       "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",
-	       fwrev, fwpatch,
-	       (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF,
-	       (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F);
+	/* special day 254: modified firmware with feature bits */
+	if ((fwdate & 0xFF) == 0xFE) {
+		b43dbg(dev->wl, "Loading firmware version %u.%u\n",
+		       fwrev, fwpatch);
+		dev->fw.features = fwtime | ((fwdate & 0xFF00) << 8);
+		b43dbg(dev->wl, "This firmware was modified and has the"
+				" added features 0x%06x\n", dev->fw.features);
+		if (dev->fw.features & B43_FW_FEATURE_MULTI_MAC_STA)
+			b43dbg(dev->wl, " * station multi MAC addr support\n");
+	} else
+		b43dbg(dev->wl, "Loading firmware version %u.%u "
+		       "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",
+		       fwrev, fwpatch,
+		       (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF,
+		       fwdate & 0xFF,
+		       (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F,
+		       fwtime & 0x1F);
 
 	dev->fw.rev = fwrev;
 	dev->fw.patch = fwpatch;
@@ -2948,11 +2974,18 @@ static int b43_op_config_interface(struc
 		return -ENODEV;
 	mutex_lock(&wl->mutex);
 	spin_lock_irqsave(&wl->irq_lock, flags);
-	B43_WARN_ON(wl->if_id != if_id);
-	if (conf->bssid)
-		memcpy(wl->bssid, conf->bssid, ETH_ALEN);
-	else
-		memset(wl->bssid, 0, ETH_ALEN);
+
+	/*
+	 * Only take bssid of first iface, we can only adopt time from
+	 * one BSS so arbitrarily choose the first.
+	 */
+	if (wl->if_id == if_id) {
+		if (conf->bssid)
+			memcpy(wl->bssid, conf->bssid, ETH_ALEN);
+		else
+			memset(wl->bssid, 0, ETH_ALEN);
+	}
+
 	if (b43_status(dev) >= B43_STAT_INITIALIZED) {
 		if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
 			B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
@@ -3424,6 +3457,71 @@ static int b43_wireless_core_init(struct
 	return err;
 }
 
+struct mac_iter {
+	struct b43_wl *wl;
+	u16 mac_val;
+	bool add;
+	int count;
+};
+
+static void b43_mac_iter(void *data, u8 *mac, int if_id)
+{
+	struct mac_iter *iter = data;
+	u16 val = (mac[4] << 8) | mac[5];
+	u16 cur = (iter->wl->mac_addr[4] << 8) | iter->wl->mac_addr[5];
+
+	/* skip the one that's being removed */
+	if (!iter->add && val == iter->mac_val)
+		return;
+
+	/* take first address we find as base */
+	if (iter->count == 0) {
+		cur = val;
+		iter->wl->mac_addr[4] = cur >> 8;
+		iter->wl->mac_addr[5] = cur;
+	}
+
+	iter->wl->mac_mask |= cur ^ val;
+
+	iter->count++;
+}
+
+static void b43_adjust_mac_addr_mask(struct b43_wl *wl, bool add, u8 *addr)
+{
+	struct mac_iter iter;
+	DECLARE_MAC_BUF(mbuf);
+	u16 cur;
+	u16 val = (addr[4] << 8) | addr[5];
+
+	/*
+	 * Because this is not invoked on adding the first address,
+	 * we do not need to have any special code for that case.
+	 * If it was invoked, we'd have to set cur to val here etc.
+	 * like above in the iter->count == 0 case (because we don't
+	 * see the interface that's being added in the iteration.)
+	 */
+
+	wl->mac_mask = 0;
+
+	iter.wl = wl;
+	iter.add = add;
+	iter.mac_val = val;
+	iter.count = 0;
+	ieee80211_iterate_active_interfaces(wl->hw, b43_mac_iter, &iter);
+
+	/* add the one that's being added */
+	cur = (wl->mac_addr[4] << 8) | wl->mac_addr[5];
+	if (add)
+		wl->mac_mask |= cur ^ val;
+
+	cur = cur & ~wl->mac_mask;
+	wl->mac_addr[4] = cur >> 8;
+	wl->mac_addr[5] = cur;
+
+	b43dbg(wl, "MAC address is %s, mask is 0x%.4x\n",
+	       print_mac(mbuf, wl->mac_addr), wl->mac_mask);
+}
+
 static int b43_op_add_interface(struct ieee80211_hw *hw,
 				struct ieee80211_if_init_conf *conf)
 {
@@ -3441,16 +3539,36 @@ static int b43_op_add_interface(struct i
 		return -EOPNOTSUPP;
 
 	mutex_lock(&wl->mutex);
-	if (wl->operating)
-		goto out_mutex_unlock;
+	dev = wl->current_dev;
 
-	b43dbg(wl, "Adding Interface type %d\n", conf->type);
+	if (dev->fw.features & B43_FW_FEATURE_MULTI_MAC_STA) {
+		if (wl->if_count && conf->type != IEEE80211_IF_TYPE_STA)
+			goto out_mutex_unlock;
+		if (wl->if_count > 0) {
+			if (((u8 *)conf->mac_addr)[0] != wl->mac_addr[0])
+				goto out_mutex_unlock;
+			if (((u8 *)conf->mac_addr)[1] != wl->mac_addr[1])
+				goto out_mutex_unlock;
+			if (((u8 *)conf->mac_addr)[2] != wl->mac_addr[2])
+				goto out_mutex_unlock;
+			if (((u8 *)conf->mac_addr)[3] != wl->mac_addr[3])
+				goto out_mutex_unlock;
+			b43_adjust_mac_addr_mask(wl, 1, conf->mac_addr);
+		}
+	} else {
+		if (wl->if_count)
+			goto out_mutex_unlock;
+	}
 
-	dev = wl->current_dev;
-	wl->operating = 1;
-	wl->if_id = conf->if_id;
-	wl->if_type = conf->type;
-	memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
+	wl->if_count++;
+
+	if (wl->if_count == 1) {
+		wl->if_id = conf->if_id;
+		wl->if_type = conf->type;
+		memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
+	}
+
+	b43dbg(wl, "Adding Interface type %d\n", conf->type);
 
 	spin_lock_irqsave(&wl->irq_lock, flags);
 	b43_adjust_opmode(dev);
@@ -3464,6 +3582,14 @@ static int b43_op_add_interface(struct i
 	return err;
 }
 
+static void b43_ifid_iter(void *data, u8 *mac, int if_id)
+{
+	struct b43_wl *wl = data;
+
+	if (wl->if_id != if_id)
+		wl->if_id = if_id;
+}
+
 static void b43_op_remove_interface(struct ieee80211_hw *hw,
 				    struct ieee80211_if_init_conf *conf)
 {
@@ -3475,14 +3601,22 @@ static void b43_op_remove_interface(stru
 
 	mutex_lock(&wl->mutex);
 
-	B43_WARN_ON(!wl->operating);
-	B43_WARN_ON(wl->if_id != conf->if_id);
+	B43_WARN_ON(!wl->if_count);
+
+	wl->if_count--;
+	if (wl->if_count == 0) {
+		wl->if_type = IEEE80211_IF_TYPE_INVALID;
+		memset(wl->mac_addr, 0, ETH_ALEN);
+	}
+
+	/* arbitrarily adopt another if_id as main if_id */
+	if (conf->if_id == wl->if_id)
+		ieee80211_iterate_active_interfaces(wl->hw, b43_ifid_iter, wl);
 
-	wl->operating = 0;
+	b43_adjust_mac_addr_mask(wl, 0, conf->mac_addr);
 
 	spin_lock_irqsave(&wl->irq_lock, flags);
 	b43_adjust_opmode(dev);
-	memset(wl->mac_addr, 0, ETH_ALEN);
 	b43_upload_card_macaddress(dev);
 	spin_unlock_irqrestore(&wl->irq_lock, flags);
 
--- everything.orig/drivers/net/wireless/b43/b43.h	2007-11-09 01:53:47.248981228 +0100
+++ everything/drivers/net/wireless/b43/b43.h	2007-11-09 02:06:41.818973253 +0100
@@ -601,22 +601,20 @@ struct b43_wl {
 	struct mutex mutex;
 	spinlock_t leds_lock;
 
-	/* We can only have one operating interface (802.11 core)
-	 * at a time. General information about this interface follows.
-	 */
-
-	/* Opaque ID of the operating interface from the ieee80211
+	/*
+	 * Opaque ID of the first operating interface from the ieee80211
 	 * subsystem. Do not modify.
 	 */
 	int if_id;
-	/* The MAC address of the operating interface. */
+	/* The MAC address */
 	u8 mac_addr[ETH_ALEN];
+	u16 mac_mask;
 	/* Current BSSID */
 	u8 bssid[ETH_ALEN];
 	/* Interface type. (IEEE80211_IF_TYPE_XXX) */
 	int if_type;
-	/* Is the card operating in AP, STA or IBSS mode? */
-	bool operating;
+	/* number of open interfaces */
+	int if_count;
 	/* filter flags */
 	unsigned int filter_flags;
 	/* Stats about the wireless interface */
@@ -648,6 +646,9 @@ struct b43_firmware {
 	u16 rev;
 	/* Firmware patchlevel */
 	u16 patch;
+	/* Firmware features (24 bits) */
+#define B43_FW_FEATURE_MULTI_MAC_STA	0x000001
+	u32 features;
 };
 
 /* Device (802.11 core) initialization status. */
@@ -781,7 +782,7 @@ static inline struct b43_wldev *dev_to_b
 /* Is the device operating in a specified mode (IEEE80211_IF_TYPE_XXX). */
 static inline int b43_is_mode(struct b43_wl *wl, int type)
 {
-	return (wl->operating && wl->if_type == type);
+	return (wl->if_count && wl->if_type == type);
 }
 
 static inline u16 b43_read16(struct b43_wldev *dev, u16 offset)
--- everything.orig/drivers/net/wireless/b43/xmit.c	2007-11-09 01:53:47.378984104 +0100
+++ everything/drivers/net/wireless/b43/xmit.c	2007-11-09 01:53:57.698983181 +0100
@@ -221,7 +221,7 @@ static void generate_txhdr_fw4(struct b4
 	} else {
 		int fbrate_base100kbps = B43_RATE_TO_BASE100KBPS(rate_fb);
 		txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
-								 dev->wl->if_id,
+								 txctl->ifindex,
 								 fragment_len,
 								 fbrate_base100kbps);
 	}
@@ -311,7 +311,7 @@ static void generate_txhdr_fw4(struct b4
 		rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
 
 		if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
-			ieee80211_ctstoself_get(dev->wl->hw, dev->wl->if_id,
+			ieee80211_ctstoself_get(dev->wl->hw, txctl->ifindex,
 						fragment_data, fragment_len,
 						txctl,
 						(struct ieee80211_cts *)(txhdr->
@@ -319,7 +319,7 @@ static void generate_txhdr_fw4(struct b4
 			mac_ctl |= B43_TX4_MAC_SENDCTS;
 			len = sizeof(struct ieee80211_cts);
 		} else {
-			ieee80211_rts_get(dev->wl->hw, dev->wl->if_id,
+			ieee80211_rts_get(dev->wl->hw, txctl->ifindex,
 					  fragment_data, fragment_len, txctl,
 					  (struct ieee80211_rts *)(txhdr->
 								   rts_frame));



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: multiple MAC addresses support
  2007-11-09  1:43 [RFC] b43: multiple MAC addresses support Johannes Berg
@ 2007-11-09 10:33 ` Johannes Berg
  2007-11-09 10:52 ` Johannes Berg
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 21+ messages in thread
From: Johannes Berg @ 2007-11-09 10:33 UTC (permalink / raw)
  To: Michael Buesch; +Cc: linux-wireless, Ben Greear, Michael Wu, Jiri Benc

[-- Attachment #1: Type: text/plain, Size: 687 bytes --]

> This patch adds support for multiple virtual interfaces (up to 65536)
> to b43. This requires modified firmware which is detected by an invalid
> day in the firmware timestamp (254), and then the firmware time and the
> rest of the date is used for feature bits.

One thing I forgot to mention is that currently, mac80211 is not able to
associate different virtual stations with the same BSSID. I had a patch
to fix this but because I had so many patches I dropped that one. I'll
try to revive it next week if I get around, basically it consisted of
adding an sdata pointer to the station get routine. The bigger problem
was making the RX path happy about it :)

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: multiple MAC addresses support
  2007-11-09  1:43 [RFC] b43: multiple MAC addresses support Johannes Berg
  2007-11-09 10:33 ` Johannes Berg
@ 2007-11-09 10:52 ` Johannes Berg
  2007-11-11  2:58   ` Jouni Malinen
  2007-11-09 10:53 ` [RFC] b43: fix multi MAC address hardware crypto support Johannes Berg
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 21+ messages in thread
From: Johannes Berg @ 2007-11-09 10:52 UTC (permalink / raw)
  To: Michael Buesch
  Cc: linux-wireless, Ben Greear, Michael Wu, Jiri Benc, Jouni Malinen

[-- Attachment #1: Type: text/plain, Size: 2163 bytes --]

So as you can see from the code, I only allowed station interfaces for
now. Which is actually pretty useless since you can't use two of them to
associate to the same AP. It also violates the IEEE 802.11 specification
as far as I can tell because we can only adopt the time of one BSS...

This is a good stepping stone, however. I've shown that the firmware can
easily be modified to support address masks, so we can now think about
how multi-BSS AP operation can work.

Right now, I'm thinking we should do it this way:

As for the firmware, I'd disable support for TIM manipulation and make
it take the beacon from the multicast/broadcast frame queue instead of
from the template RAM. Essentially, at beacon time, the firmware would
send the first frame from the mc/bc queue (the beacon) and then all
other frames from the mc/bc queue (the mc/bc traffic) up to the "last
bc/mc frame ID" where we clear the more data bit. No special-casing of
the DTIM period etc, we let the driver handle all that.

We should limit multi-BSS operation to some sane value, say 16, and
require that the mask is the last four bits or less. This way, we can
use the lowest four bits of the mac address as a beacon ID and have
different "last bc/mc frame ID"s for the different beacons to ease
driver operation and make it race-free.

In the driver, for such modified firmware, we rely on mac80211's
software broadcast/multicast queuing feature along with the get_beacon()
function. Every time the firmware indicates that it has sent a beacon,
the driver will queue the next beacon (round-robin between the
interfaces) and the corresponding multicast traffic.

Something I'm not clear on right now is the timing of it all. If there
are say two BSSes, the driver can simply program the hardware to half
the beacon period and then the beacons will alternate. But if there are
seven BSSes, the beacon period might not be divisible by seven so timing
errors will happen and, worse yet, accumulate. Does hostapd somehow
account for this? Or should the beaconing work completely differently,
for example with all N beacons sent in a burst?

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC] b43: fix multi MAC address hardware crypto support
  2007-11-09  1:43 [RFC] b43: multiple MAC addresses support Johannes Berg
  2007-11-09 10:33 ` Johannes Berg
  2007-11-09 10:52 ` Johannes Berg
@ 2007-11-09 10:53 ` Johannes Berg
  2007-11-09 12:39   ` Johannes Berg
  2007-11-10  1:21   ` [RFC v2] " Johannes Berg
  2007-11-09 12:25 ` [RFC] b43: multiple MAC addresses support Johannes Berg
                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 21+ messages in thread
From: Johannes Berg @ 2007-11-09 10:53 UTC (permalink / raw)
  To: Michael Buesch; +Cc: linux-wireless, Ben Greear, Michael Wu, Jiri Benc

Once mac80211 will be able to have the same station associated
to different virtual interfaces (no matter whether as AP or as
station), we may get into trouble with the hardware encryption
offload RX path because we might have the same peer more than
once and hence the RX path doesn't know which key to use. For
this rare case, we disable the hardware RX path.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
Hopefully this helps other drivers... :)

 drivers/net/wireless/b43/b43.h  |    4 +-
 drivers/net/wireless/b43/main.c |   77 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 77 insertions(+), 4 deletions(-)

--- everything.orig/drivers/net/wireless/b43/main.c	2007-11-09 10:48:48.474785861 +0100
+++ everything/drivers/net/wireless/b43/main.c	2007-11-09 11:26:41.284781195 +0100
@@ -793,6 +793,8 @@ static int b43_key_write(struct b43_wlde
 {
 	int i;
 	int sta_keys_start;
+	static const u8 zero_mac[ETH_ALEN] = { 0 };
+	const u8 *orig_mac = mac_addr;
 
 	if (key_len > B43_SEC_KEYSIZE)
 		return -EINVAL;
@@ -807,6 +809,20 @@ static int b43_key_write(struct b43_wlde
 			sta_keys_start = 4;
 		else
 			sta_keys_start = 8;
+		/*
+		 * Check if we already have this MAC address. If so, we're
+		 * adding a key for the second station (the in-hardware mac
+		 * address for the first has already been cleared) and thus
+		 * may not write the address to the hardware.
+		 */
+		for (i = sta_keys_start; i < dev->max_nr_keys; i++) {
+			if (!dev->key[i].keyconf)
+				continue;
+			if (!compare_ether_addr(mac_addr, dev->key[i].mac)) {
+				mac_addr = zero_mac;
+				break;
+			}
+		}
 		for (i = sta_keys_start; i < dev->max_nr_keys; i++) {
 			if (!dev->key[i].keyconf) {
 				/* found empty */
@@ -829,6 +845,7 @@ static int b43_key_write(struct b43_wlde
 	}
 	keyconf->hw_key_idx = index;
 	dev->key[index].keyconf = keyconf;
+	memcpy(dev->key[index].mac, orig_mac, ETH_ALEN);
 
 	return 0;
 }
@@ -2895,8 +2912,13 @@ static int b43_op_set_key(struct ieee802
 		if (err)
 			goto out_unlock;
 
-		if (algorithm == B43_SEC_ALGO_WEP40 ||
-		    algorithm == B43_SEC_ALGO_WEP104) {
+		/*
+		 * The USE DEFAULT KEYS bit may never be set when we have
+		 * multiple interfaces.
+		 */
+		if ((dev->wl->if_count < 2) &&
+		    (algorithm == B43_SEC_ALGO_WEP40 ||
+		     algorithm == B43_SEC_ALGO_WEP104)) {
 			b43_hf_write(dev, b43_hf_read(dev) | B43_HF_USEDEFKEYS);
 		} else {
 			b43_hf_write(dev,
@@ -2925,6 +2947,56 @@ out_unlock:
 	return err;
 }
 
+static void b43_op_sta_notify(struct ieee80211_hw *hw, int if_id,
+			      enum sta_notify_cmd cmd, const u8 *addr)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev;
+	unsigned long flags;
+	int sta_keys_start, i;
+	DECLARE_MAC_BUF(mbuf);
+
+	/*
+	 * NB: This function relies (for correctness) on the fact that
+	 *     sta_notify() is always called before set_key() for any
+	 *     given station.
+	 */
+
+	/*
+	 * For now, don't add back a STA to the RX key matching
+	 * when it is removed from the second virtual interface.
+	 */
+	if (cmd != STA_NOTIFY_ADD)
+		return;
+
+	mutex_lock(&wl->mutex);
+	spin_lock_irqsave(&wl->irq_lock, flags);
+
+	dev = wl->current_dev;
+
+	if (b43_new_kidx_api(dev))
+		sta_keys_start = 4;
+	else
+		sta_keys_start = 8;
+	for (i = sta_keys_start; i < dev->max_nr_keys; i++) {
+		if (!dev->key[i].keyconf)
+			continue;
+		if (compare_ether_addr(dev->key[i].mac, addr) == 0) {
+			/*
+			 * Found the same address as is being added,
+			 * so we cannot use hardware crypto for the RX
+			 * path any more.
+			 */
+			keymac_write(dev, i, NULL);
+			b43dbg(wl, "Removed %s from key matching.\n",
+			       print_mac(mbuf, addr));
+		}
+	}
+
+	spin_unlock_irqrestore(&wl->irq_lock, flags);
+	mutex_unlock(&wl->mutex);
+}
+
 static void b43_op_configure_filter(struct ieee80211_hw *hw,
 				    unsigned int changed, unsigned int *fflags,
 				    int mc_count, struct dev_addr_list *mc_list)
@@ -3695,6 +3767,7 @@ static const struct ieee80211_ops b43_hw
 	.config_interface	= b43_op_config_interface,
 	.configure_filter	= b43_op_configure_filter,
 	.set_key		= b43_op_set_key,
+	.sta_notify		= b43_op_sta_notify,
 	.get_stats		= b43_op_get_stats,
 	.get_tx_stats		= b43_op_get_tx_stats,
 	.start			= b43_op_start,
--- everything.orig/drivers/net/wireless/b43/b43.h	2007-11-09 11:12:07.454790147 +0100
+++ everything/drivers/net/wireless/b43/b43.h	2007-11-09 11:13:11.904780978 +0100
@@ -582,10 +582,10 @@ struct b43_stats {
 
 struct b43_key {
 	/* If keyconf is NULL, this key is disabled.
-	 * keyconf is a cookie. Don't derefenrence it outside of the set_key
-	 * path, because b43 doesn't own it. */
+	 * keyconf is a cookie. b43 doesn't own it. */
 	struct ieee80211_key_conf *keyconf;
 	u8 algorithm;
+	u8 mac[ETH_ALEN];
 };
 
 struct b43_wldev;



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: multiple MAC addresses support
  2007-11-09  1:43 [RFC] b43: multiple MAC addresses support Johannes Berg
                   ` (2 preceding siblings ...)
  2007-11-09 10:53 ` [RFC] b43: fix multi MAC address hardware crypto support Johannes Berg
@ 2007-11-09 12:25 ` Johannes Berg
  2007-11-10  1:20 ` [RFC v2] " Johannes Berg
  2007-11-10  1:53 ` [RFC] " Johannes Berg
  5 siblings, 0 replies; 21+ messages in thread
From: Johannes Berg @ 2007-11-09 12:25 UTC (permalink / raw)
  To: Michael Buesch; +Cc: linux-wireless, Ben Greear, Michael Wu, Jiri Benc

[-- Attachment #1: Type: text/plain, Size: 330 bytes --]


On Fri, 2007-11-09 at 02:43 +0100, Johannes Berg wrote:
> This patch adds support for multiple virtual interfaces (up to 65536)
> to b43.

Ok, turns out I need to do more testing, somehow I broke something, it
seems that the RX header lost the "frame is for me" bit or something. Or
maybe mac80211 has a bug.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: fix multi MAC address hardware crypto support
  2007-11-09 10:53 ` [RFC] b43: fix multi MAC address hardware crypto support Johannes Berg
@ 2007-11-09 12:39   ` Johannes Berg
  2007-11-10  1:21   ` [RFC v2] " Johannes Berg
  1 sibling, 0 replies; 21+ messages in thread
From: Johannes Berg @ 2007-11-09 12:39 UTC (permalink / raw)
  To: Michael Buesch; +Cc: linux-wireless, Ben Greear, Michael Wu, Jiri Benc

[-- Attachment #1: Type: text/plain, Size: 751 bytes --]


> +static void b43_op_sta_notify(struct ieee80211_hw *hw, int if_id,
> +			      enum sta_notify_cmd cmd, const u8 *addr)
> +{
> +	struct b43_wl *wl = hw_to_b43_wl(hw);
> +	struct b43_wldev *dev;
> +	unsigned long flags;
> +	int sta_keys_start, i;
> +	DECLARE_MAC_BUF(mbuf);
> +
> +	/*
> +	 * NB: This function relies (for correctness) on the fact that
> +	 *     sta_notify() is always called before set_key() for any
> +	 *     given station.
> +	 */
> +
> +	/*
> +	 * For now, don't add back a STA to the RX key matching
> +	 * when it is removed from the second virtual interface.
> +	 */
> +	if (cmd != STA_NOTIFY_ADD)
> +		return;
> +
> +	mutex_lock(&wl->mutex);

Hm. this is atomic, can't lock the mutex.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC v2] b43: multiple MAC addresses support
  2007-11-09  1:43 [RFC] b43: multiple MAC addresses support Johannes Berg
                   ` (3 preceding siblings ...)
  2007-11-09 12:25 ` [RFC] b43: multiple MAC addresses support Johannes Berg
@ 2007-11-10  1:20 ` Johannes Berg
  2007-11-10  1:53 ` [RFC] " Johannes Berg
  5 siblings, 0 replies; 21+ messages in thread
From: Johannes Berg @ 2007-11-10  1:20 UTC (permalink / raw)
  To: Michael Buesch; +Cc: linux-wireless, Ben Greear, Michael Wu, Jiri Benc

This patch adds support for multiple virtual interfaces (up to 65536)
to b43. This requires modified firmware which is detected by an invalid
day in the firmware timestamp (254), and then the firmware time and the
rest of the date is used for feature bits.

The multi-MAC support works by having a mask of ignored bits, the
modified firmware will mask off these bits before comparing the address
on incoming frames with the address. This, however, means that when you
add three MAC virtual interfaces, the firmware will at least also ACK
frames on a fourth address. The required mask is calculated dynamically
to be the least restrictive mask possible, but you should take care to
allocate your MAC addresses in a way that minimises the mask to avoid
strange behaviour. For example, avoid using addresses 02:00:00:00:00:02
and 02:00:00:00:00:10 together because these two have only 46 bits in
common, use 02:00:00:00:00:12 and 02:00:00:00:00:10 instead as those
have 47 bits in common.

Note that the mask applies only to the lower 16 bits, so the first four
bytes of all addresses need to be identical.

The required tool to patch the firmware will be published separately.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Michael Wu <flamingice@sourmilk.net>
Cc: Jiri Benc <jbenc@suse.cz>
Cc: Ben Greear <greearb@candelatech.com>
---
Ok, it works now. This uses registers instead of shm to set the MAC
address. Not that it matters much. Also fixes a few small bugs I think.
But that may have been only in the security fix patch. You can do the
interdiff to find out...

 drivers/net/wireless/b43/b43.h  |   19 ++-
 drivers/net/wireless/b43/main.c |  199 +++++++++++++++++++++++++++++++++-------
 drivers/net/wireless/b43/xmit.c |    6 -
 3 files changed, 179 insertions(+), 45 deletions(-)

--- everything.orig/drivers/net/wireless/b43/main.c	2007-11-09 03:22:39.028987631 +0100
+++ everything/drivers/net/wireless/b43/main.c	2007-11-10 02:12:20.959959690 +0100
@@ -543,7 +543,20 @@ static void b43_write_mac_bssid_template
 static void b43_upload_card_macaddress(struct b43_wldev *dev)
 {
 	b43_write_mac_bssid_templates(dev);
-	b43_macfilter_set(dev, B43_MACFILTER_SELF, dev->wl->mac_addr);
+
+	if (dev->fw.features & B43_FW_FEATURE_MULTI_MAC_STA) {
+		u16 tmp;
+
+		tmp = ((u16 *)dev->wl->mac_addr)[0];
+		b43_shm_write16(dev, B43_SHM_SCRATCH, 60, cpu_to_le16(tmp));
+		tmp = ((u16 *)dev->wl->mac_addr)[1];
+		b43_shm_write16(dev, B43_SHM_SCRATCH, 61, cpu_to_le16(tmp));
+		tmp = ((u16 *)dev->wl->mac_addr)[2];
+		b43_shm_write16(dev, B43_SHM_SCRATCH, 62, cpu_to_le16(tmp));
+		/* swap here because we always treat the mask as big endian */
+		b43_shm_write16(dev, B43_SHM_SCRATCH, 63, swab16(~dev->wl->mac_mask));
+	} else
+		b43_macfilter_set(dev, B43_MACFILTER_SELF, dev->wl->mac_addr);
 }
 
 static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time)
@@ -1174,18 +1187,18 @@ static void b43_write_probe_resp_plcp(st
 {
 	struct b43_plcp_hdr4 plcp;
 	u32 tmp;
-	__le16 dur;
 
 	plcp.data = 0;
 	b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
-	dur = ieee80211_generic_frame_duration(dev->wl->hw,
-					       dev->wl->if_id, size,
-					       B43_RATE_TO_BASE100KBPS(rate));
 	/* Write PLCP in two parts and timing for packet transfer */
 	tmp = le32_to_cpu(plcp.data);
 	b43_shm_write16(dev, B43_SHM_SHARED, shm_offset, tmp & 0xFFFF);
 	b43_shm_write16(dev, B43_SHM_SHARED, shm_offset + 2, tmp >> 16);
-	b43_shm_write16(dev, B43_SHM_SHARED, shm_offset + 6, le16_to_cpu(dur));
+	/*
+	 * XXX: currently, the duration here doesn't matter, but
+	 * when we implement offload it needs to be fixed!
+	 */
+	b43_shm_write16(dev, B43_SHM_SHARED, shm_offset + 6, 0);
 }
 
 /* Instead of using custom probe response template, this function
@@ -1200,7 +1213,6 @@ static u8 *b43_generate_probe_resp(struc
 	const u8 *src_data;
 	u8 *dest_data;
 	u16 src_size, elem_size, src_pos, dest_pos;
-	__le16 dur;
 	struct ieee80211_hdr *hdr;
 
 	B43_WARN_ON(!dev->cached_beacon);
@@ -1235,10 +1247,11 @@ static u8 *b43_generate_probe_resp(struc
 	/* Set the frame control. */
 	hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 					 IEEE80211_STYPE_PROBE_RESP);
-	dur = ieee80211_generic_frame_duration(dev->wl->hw,
-					       dev->wl->if_id, *dest_size,
-					       B43_RATE_TO_BASE100KBPS(rate));
-	hdr->duration_id = dur;
+	/*
+	 * XXX: currently, the duration here doesn't matter, but
+	 * when we implement offload it needs to be fixed!
+	 */
+	hdr->duration_id = 0;
 
 	return dest_data;
 }
@@ -1792,11 +1805,23 @@ static int b43_upload_microcode(struct b
 		err = -EOPNOTSUPP;
 		goto out;
 	}
-	b43dbg(dev->wl, "Loading firmware version %u.%u "
-	       "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",
-	       fwrev, fwpatch,
-	       (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF,
-	       (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F);
+	/* special day 254: modified firmware with feature bits */
+	if ((fwdate & 0xFF) == 0xFE) {
+		b43dbg(dev->wl, "Loading firmware version %u.%u\n",
+		       fwrev, fwpatch);
+		dev->fw.features = fwtime | ((fwdate & 0xFF00) << 8);
+		b43dbg(dev->wl, "This firmware was modified and has the"
+				" added features 0x%06x\n", dev->fw.features);
+		if (dev->fw.features & B43_FW_FEATURE_MULTI_MAC_STA)
+			b43dbg(dev->wl, " * station multi MAC addr support\n");
+	} else
+		b43dbg(dev->wl, "Loading firmware version %u.%u "
+		       "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",
+		       fwrev, fwpatch,
+		       (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF,
+		       fwdate & 0xFF,
+		       (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F,
+		       fwtime & 0x1F);
 
 	dev->fw.rev = fwrev;
 	dev->fw.patch = fwpatch;
@@ -2948,11 +2973,18 @@ static int b43_op_config_interface(struc
 		return -ENODEV;
 	mutex_lock(&wl->mutex);
 	spin_lock_irqsave(&wl->irq_lock, flags);
-	B43_WARN_ON(wl->if_id != if_id);
-	if (conf->bssid)
-		memcpy(wl->bssid, conf->bssid, ETH_ALEN);
-	else
-		memset(wl->bssid, 0, ETH_ALEN);
+
+	/*
+	 * Only take bssid of first iface, we can only adopt time from
+	 * one BSS so arbitrarily choose the first.
+	 */
+	if (wl->if_id == if_id) {
+		if (conf->bssid)
+			memcpy(wl->bssid, conf->bssid, ETH_ALEN);
+		else
+			memset(wl->bssid, 0, ETH_ALEN);
+	}
+
 	if (b43_status(dev) >= B43_STAT_INITIALIZED) {
 		if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
 			B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
@@ -3424,6 +3456,71 @@ static int b43_wireless_core_init(struct
 	return err;
 }
 
+struct mac_iter {
+	struct b43_wl *wl;
+	u16 mac_val;
+	bool add;
+	int count;
+};
+
+static void b43_mac_iter(void *data, u8 *mac, int if_id)
+{
+	struct mac_iter *iter = data;
+	u16 val = (mac[4] << 8) | mac[5];
+	u16 cur = (iter->wl->mac_addr[4] << 8) | iter->wl->mac_addr[5];
+
+	/* skip the one that's being removed */
+	if (!iter->add && val == iter->mac_val)
+		return;
+
+	/* take first address we find as base */
+	if (iter->count == 0) {
+		cur = val;
+		iter->wl->mac_addr[4] = cur >> 8;
+		iter->wl->mac_addr[5] = cur;
+	}
+
+	iter->wl->mac_mask |= cur ^ val;
+
+	iter->count++;
+}
+
+static void b43_adjust_mac_addr_mask(struct b43_wl *wl, bool add, u8 *addr)
+{
+	struct mac_iter iter;
+	DECLARE_MAC_BUF(mbuf);
+	u16 cur;
+	u16 val = (addr[4] << 8) | addr[5];
+
+	/*
+	 * Because this is not invoked on adding the first address,
+	 * we do not need to have any special code for that case.
+	 * If it was invoked, we'd have to set cur to val here etc.
+	 * like above in the iter->count == 0 case (because we don't
+	 * see the interface that's being added in the iteration.)
+	 */
+
+	wl->mac_mask = 0;
+
+	iter.wl = wl;
+	iter.add = add;
+	iter.mac_val = val;
+	iter.count = 0;
+	ieee80211_iterate_active_interfaces(wl->hw, b43_mac_iter, &iter);
+
+	/* add the one that's being added */
+	cur = (wl->mac_addr[4] << 8) | wl->mac_addr[5];
+	if (add)
+		wl->mac_mask |= cur ^ val;
+
+	cur = cur & ~wl->mac_mask;
+	wl->mac_addr[4] = cur >> 8;
+	wl->mac_addr[5] = cur;
+
+	b43dbg(wl, "MAC address is %s, mask is 0x%.4x\n",
+	       print_mac(mbuf, wl->mac_addr), wl->mac_mask);
+}
+
 static int b43_op_add_interface(struct ieee80211_hw *hw,
 				struct ieee80211_if_init_conf *conf)
 {
@@ -3441,16 +3538,36 @@ static int b43_op_add_interface(struct i
 		return -EOPNOTSUPP;
 
 	mutex_lock(&wl->mutex);
-	if (wl->operating)
-		goto out_mutex_unlock;
+	dev = wl->current_dev;
 
-	b43dbg(wl, "Adding Interface type %d\n", conf->type);
+	if (dev->fw.features & B43_FW_FEATURE_MULTI_MAC_STA) {
+		if (wl->if_count && conf->type != IEEE80211_IF_TYPE_STA)
+			goto out_mutex_unlock;
+		if (wl->if_count > 0) {
+			if (((u8 *)conf->mac_addr)[0] != wl->mac_addr[0])
+				goto out_mutex_unlock;
+			if (((u8 *)conf->mac_addr)[1] != wl->mac_addr[1])
+				goto out_mutex_unlock;
+			if (((u8 *)conf->mac_addr)[2] != wl->mac_addr[2])
+				goto out_mutex_unlock;
+			if (((u8 *)conf->mac_addr)[3] != wl->mac_addr[3])
+				goto out_mutex_unlock;
+			b43_adjust_mac_addr_mask(wl, 1, conf->mac_addr);
+		}
+	} else {
+		if (wl->if_count)
+			goto out_mutex_unlock;
+	}
 
-	dev = wl->current_dev;
-	wl->operating = 1;
-	wl->if_id = conf->if_id;
-	wl->if_type = conf->type;
-	memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
+	wl->if_count++;
+
+	if (wl->if_count == 1) {
+		wl->if_id = conf->if_id;
+		wl->if_type = conf->type;
+		memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
+	}
+
+	b43dbg(wl, "Adding Interface type %d\n", conf->type);
 
 	spin_lock_irqsave(&wl->irq_lock, flags);
 	b43_adjust_opmode(dev);
@@ -3464,6 +3581,14 @@ static int b43_op_add_interface(struct i
 	return err;
 }
 
+static void b43_ifid_iter(void *data, u8 *mac, int if_id)
+{
+	struct b43_wl *wl = data;
+
+	if (wl->if_id != if_id)
+		wl->if_id = if_id;
+}
+
 static void b43_op_remove_interface(struct ieee80211_hw *hw,
 				    struct ieee80211_if_init_conf *conf)
 {
@@ -3475,14 +3600,22 @@ static void b43_op_remove_interface(stru
 
 	mutex_lock(&wl->mutex);
 
-	B43_WARN_ON(!wl->operating);
-	B43_WARN_ON(wl->if_id != conf->if_id);
+	B43_WARN_ON(!wl->if_count);
+
+	wl->if_count--;
+	if (wl->if_count == 0) {
+		wl->if_type = IEEE80211_IF_TYPE_INVALID;
+		memset(wl->mac_addr, 0, ETH_ALEN);
+	}
+
+	/* arbitrarily adopt another if_id as main if_id */
+	if (conf->if_id == wl->if_id)
+		ieee80211_iterate_active_interfaces(wl->hw, b43_ifid_iter, wl);
 
-	wl->operating = 0;
+	b43_adjust_mac_addr_mask(wl, 0, conf->mac_addr);
 
 	spin_lock_irqsave(&wl->irq_lock, flags);
 	b43_adjust_opmode(dev);
-	memset(wl->mac_addr, 0, ETH_ALEN);
 	b43_upload_card_macaddress(dev);
 	spin_unlock_irqrestore(&wl->irq_lock, flags);
 
--- everything.orig/drivers/net/wireless/b43/b43.h	2007-11-09 03:22:39.098988498 +0100
+++ everything/drivers/net/wireless/b43/b43.h	2007-11-09 22:54:31.489965385 +0100
@@ -601,22 +601,20 @@ struct b43_wl {
 	struct mutex mutex;
 	spinlock_t leds_lock;
 
-	/* We can only have one operating interface (802.11 core)
-	 * at a time. General information about this interface follows.
-	 */
-
-	/* Opaque ID of the operating interface from the ieee80211
+	/*
+	 * Opaque ID of the first operating interface from the ieee80211
 	 * subsystem. Do not modify.
 	 */
 	int if_id;
-	/* The MAC address of the operating interface. */
+	/* The MAC address */
 	u8 mac_addr[ETH_ALEN];
+	u16 mac_mask;
 	/* Current BSSID */
 	u8 bssid[ETH_ALEN];
 	/* Interface type. (IEEE80211_IF_TYPE_XXX) */
 	int if_type;
-	/* Is the card operating in AP, STA or IBSS mode? */
-	bool operating;
+	/* number of open interfaces */
+	int if_count;
 	/* filter flags */
 	unsigned int filter_flags;
 	/* Stats about the wireless interface */
@@ -648,6 +646,9 @@ struct b43_firmware {
 	u16 rev;
 	/* Firmware patchlevel */
 	u16 patch;
+	/* Firmware features (24 bits) */
+#define B43_FW_FEATURE_MULTI_MAC_STA	0x000001
+	u32 features;
 };
 
 /* Device (802.11 core) initialization status. */
@@ -781,7 +782,7 @@ static inline struct b43_wldev *dev_to_b
 /* Is the device operating in a specified mode (IEEE80211_IF_TYPE_XXX). */
 static inline int b43_is_mode(struct b43_wl *wl, int type)
 {
-	return (wl->operating && wl->if_type == type);
+	return (wl->if_count && wl->if_type == type);
 }
 
 static inline u16 b43_read16(struct b43_wldev *dev, u16 offset)
--- everything.orig/drivers/net/wireless/b43/xmit.c	2007-11-09 03:22:39.238983995 +0100
+++ everything/drivers/net/wireless/b43/xmit.c	2007-11-09 22:38:21.219963866 +0100
@@ -221,7 +221,7 @@ static void generate_txhdr_fw4(struct b4
 	} else {
 		int fbrate_base100kbps = B43_RATE_TO_BASE100KBPS(rate_fb);
 		txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
-								 dev->wl->if_id,
+								 txctl->ifindex,
 								 fragment_len,
 								 fbrate_base100kbps);
 	}
@@ -311,7 +311,7 @@ static void generate_txhdr_fw4(struct b4
 		rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
 
 		if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
-			ieee80211_ctstoself_get(dev->wl->hw, dev->wl->if_id,
+			ieee80211_ctstoself_get(dev->wl->hw, txctl->ifindex,
 						fragment_data, fragment_len,
 						txctl,
 						(struct ieee80211_cts *)(txhdr->
@@ -319,7 +319,7 @@ static void generate_txhdr_fw4(struct b4
 			mac_ctl |= B43_TX4_MAC_SENDCTS;
 			len = sizeof(struct ieee80211_cts);
 		} else {
-			ieee80211_rts_get(dev->wl->hw, dev->wl->if_id,
+			ieee80211_rts_get(dev->wl->hw, txctl->ifindex,
 					  fragment_data, fragment_len, txctl,
 					  (struct ieee80211_rts *)(txhdr->
 								   rts_frame));



^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC v2] b43: fix multi MAC address hardware crypto support
  2007-11-09 10:53 ` [RFC] b43: fix multi MAC address hardware crypto support Johannes Berg
  2007-11-09 12:39   ` Johannes Berg
@ 2007-11-10  1:21   ` Johannes Berg
  1 sibling, 0 replies; 21+ messages in thread
From: Johannes Berg @ 2007-11-10  1:21 UTC (permalink / raw)
  To: Michael Buesch; +Cc: linux-wireless, Ben Greear, Michael Wu, Jiri Benc

Once mac80211 will be able to have the same station associated
to different virtual interfaces (no matter whether as AP or as
station), we may get into trouble with the hardware encryption
offload RX path because we might have the same peer more than
once and hence the RX path doesn't know which key to use. For
this rare case, we disable the hardware RX path.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
Fixes two NULL pointer dereferences and the mutex lock thing. No way to
actually test it until I patch mac80211 to support associating to the
same AP with two virtual interfaces...

 drivers/net/wireless/b43/b43.h  |    3 -
 drivers/net/wireless/b43/main.c |   81 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 81 insertions(+), 3 deletions(-)

--- everything.orig/drivers/net/wireless/b43/main.c	2007-11-10 02:12:20.959959690 +0100
+++ everything/drivers/net/wireless/b43/main.c	2007-11-10 02:14:26.719963486 +0100
@@ -792,6 +792,8 @@ static int b43_key_write(struct b43_wlde
 {
 	int i;
 	int sta_keys_start;
+	static const u8 zero_mac[ETH_ALEN] = { 0 };
+	const u8 *orig_mac = mac_addr;
 
 	if (key_len > B43_SEC_KEYSIZE)
 		return -EINVAL;
@@ -806,6 +808,22 @@ static int b43_key_write(struct b43_wlde
 			sta_keys_start = 4;
 		else
 			sta_keys_start = 8;
+		/*
+		 * Check if we already have this MAC address. If so, we're
+		 * adding a key for the second station (the in-hardware mac
+		 * address for the first has already been cleared) and thus
+		 * may not write the address to the hardware.
+		 */
+		for (i = sta_keys_start; i < dev->max_nr_keys; i++) {
+			if (!mac_addr)
+				break;
+			if (!dev->key[i].keyconf)
+				continue;
+			if (!compare_ether_addr(mac_addr, dev->key[i].mac)) {
+				mac_addr = zero_mac;
+				break;
+			}
+		}
 		for (i = sta_keys_start; i < dev->max_nr_keys; i++) {
 			if (!dev->key[i].keyconf) {
 				/* found empty */
@@ -828,6 +846,10 @@ static int b43_key_write(struct b43_wlde
 	}
 	keyconf->hw_key_idx = index;
 	dev->key[index].keyconf = keyconf;
+	if (orig_mac)
+		memcpy(dev->key[index].mac, orig_mac, ETH_ALEN);
+	else
+		memset(dev->key[index].mac, 0xFF, ETH_ALEN);
 
 	return 0;
 }
@@ -2894,8 +2916,13 @@ static int b43_op_set_key(struct ieee802
 		if (err)
 			goto out_unlock;
 
-		if (algorithm == B43_SEC_ALGO_WEP40 ||
-		    algorithm == B43_SEC_ALGO_WEP104) {
+		/*
+		 * The USE DEFAULT KEYS bit may never be set when we have
+		 * multiple interfaces.
+		 */
+		if ((wl->if_count < 2) &&
+		    (algorithm == B43_SEC_ALGO_WEP40 ||
+		     algorithm == B43_SEC_ALGO_WEP104)) {
 			b43_hf_write(dev, b43_hf_read(dev) | B43_HF_USEDEFKEYS);
 		} else {
 			b43_hf_write(dev,
@@ -2924,6 +2951,55 @@ out_unlock:
 	return err;
 }
 
+static void b43_op_sta_notify(struct ieee80211_hw *hw, int if_id,
+			      enum sta_notify_cmd cmd, const u8 *addr)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev;
+	unsigned long flags;
+	int sta_keys_start, i;
+	DECLARE_MAC_BUF(mbuf);
+
+	/*
+	 * NB: This function relies (for correctness) on the fact that
+	 *     sta_notify() is always called before set_key() for any
+	 *     given station.
+	 */
+
+	/*
+	 * For now, don't add back a STA to the RX key matching
+	 * when it is removed from the second virtual interface.
+	 */
+	if (cmd != STA_NOTIFY_ADD)
+		return;
+
+	/* can't lock mutex here */
+	spin_lock_irqsave(&wl->irq_lock, flags);
+
+	dev = wl->current_dev;
+
+	if (b43_new_kidx_api(dev))
+		sta_keys_start = 4;
+	else
+		sta_keys_start = 8;
+	for (i = sta_keys_start; i < dev->max_nr_keys; i++) {
+		if (!dev->key[i].keyconf)
+			continue;
+		if (compare_ether_addr(dev->key[i].mac, addr) == 0) {
+			/*
+			 * Found the same address as is being added,
+			 * so we cannot use hardware crypto for the RX
+			 * path any more.
+			 */
+			keymac_write(dev, i, NULL);
+			b43dbg(wl, "Removed %s from key matching.\n",
+			       print_mac(mbuf, addr));
+		}
+	}
+
+	spin_unlock_irqrestore(&wl->irq_lock, flags);
+}
+
 static void b43_op_configure_filter(struct ieee80211_hw *hw,
 				    unsigned int changed, unsigned int *fflags,
 				    int mc_count, struct dev_addr_list *mc_list)
@@ -3694,6 +3770,7 @@ static const struct ieee80211_ops b43_hw
 	.config_interface	= b43_op_config_interface,
 	.configure_filter	= b43_op_configure_filter,
 	.set_key		= b43_op_set_key,
+	.sta_notify		= b43_op_sta_notify,
 	.get_stats		= b43_op_get_stats,
 	.get_tx_stats		= b43_op_get_tx_stats,
 	.start			= b43_op_start,
--- everything.orig/drivers/net/wireless/b43/b43.h	2007-11-09 22:54:31.489965385 +0100
+++ everything/drivers/net/wireless/b43/b43.h	2007-11-10 02:14:26.719963486 +0100
@@ -582,10 +582,11 @@ struct b43_stats {
 
 struct b43_key {
 	/* If keyconf is NULL, this key is disabled.
-	 * keyconf is a cookie. Don't derefenrence it outside of the set_key
+	 * keyconf is a cookie. Don't dereference it outside of the set_key
 	 * path, because b43 doesn't own it. */
 	struct ieee80211_key_conf *keyconf;
 	u8 algorithm;
+	u8 mac[ETH_ALEN];
 };
 
 struct b43_wldev;



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: multiple MAC addresses support
  2007-11-09  1:43 [RFC] b43: multiple MAC addresses support Johannes Berg
                   ` (4 preceding siblings ...)
  2007-11-10  1:20 ` [RFC v2] " Johannes Berg
@ 2007-11-10  1:53 ` Johannes Berg
  2007-11-10 21:34   ` Johannes Berg
  5 siblings, 1 reply; 21+ messages in thread
From: Johannes Berg @ 2007-11-10  1:53 UTC (permalink / raw)
  To: Michael Buesch; +Cc: linux-wireless, Ben Greear, Michael Wu, Jiri Benc

[-- Attachment #1: Type: text/plain, Size: 281 bytes --]


> The required tool to patch the firmware will be published separately.

http://git.sipsolutions.net/bcom-ucode.git

Requires patched bcm43xx-asm and bcm43xx-dasm so you won't be happy
until Michael does similar changes, I've sent them to him in private
mail.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: multiple MAC addresses support
  2007-11-10  1:53 ` [RFC] " Johannes Berg
@ 2007-11-10 21:34   ` Johannes Berg
  0 siblings, 0 replies; 21+ messages in thread
From: Johannes Berg @ 2007-11-10 21:34 UTC (permalink / raw)
  To: Michael Buesch; +Cc: linux-wireless, Ben Greear, Michael Wu, Jiri Benc

[-- Attachment #1: Type: text/plain, Size: 347 bytes --]


> http://git.sipsolutions.net/bcom-ucode.git
> 
> Requires patched bcm43xx-asm and bcm43xx-dasm so you won't be happy
> until Michael does similar changes, I've sent them to him in private
> mail.

And he has committed them. Grab my script above,
http://git.bu3sch.de/git/bcm43xx-asm.git and let me know the test
results ;)

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: multiple MAC addresses support
  2007-11-09 10:52 ` Johannes Berg
@ 2007-11-11  2:58   ` Jouni Malinen
  2007-11-12 11:14     ` Kalle Valo
  2007-11-12 12:02     ` Johannes Berg
  0 siblings, 2 replies; 21+ messages in thread
From: Jouni Malinen @ 2007-11-11  2:58 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Michael Buesch, linux-wireless, Ben Greear, Michael Wu, Jiri Benc

On Fri, Nov 09, 2007 at 11:52:30AM +0100, Johannes Berg wrote:

> Something I'm not clear on right now is the timing of it all. If there
> are say two BSSes, the driver can simply program the hardware to half
> the beacon period and then the beacons will alternate. But if there are
> seven BSSes, the beacon period might not be divisible by seven so timing
> errors will happen and, worse yet, accumulate. Does hostapd somehow
> account for this? Or should the beaconing work completely differently,
> for example with all N beacons sent in a burst?

You could always modify the beacon period to a suitable number that
would be divisible by whatever number of BSSes there are and/or add
empty slot to move from, say, 7 to 8, and just not send a beacon at some
of the slots. Sending a burst of all beacons at the same time is also a
valid option up to a certain limit on how long a time would be allocated
for this. However, this may have some timing issues when there are
multiple power save buffered broadcast/multicast frames waiting to be
sent out. In general, it would be good to try to send the beacon frames
as close to their correct time as possible to allow power saving
stations to remain asleep most of the time. Some low-level operation
would also need to make sure the beacon timestamp is correct if the
frame gets delayed due to other frames.

I think it would be perfectly fine to try to simply the configuration
and implementation by requiring all BSSes to use the same beacon
interval and allow small changes in the interval, if needed. hostapd
does not have code for this type of modifications. I've done some
experiments with configuring the hardware to use beacon interval divided
by number of BSSes, but ended up using burst of beacon frames instead
(and all BSSes were forced to use the same beacon interval).

-- 
Jouni Malinen                                            PGP id EFC895FA

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: multiple MAC addresses support
  2007-11-11  2:58   ` Jouni Malinen
@ 2007-11-12 11:14     ` Kalle Valo
  2007-11-13 11:26       ` Johannes Berg
  2007-11-13 14:14       ` Johannes Berg
  2007-11-12 12:02     ` Johannes Berg
  1 sibling, 2 replies; 21+ messages in thread
From: Kalle Valo @ 2007-11-12 11:14 UTC (permalink / raw)
  To: Jouni Malinen
  Cc: Johannes Berg, Michael Buesch, linux-wireless, Ben Greear,
	Michael Wu, Jiri Benc

Jouni Malinen <j@w1.fi> writes:

> On Fri, Nov 09, 2007 at 11:52:30AM +0100, Johannes Berg wrote:
>
>> Something I'm not clear on right now is the timing of it all. If there
>> are say two BSSes, the driver can simply program the hardware to half
>> the beacon period and then the beacons will alternate. But if there are
>> seven BSSes, the beacon period might not be divisible by seven so timing
>> errors will happen and, worse yet, accumulate. Does hostapd somehow
>> account for this? Or should the beaconing work completely differently,
>> for example with all N beacons sent in a burst?
>
> You could always modify the beacon period to a suitable number that
> would be divisible by whatever number of BSSes there are and/or add
> empty slot to move from, say, 7 to 8, and just not send a beacon at some
> of the slots. Sending a burst of all beacons at the same time is also a
> valid option up to a certain limit on how long a time would be allocated
> for this. However, this may have some timing issues when there are
> multiple power save buffered broadcast/multicast frames waiting to be
> sent out. In general, it would be good to try to send the beacon frames
> as close to their correct time as possible to allow power saving
> stations to remain asleep most of the time.

Exactly, it is important for small mobile devices that beacons are
sent at the correct time. For example, I have seen broken APs which
Target Beacon Transmission Time fluctuates and Nokia N800 has high
power consumption because of that.

-- 
Kalle Valo

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: multiple MAC addresses support
  2007-11-11  2:58   ` Jouni Malinen
  2007-11-12 11:14     ` Kalle Valo
@ 2007-11-12 12:02     ` Johannes Berg
  2007-11-18 23:47       ` Jouni Malinen
  1 sibling, 1 reply; 21+ messages in thread
From: Johannes Berg @ 2007-11-12 12:02 UTC (permalink / raw)
  To: Jouni Malinen
  Cc: Michael Buesch, linux-wireless, Ben Greear, Michael Wu, Jiri Benc

[-- Attachment #1: Type: text/plain, Size: 3843 bytes --]


> You could always modify the beacon period to a suitable number that
> would be divisible by whatever number of BSSes there are and/or add
> empty slot to move from, say, 7 to 8, and just not send a beacon at some
> of the slots.

Hmm. I'd have said that yes, this works, but rereading the spec I'm not
too certain any more. But more below.

> Sending a burst of all beacons at the same time is also a
> valid option up to a certain limit on how long a time would be allocated
> for this. However, this may have some timing issues when there are
> multiple power save buffered broadcast/multicast frames waiting to be
> sent out.

That's the point I wasn't quite sure on, would it be valid to send the
frames in the order beacon1, beacon2, beacon3, mc1, mc1, ..., mc2, ...,
mc3, ...?

[slight reordering of your mail]

> Some low-level operation
> would also need to make sure the beacon timestamp is correct if the
> frame gets delayed due to other frames.

On Broadcom hardware, I'm pretty sure that the transmit engine updates
the timestamp only during transmission so that shouldn't be a problem.

> In general, it would be good to try to send the beacon frames
> as close to their correct time as possible to allow power saving
> stations to remain asleep most of the time. 

Time zero is defined as TBTT, so this means we need to send the frame as
close to TU "Beacon Interval" * N where N is a non-negative number. Is
my interpretation correct here? If so, and because we only have a single
TSF, doesn't this mean that we should send the beacons all together as
quickly as possible? If we tried spreading them out we'd be sending them
at something like "Beacon Interval" * (N + 0.25) which isn't something
we should do, no?

Another thing that I just realised is that I'm not sure whether we
update the TSF in probe responses correctly or at all because as far as
I can tell it's only done for the probe response microcode offload.
We'll have to look into this.

Actually, what we can do is adjust the offset for each of the beacons
differently. So when we're sending a beacon at TSF "interval * (N+.25)"
we can round that up to "interval * (N+1)" by adjusting the TSF write
offset. This means that stations will adopt a TSF that is larger than
ours by a bit. If we'd do the same for probe responses (which should be
fairly easy), would the timing work out? I'm not entirely clear about
CFP operation etc.

Effectively, only one of our BSSes would be sending out our own TSF, the
other ones would be sending something up to say 0.875 of the beacon
interval larger (assuming we limit the number of BSSes to eight). All
STAs would adopt this time, but what influence does that have on other
operation?

> I think it would be perfectly fine to try to simply the configuration
> and implementation by requiring all BSSes to use the same beacon
> interval and allow small changes in the interval, if needed. hostapd
> does not have code for this type of modifications.

I think I can do pretty much whatever we want, including send TSF
offsets as described above. But I'm not entirely clear on the
side-effects of that. If the TSF offsets are possible without
significant side effects then we're pretty much free to do whatever we
want in software (under some constraints), in the microcode I'd probably
simply pull the broadcast/multicast FIFO at the beacon interval and send
whatever software put into it and allow for extended frame control wrt.
timestamping for beacons/probe responses.

> I've done some
> experiments with configuring the hardware to use beacon interval divided
> by number of BSSes, but ended up using burst of beacon frames instead
> (and all BSSes were forced to use the same beacon interval).

Do you remember any reason?

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: multiple MAC addresses support
  2007-11-12 11:14     ` Kalle Valo
@ 2007-11-13 11:26       ` Johannes Berg
  2007-11-15  9:35         ` Kalle Valo
  2007-11-18 23:02         ` Jouni Malinen
  2007-11-13 14:14       ` Johannes Berg
  1 sibling, 2 replies; 21+ messages in thread
From: Johannes Berg @ 2007-11-13 11:26 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Jouni Malinen, Michael Buesch, linux-wireless, Ben Greear,
	Michael Wu, Jiri Benc

[-- Attachment #1: Type: text/plain, Size: 2101 bytes --]


On Mon, 2007-11-12 at 13:14 +0200, Kalle Valo wrote:

> Exactly, it is important for small mobile devices that beacons are
> sent at the correct time. For example, I have seen broken APs which
> Target Beacon Transmission Time fluctuates and Nokia N800 has high
> power consumption because of that.

The N800 and similar devices only wake up at DTIM beacons, right? So
another idea would be to burst beacons but make sure the DTIM beacon
time doesn't fluctuate away from the DTIM TBTT. This would be possible
by changing the order of the beacons and adjusting the DTIM count so
that the beacon with DTIM count zero is always the first.

Noting beacon(BSS,DTIM count) you'd send:

 - at TBTT 123: beacon(A,1), beacon(B,2), beacon(C,3)
 - at TBTT 124: beacon(A,0), beacon(B,1), beacon(C,2)
 - at TBTT 125: beacon(B,0), beacon(C,1), beacon(A,3)
 - at TBTT 126: beacon(C,0), beacon(A,2), beacon(B,3)

etc.

The actual restrictions this imposes are very complicated to describe,
easier to describe and implement are the restrictions

 (a) identical beacon periods
 (b) identical DTIM periods
 (c) DTIM period > number of BSSes

that result in a subset of the possible values being allowed. Slight
relaxations could be allowed, identical DTIM periods are not really
required when it is possible to schedule them in a non-conflicting way,
i.e. (I think) when the sum over all 1/(DTIM period) is less or equal to
one (all fit) and the gcd of all is not one (possible to schedule in a
non-conflicting way).

[An example: You could have four BSSes A-D, with DTIM periods 2, 4, 8
and 16 respectively. The DTIM beacon scheduling would be
 A, B, A, C, A, B, A, D, A, B, A, C, A, B, A, - (repeat)
with all the other beacons at each period sent after the DTIM beacon.

In the empty slot ("-") you could insert another BSS with DTIM period 16
or a multiple of 16.]

[The actual restrictions don't even require using identical beacon
periods as long as there's a not too small value that divides all beacon
periods. This is very hard to describe formally.]

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: multiple MAC addresses support
  2007-11-12 11:14     ` Kalle Valo
  2007-11-13 11:26       ` Johannes Berg
@ 2007-11-13 14:14       ` Johannes Berg
  1 sibling, 0 replies; 21+ messages in thread
From: Johannes Berg @ 2007-11-13 14:14 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Jouni Malinen, Michael Buesch, linux-wireless, Ben Greear,
	Michael Wu, Jiri Benc

[-- Attachment #1: Type: text/plain, Size: 530 bytes --]


> Exactly, it is important for small mobile devices that beacons are
> sent at the correct time. For example, I have seen broken APs which
> Target Beacon Transmission Time fluctuates and Nokia N800 has high
> power consumption because of that.

The APs at university do this, they're Airespace according to the MAC
address and they just burst beacon1,2,3, wait, burst beacon1,2,3 etc.
They also send all DTIM 0 beacons at the same burst so force PS STAs to
wake up at TBTT and wait for the right beacon...

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: multiple MAC addresses support
  2007-11-13 11:26       ` Johannes Berg
@ 2007-11-15  9:35         ` Kalle Valo
  2007-11-15 16:40           ` Johannes Berg
  2007-11-18 23:02         ` Jouni Malinen
  1 sibling, 1 reply; 21+ messages in thread
From: Kalle Valo @ 2007-11-15  9:35 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Jouni Malinen, Michael Buesch, linux-wireless, Ben Greear,
	Michael Wu, Jiri Benc

Johannes Berg <johannes@sipsolutions.net> writes:

> On Mon, 2007-11-12 at 13:14 +0200, Kalle Valo wrote:
>
>> Exactly, it is important for small mobile devices that beacons are
>> sent at the correct time. For example, I have seen broken APs which
>> Target Beacon Transmission Time fluctuates and Nokia N800 has high
>> power consumption because of that.
>
> The N800 and similar devices only wake up at DTIM beacons, right?

At least N800 and N810 do, we don't want to miss any of broadcast and
multicast traffic. But I don't know how other mobile devices wakeup
for beacons.

> So another idea would be to burst beacons but make sure the DTIM
> beacon time doesn't fluctuate away from the DTIM TBTT. This would be
> possible by changing the order of the beacons and adjusting the DTIM
> count so that the beacon with DTIM count zero is always the first.

At least from my point of view that could possible. Of course it feels
like a bit of a hack, but I guess there's no clean way to implement
this.

-- 
Kalle Valo

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: multiple MAC addresses support
  2007-11-15  9:35         ` Kalle Valo
@ 2007-11-15 16:40           ` Johannes Berg
  0 siblings, 0 replies; 21+ messages in thread
From: Johannes Berg @ 2007-11-15 16:40 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Jouni Malinen, Michael Buesch, linux-wireless, Ben Greear,
	Michael Wu, Jiri Benc

[-- Attachment #1: Type: text/plain, Size: 673 bytes --]


> > The N800 and similar devices only wake up at DTIM beacons, right?
> 
> At least N800 and N810 do, we don't want to miss any of broadcast and
> multicast traffic. But I don't know how other mobile devices wakeup
> for beacons.

Well, if they wake up for all beacons they're using too much power
anyway so I'm not concerned.

> At least from my point of view that could possible. Of course it feels
> like a bit of a hack, but I guess there's no clean way to implement
> this.

Well the scheme with distributing the beacons would make it seem a lot
more like it was implemented in different MACs, but that's quite a bit
harder to implement.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: multiple MAC addresses support
  2007-11-13 11:26       ` Johannes Berg
  2007-11-15  9:35         ` Kalle Valo
@ 2007-11-18 23:02         ` Jouni Malinen
  2007-11-19 14:50           ` Johannes Berg
  1 sibling, 1 reply; 21+ messages in thread
From: Jouni Malinen @ 2007-11-18 23:02 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Kalle Valo, Michael Buesch, linux-wireless, Ben Greear,
	Michael Wu, Jiri Benc

On Tue, Nov 13, 2007 at 12:26:57PM +0100, Johannes Berg wrote:

> The N800 and similar devices only wake up at DTIM beacons, right? So
> another idea would be to burst beacons but make sure the DTIM beacon
> time doesn't fluctuate away from the DTIM TBTT. This would be possible
> by changing the order of the beacons and adjusting the DTIM count so
> that the beacon with DTIM count zero is always the first.

This could be an improvement for small number of BSSes, but if the DTIM
period starts going up, the delay in sending out multicast/broadcast
frames may not be acceptable anymore depending on application.

-- 
Jouni Malinen                                            PGP id EFC895FA

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: multiple MAC addresses support
  2007-11-12 12:02     ` Johannes Berg
@ 2007-11-18 23:47       ` Jouni Malinen
  2007-11-19 14:49         ` Johannes Berg
  0 siblings, 1 reply; 21+ messages in thread
From: Jouni Malinen @ 2007-11-18 23:47 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Michael Buesch, linux-wireless, Ben Greear, Michael Wu, Jiri Benc

On Mon, Nov 12, 2007 at 01:02:31PM +0100, Johannes Berg wrote:

> That's the point I wasn't quite sure on, would it be valid to send the
> frames in the order beacon1, beacon2, beacon3, mc1, mc1, ..., mc2, ...,
> mc3, ...?

Well, the multicast/broadcast frames would be sent after DTIM beacon
using normal frame transmission rules, so this would be possible order.
Though, this might not be that likely if one were to consider a case
where these APs are on separate radios (i.e., multiple STAs contenting
for the medium) should there be large number of buffered frames.

While this may end up being the easiest and cleanest way of implementing
multi-BSS support, this has somewhat unfortunate drawbacks for power
save stations (e.g., STAs associated with the AP1 would need to remain
awake for the extra time needed to send beacon2 and beacon3; and STAs
associated with the AP3 would need to remain awake while mc1..mc2 frames
are sent).


> On Broadcom hardware, I'm pretty sure that the transmit engine updates
> the timestamp only during transmission so that shouldn't be a problem.

OK. This will allow the STAs to remain in sync.

> Time zero is defined as TBTT, so this means we need to send the frame as
> close to TU "Beacon Interval" * N where N is a non-negative number. Is
> my interpretation correct here? If so, and because we only have a single
> TSF, doesn't this mean that we should send the beacons all together as
> quickly as possible? If we tried spreading them out we'd be sending them
> at something like "Beacon Interval" * (N + 0.25) which isn't something
> we should do, no?

TBTT could (and well, should) be separate for each BSS. In other words,
if there are four virtual BSSes using one radio (BSS1 .. BSS4), TBTT
should be different for each. If the beacon frames are send out as a
burst, TBTT2 should be TBTT1 + <time needed to send beacon1> and so on..
Similarly, there should be independent TSF for each BSS. However,
implementing this for virtual BSS (single radio) designs is going to be
quite difficult since the hardware/firmware is unlikely to support
something like this..

Consequently, the only realistic mechanism may end up being to try to
send the beacon frames as close to each other as possible. I'm not sure
whether non-AP STAs would be able to handle offset from the N *
beacon_int TUs time and still sleep properly. In theory, they could try
to sync with previous beacons, but this would be difficult to do since
beacon transmission times can vary a bit. This would be simple if we
would not need to think about power saving, but reality is likely to be
much more complex and the safest solution would to just try to send the
frame as close as possible after the N * beacon_int time.

> Another thing that I just realised is that I'm not sure whether we
> update the TSF in probe responses correctly or at all because as far as
> I can tell it's only done for the probe response microcode offload.
> We'll have to look into this.

This should be done in the same way as for Beacons, i.e., by whatever
low-level functionality is available in the transmitting path.

> Actually, what we can do is adjust the offset for each of the beacons
> differently. So when we're sending a beacon at TSF "interval * (N+.25)"
> we can round that up to "interval * (N+1)" by adjusting the TSF write
> offset. This means that stations will adopt a TSF that is larger than
> ours by a bit. If we'd do the same for probe responses (which should be
> fairly easy), would the timing work out? I'm not entirely clear about
> CFP operation etc.

Where would the TSF be adjusted? Some of these tricks could be doable in
the low-level firmware/microcode (if one is used), but this may be
difficult to do without access to such low-level location.

> > I've done some
> > experiments with configuring the hardware to use beacon interval divided
> > by number of BSSes, but ended up using burst of beacon frames instead
> > (and all BSSes were forced to use the same beacon interval).
> 
> Do you remember any reason?

Nope.. There were some issues in getting the implementation to be
stable, so that may have been the main reason. Setting the beacon
interval and related interrupts to very small values was probably not
expected in the original design.

-- 
Jouni Malinen                                            PGP id EFC895FA

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: multiple MAC addresses support
  2007-11-18 23:47       ` Jouni Malinen
@ 2007-11-19 14:49         ` Johannes Berg
  0 siblings, 0 replies; 21+ messages in thread
From: Johannes Berg @ 2007-11-19 14:49 UTC (permalink / raw)
  To: Jouni Malinen
  Cc: Michael Buesch, linux-wireless, Ben Greear, Michael Wu, Jiri Benc

[-- Attachment #1: Type: text/plain, Size: 3116 bytes --]


> Well, the multicast/broadcast frames would be sent after DTIM beacon
> using normal frame transmission rules, so this would be possible order.
> Though, this might not be that likely if one were to consider a case
> where these APs are on separate radios (i.e., multiple STAs contenting
> for the medium) should there be large number of buffered frames.

Right.

> While this may end up being the easiest and cleanest way of implementing
> multi-BSS support, this has somewhat unfortunate drawbacks for power
> save stations (e.g., STAs associated with the AP1 would need to remain
> awake for the extra time needed to send beacon2 and beacon3; and STAs
> associated with the AP3 would need to remain awake while mc1..mc2 frames
> are sent).

Yep. Hence my idea of doing DTIM 0 beacons independently.

> TBTT could (and well, should) be separate for each BSS. In other words,
> if there are four virtual BSSes using one radio (BSS1 .. BSS4), TBTT
> should be different for each. If the beacon frames are send out as a
> burst, TBTT2 should be TBTT1 + <time needed to send beacon1> and so on..
> Similarly, there should be independent TSF for each BSS. However,
> implementing this for virtual BSS (single radio) designs is going to be
> quite difficult since the hardware/firmware is unlikely to support
> something like this..

Well, I'm fairly sure Broadcom hardware would allow this because
apparently it allows subtracting/adding (?) an arbitrary (?) value to
the TSF timestamp as it is written. This could be made host-controlled
so the host keeps track of the offsets. The only requirement would be
that the beacon periods are spread out in equal intervals to allow the
microcode to schedule properly.

> > Another thing that I just realised is that I'm not sure whether we
> > update the TSF in probe responses correctly or at all because as far as
> > I can tell it's only done for the probe response microcode offload.
> > We'll have to look into this.
> 
> This should be done in the same way as for Beacons, i.e., by whatever
> low-level functionality is available in the transmitting path.

Yes. Except as far as I can tell Broadcom hardware/firmware only does it
when the *firmware* responds to probe responses, and we disabled that.

> > Actually, what we can do is adjust the offset for each of the beacons
> > differently. So when we're sending a beacon at TSF "interval * (N+.25)"
> > we can round that up to "interval * (N+1)" by adjusting the TSF write
> > offset. This means that stations will adopt a TSF that is larger than
> > ours by a bit. If we'd do the same for probe responses (which should be
> > fairly easy), would the timing work out? I'm not entirely clear about
> > CFP operation etc.
> 
> Where would the TSF be adjusted? Some of these tricks could be doable in
> the low-level firmware/microcode (if one is used), but this may be
> difficult to do without access to such low-level location.

There is such access as I described above.

I need do tests but right now I have no second wireless card at all.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC] b43: multiple MAC addresses support
  2007-11-18 23:02         ` Jouni Malinen
@ 2007-11-19 14:50           ` Johannes Berg
  0 siblings, 0 replies; 21+ messages in thread
From: Johannes Berg @ 2007-11-19 14:50 UTC (permalink / raw)
  To: Jouni Malinen
  Cc: Kalle Valo, Michael Buesch, linux-wireless, Ben Greear,
	Michael Wu, Jiri Benc

[-- Attachment #1: Type: text/plain, Size: 949 bytes --]


On Sun, 2007-11-18 at 15:02 -0800, Jouni Malinen wrote:
> On Tue, Nov 13, 2007 at 12:26:57PM +0100, Johannes Berg wrote:
> 
> > The N800 and similar devices only wake up at DTIM beacons, right? So
> > another idea would be to burst beacons but make sure the DTIM beacon
> > time doesn't fluctuate away from the DTIM TBTT. This would be possible
> > by changing the order of the beacons and adjusting the DTIM count so
> > that the beacon with DTIM count zero is always the first.
> 
> This could be an improvement for small number of BSSes, but if the DTIM
> period starts going up, the delay in sending out multicast/broadcast
> frames may not be acceptable anymore depending on application.

Well even if you have a larger number of BSSes you can spread the DTIm 0
beacons across the periods so that you have a few but not all DTIM 0
beacons at one time. And that's still an improvement over currently used
schemes.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2007-11-19 14:48 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-09  1:43 [RFC] b43: multiple MAC addresses support Johannes Berg
2007-11-09 10:33 ` Johannes Berg
2007-11-09 10:52 ` Johannes Berg
2007-11-11  2:58   ` Jouni Malinen
2007-11-12 11:14     ` Kalle Valo
2007-11-13 11:26       ` Johannes Berg
2007-11-15  9:35         ` Kalle Valo
2007-11-15 16:40           ` Johannes Berg
2007-11-18 23:02         ` Jouni Malinen
2007-11-19 14:50           ` Johannes Berg
2007-11-13 14:14       ` Johannes Berg
2007-11-12 12:02     ` Johannes Berg
2007-11-18 23:47       ` Jouni Malinen
2007-11-19 14:49         ` Johannes Berg
2007-11-09 10:53 ` [RFC] b43: fix multi MAC address hardware crypto support Johannes Berg
2007-11-09 12:39   ` Johannes Berg
2007-11-10  1:21   ` [RFC v2] " Johannes Berg
2007-11-09 12:25 ` [RFC] b43: multiple MAC addresses support Johannes Berg
2007-11-10  1:20 ` [RFC v2] " Johannes Berg
2007-11-10  1:53 ` [RFC] " Johannes Berg
2007-11-10 21:34   ` Johannes Berg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.