Re: [zd1211-devs] multicast support and ipv6

2006-11-27 Thread Benoit PAPILLAULT
Uli Kunitz wrote:

> Benoit, I'm doing the filtering with following change:
OK. I read the patch a bit fast. My apologies...

> I'm absolutely interested in test results. The patch works for me  
> here under IPv4.

Patch is working under IPv6 as well. Thanks for the rewriting it.

Benoit

-
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
___
Zd1211-devs mailing list - http://zd1211.ath.cx/
Unsubscribe: https://lists.sourceforge.net/lists/listinfo/zd1211-devs


Re: [zd1211-devs] multicast support and ipv6

2006-11-26 Thread Uli Kunitz
> IPv6 needs to ignore packets sent, which is not done in your patch.
> However, I think such filtering is not zd1211 specific and could be
> better done in the generic softmac layer. What is the process to patch
> the softmac layer? I was also wondering if filtering ALL packets whose
> sender mac is our MAC would be more appropriate? (currently, my patch
> only filters out multicast packets with sender MAC being our MAC).

Benoit, I'm doing the filtering with following change:

  @@ -771,7 +812,8 @@ static int is_data_packet_for_us(struct
  }

  return memcmp(hdr->addr1, netdev->dev_addr, ETH_ALEN) == 0 ||
-   is_multicast_ether_addr(hdr->addr1) ||
+   (is_multicast_ether_addr(hdr->addr1) &&
+memcmp(hdr->addr3, netdev->dev_addr, ETH_ALEN) != 0) ||
 (netdev->flags & IFF_PROMISC);
  }

It's exactly as you are doing, but will work also in other modes.
According to RFC2462 there are problems with removing frames
with the identical source address. So limiting it has some value.
One could implement something more complex like
updating a time-stamp variable in tx for multicast packets. And suppress
the incoming packet only if it is in a certain timw window after the tx.
I doubt that it is worth to do it.

Sharing the code with other cards, might not be possible, because the  
devices
might behave differently. For instance doing the filtering on its own.

I'm absolutely interested in test results. The patch works for me  
here under IPv4.

Cheers,

Uli
--
Uli Kunitz




-
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
___
Zd1211-devs mailing list - http://zd1211.ath.cx/
Unsubscribe: https://lists.sourceforge.net/lists/listinfo/zd1211-devs


Re: [zd1211-devs] multicast support and ipv6

2006-11-26 Thread Benoit PAPILLAULT
Ulrich Kunitz wrote:
> On 06-11-23 22:52 Benoit PAPILLAULT wrote:
> 
>> Patch (replacing the previous) is attached.
>>
>> Best regards,
>> Benoit
> 
> Benoit,
> 
> Thank's again for demonstrating how to solve the issue. I've
> reworked your patch. You can find the new patch below. Please
> check it with IPv6. I don't have here a running AP with IPv6
> enabled. 

IPv6 needs to ignore packets sent, which is not done in your patch. 
However, I think such filtering is not zd1211 specific and could be 
better done in the generic softmac layer. What is the process to patch 
the softmac layer? I was also wondering if filtering ALL packets whose 
sender mac is our MAC would be more appropriate? (currently, my patch 
only filters out multicast packets with sender MAC being our MAC).

I'll try your patch on my 2.6.18 kernel as well, later.

Best regards,
Benoit

-
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
___
Zd1211-devs mailing list - http://zd1211.ath.cx/
Unsubscribe: https://lists.sourceforge.net/lists/listinfo/zd1211-devs


Re: [zd1211-devs] multicast support and ipv6

2006-11-26 Thread Ulrich Kunitz
On 06-11-23 22:52 Benoit PAPILLAULT wrote:

> Patch (replacing the previous) is attached.
> 
> Best regards,
> Benoit

Benoit,

Thank's again for demonstrating how to solve the issue. I've
reworked your patch. You can find the new patch below. Please
check it with IPv6. I don't have here a running AP with IPv6
enabled. 

The patch is also include in my git tree.

http://www.deine-taler.de/zd1211/zd1211.git/

Please consider that the master branch compiles against 2.6.18 and
not 2.6.19. For 2.6.19 use the branch wireless-dev.

Regards,

Uli

Support for multicast adresses is implemented by supporting the
set_multicast_list() function of the network device. Address
filtering is supported by a group hash table in the device. Should
fix bugzilla.kernel.org bug 7424.

Signed-off-by: Ulrich Kunitz <[EMAIL PROTECTED]>
---
 zd_chip.c   |   13 +
 zd_chip.h   |   43 ++-
 zd_mac.c|   44 +++-
 zd_mac.h|3 +++
 zd_netdev.c |2 +-
 5 files changed, 102 insertions(+), 3 deletions(-)

diff --git a/zd_chip.c b/zd_chip.c
index bfff84c..4624379 100644
--- a/zd_chip.c
+++ b/zd_chip.c
@@ -1672,3 +1672,16 @@ int zd_rfwritev_cr_locked(struct zd_chip
 
return 0;
 }
+
+int zd_chip_set_multicast_hash(struct zd_chip *chip,
+  struct zd_mc_hash *hash)
+{
+   struct zd_ioreq32 ioreqs[] = {
+   { CR_GROUP_HASH_P1, hash->low },
+   { CR_GROUP_HASH_P2, hash->high },
+   };
+
+   dev_dbg_f(zd_chip_dev(chip), "hash l 0x%08x h 0x%08x\n",
+   ioreqs[0].value, ioreqs[1].value);
+   return zd_iowrite32a(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
diff --git a/zd_chip.h b/zd_chip.h
index 0df9d5b..6ed3fb6 100644
--- a/zd_chip.h
+++ b/zd_chip.h
@@ -395,10 +395,19 @@ #define CR_MAC_ADDR_P2CTL_REG(0x0614)
 #define CR_BSSID_P1CTL_REG(0x0618)
 #define CR_BSSID_P2CTL_REG(0x061C)
 #define CR_BCN_PLCP_CFGCTL_REG(0x0620)
+
+/* Group hash table for filtering incoming packets.
+ *
+ * The group hash table is 64 bit large and split over two parts. The first
+ * part is the lower part. The upper 6 bits of the last byte of the target
+ * address are used as index. Packets are received if the hash table bit is
+ * set. This is used for multicast handling, but for broadcasts (address
+ * ff:ff:ff:ff:ff:ff) the highest bit in the second table must also be set.
+ */
 #define CR_GROUP_HASH_P1   CTL_REG(0x0624)
 #define CR_GROUP_HASH_P2   CTL_REG(0x0628)
-#define CR_RX_TIMEOUT  CTL_REG(0x062C)
 
+#define CR_RX_TIMEOUT  CTL_REG(0x062C)
 /* Basic rates supported by the BSS. When producing ACK or CTS messages, the
  * device will use a rate in this table that is less than or equal to the rate
  * of the incoming frame which prompted the response */
@@ -850,4 +859,36 @@ int zd_chip_handle_signal_strength(struc
 
 u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status);
 
+struct zd_mc_hash {
+   u32 low;
+   u32 high;
+};
+
+static inline void zd_mc_clear(struct zd_mc_hash *hash)
+{
+   hash->low = 0;
+   /* The interfaces must always received broadcasts.
+* The hash of the broadcast address ff:ff:ff:ff:ff:ff is 63.
+*/
+   hash->high = 0x8000;
+}
+
+static inline void zd_mc_add_all(struct zd_mc_hash *hash)
+{
+   hash->low = hash->high = 0x;
+}
+
+static inline void zd_mc_add_addr(struct zd_mc_hash *hash, u8 *addr)
+{
+   unsigned int i = addr[5] >> 2;
+   if (i < 32) {
+   hash->low |= 1 << i;
+   } else {
+   hash->high |= 1 << (i-32);
+   }
+}
+
+int zd_chip_set_multicast_hash(struct zd_chip *chip,
+  struct zd_mc_hash *hash);
+
 #endif /* _ZD_CHIP_H */
diff --git a/zd_mac.c b/zd_mac.c
index 30ae0c2..5b100a3 100644
--- a/zd_mac.c
+++ b/zd_mac.c
@@ -37,6 +37,8 @@ static void housekeeping_init(struct zd_
 static void housekeeping_enable(struct zd_mac *mac);
 static void housekeeping_disable(struct zd_mac *mac);
 
+static void set_multicast_hash_handler(void *mac_ptr);
+
 int zd_mac_init(struct zd_mac *mac,
struct net_device *netdev,
struct usb_interface *intf)
@@ -51,6 +53,8 @@ int zd_mac_init(struct zd_mac *mac,
softmac_init(ieee80211_priv(netdev));
zd_chip_init(&mac->chip, netdev, intf);
housekeeping_init(mac);
+   INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler,
+ mac);
return 0;
 }
 
@@ -132,6 +136,7 @@ out:
 
 void zd_mac_clear(struct zd_mac *mac)
 {
+   flush_workqueue(zd_workqueue);
zd_chip_clear(&mac->chip);
ZD_ASSERT(!spin_is_locked(&mac->lock));
ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
@@ -245,6 +250,42 @@ int zd_mac_set_mac_address(struct net_de
return 0;
 }
 
+stati

Re: [zd1211-devs] multicast support and ipv6

2006-11-23 Thread Uli Kunitz

Benoit,

I just send my mail and received then yours.

I will rework your patch as outlined in my e-mail at the weekend.
Then it will be in my master branch for 2.6.18 and in the wireless- 
dev for 2.6.19-rc*.


Both trees are synchronized with Daniel's tree. Daniel forwards  
usually the patches

to the John Linville, the maintainer of the wireless tree.

Kind regards,

UIi

--
Uli Kunitz



-
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV___
Zd1211-devs mailing list - http://zd1211.ath.cx/
Unsubscribe: https://lists.sourceforge.net/lists/listinfo/zd1211-devs

Re: [zd1211-devs] multicast support and ipv6

2006-11-23 Thread Uli Kunitz

Benoit,

I appreciate, that you have actually provided a patch. I will  
probably not
use the code at is, I don't like particularly the kevent hacks here.  
It's simpler

and not less prone to race conditions to handle each event in its own
work function. So everything related to kevent needs to be removed.
Given the structure of our driver we would certainly implement
a zd_chip function, which gets the list of muliticast addresses and  
writes

the group hash table.

Your patch doesn't work however, because you didn't implement loopback
handling. The easy way would be to remove all inbound packets with a  
source
address, that is equal to our own. It would be perfect only to remove  
it, if we

actually send out a multicast packet some time before.

Cheers,

Uli


Am 23.11.2006 um 21:38 wrote Benoit PAPILLAULT:


Hello,

I noticed that the zd1211rw driver does not work with ipv6 since  
the autoconfiguration process requires multicast to be implemented.  
This was working with the vendor driver. I successfully ported the  
needed part of the source code to zd1211rw to add multicast support  
(in fact, the cards needs to be instruct with the proper MAC  
multicast addr in order to receive the packets intended to those  
multicast addr). It works (patch attached, against git repository  
from dsd).


However, ipv6 is still not working and i got several messages  
"wlan0: duplicate address detected!". I'm not sure yet but i think  
that multicast packets sent from STA to AP are then retransmitted  
by the AP to all STA, including the STA which has sent it!


How to make ipv6 working?

Best regards,
Benoit

diff --git a/zd_chip.c b/zd_chip.c
diff --git a/zd_def.h b/zd_def.h
diff --git a/zd_mac.c b/zd_mac.c
index 8acd168..3698ed9 100644
--- a/zd_mac.c
+++ b/zd_mac.c
@@ -36,6 +36,9 @@ static void softmac_init(struct ieee8021
 static void housekeeping_init(struct zd_mac *mac);
 static void housekeeping_enable(struct zd_mac *mac);
 static void housekeeping_disable(struct zd_mac *mac);
+static void zd_mac_kevent(void *);
+
+#define KEVENT_SET_MULTICAST 1

 int zd_mac_init(struct zd_mac *mac,
struct net_device *netdev,
@@ -51,6 +54,9 @@ int zd_mac_init(struct zd_mac *mac,
softmac_init(ieee80211_priv(netdev));
zd_chip_init(&mac->chip, netdev, intf);
housekeeping_init(mac);
+
+INIT_WORK(&mac->kevent, zd_mac_kevent, netdev);
+mac->kevent_flags = 0;
return 0;
 }

@@ -220,6 +226,85 @@ int zd_mac_stop(struct net_device *netde
return 0;
 }

+/*
+  Set the proper registers from the list of multicast addr. to  
listen to.
+  Promiscuous and allmulti modes are handled here as well. This  
function cannot

+  be called in atomic context since zd_io... function needs to sleep.
+*/
+
+void zd_mac_set_multicast_list_real(struct net_device * dev)
+{
+struct zd_mac * mac = zd_netdev_mac(dev);
+struct zd_chip * chip = &mac->chip;
+struct dev_mc_list * mc_list;
+unsigned int i;
+u32 tmp;
+
+/* check that the interface is UP */
+if (!(dev->flags & IFF_UP))
+return;
+
+zd_iowrite32(chip, CR_GROUP_HASH_P1, 0);
+zd_iowrite32(chip, CR_GROUP_HASH_P2, 0x8000);
+
+for (i=0, mc_list=dev->mc_list;
+ imc_count; i++, mc_list = mc_list->next) {
+
+u8 val;
+
+printk(__FILE__ " : multicast " MAC_FMT "\n",
+   MAC_ARG(mc_list->dmi_addr));
+
+val = mc_list->dmi_addr[5] >> 2;
+if (val < 32) {
+zd_ioread32(chip, CR_GROUP_HASH_P1, &tmp);
+tmp |= 1 << val;
+zd_iowrite32(chip, CR_GROUP_HASH_P1, tmp);
+} else {
+val -= 32;
+zd_ioread32(chip, CR_GROUP_HASH_P2, &tmp);
+tmp |= 1 << val;
+zd_iowrite32(chip, CR_GROUP_HASH_P2, tmp);
+}
+}
+
+if ((dev->flags & IFF_PROMISC) ||
+(dev->flags & IFF_ALLMULTI)) {
+zd_iowrite32(chip, CR_GROUP_HASH_P1, 0x);
+zd_iowrite32(chip, CR_GROUP_HASH_P2, 0x);
+}
+
+zd_ioread32(chip, CR_GROUP_HASH_P1, &tmp);
+printk(__FILE__ " : GroupHashP1 = %x\n", tmp);
+zd_ioread32(chip, CR_GROUP_HASH_P2, &tmp);
+printk(__FILE__ " : GroupHashP2 = %x\n", tmp);
+}
+
+/*
+  This is the function called by the netdev layer. This function  
is in an
+  atomic context and such registers cannot be set directly. As  
such, the work
+  is defered to the default workqueue, which will call zd_mac_keven 
().

+*/
+
+void zd_mac_set_multicast_list(struct net_device * dev)
+{
+struct zd_mac * mac = zd_netdev_mac(dev);
+
+set_bit(KEVENT_SET_MULTICAST, &mac->kevent_flags);
+schedule_work(&mac->kevent);
+}
+
+void zd_mac_kevent(void * data)
+{
+struct net_device * dev = (struct net_device *) data;
+struct zd_mac * mac = zd_netdev_mac(dev);
+
+if (test_bit(KEVENT_SET_MULTICAST, &mac->kevent_flags)) {
+zd_mac_set_multicast_list_real(dev);
+clear_bit(KEVENT_SET_MULTICAST, &mac->kevent_fl

Re: [zd1211-devs] multicast support and ipv6

2006-11-23 Thread Benoit PAPILLAULT

Benoit PAPILLAULT wrote:

Hello,

I noticed that the zd1211rw driver does not work with ipv6 since the 
autoconfiguration process requires multicast to be implemented. This was 
working with the vendor driver. I successfully ported the needed part of 
the source code to zd1211rw to add multicast support (in fact, the cards 
needs to be instruct with the proper MAC multicast addr in order to 
receive the packets intended to those multicast addr). It works (patch 
attached, against git repository from dsd).


However, ipv6 is still not working and i got several messages "wlan0: 
duplicate address detected!". I'm not sure yet but i think that 
multicast packets sent from STA to AP are then retransmitted by the AP 
to all STA, including the STA which has sent it!


How to make ipv6 working?

Best regards,
Benoit


I found it. Broadcast/multicast packets sent by the AP are retransmitted 
by the AP and as such, received by the STA. Reading the vendor driver 
and the 802.11 specs, I added a filter against broadcast/multicast 
packets whose source address (SA) is ours.


IPv6 is now working!

Patch (replacing the previous) is attached.

Best regards,
Benoit

diff --git a/zd_chip.c b/zd_chip.c
diff --git a/zd_def.h b/zd_def.h
diff --git a/zd_mac.c b/zd_mac.c
index 8acd168..fac9d65 100644
--- a/zd_mac.c
+++ b/zd_mac.c
@@ -36,6 +36,9 @@ static void softmac_init(struct ieee8021
 static void housekeeping_init(struct zd_mac *mac);
 static void housekeeping_enable(struct zd_mac *mac);
 static void housekeeping_disable(struct zd_mac *mac);
+static void zd_mac_kevent(void *);
+
+#define KEVENT_SET_MULTICAST 1
 
 int zd_mac_init(struct zd_mac *mac,
 	struct net_device *netdev,
@@ -51,6 +54,9 @@ int zd_mac_init(struct zd_mac *mac,
 	softmac_init(ieee80211_priv(netdev));
 	zd_chip_init(&mac->chip, netdev, intf);
 	housekeeping_init(mac);
+
+INIT_WORK(&mac->kevent, zd_mac_kevent, netdev);
+mac->kevent_flags = 0;
 	return 0;
 }
 
@@ -220,6 +226,85 @@ int zd_mac_stop(struct net_device *netde
 	return 0;
 }
 
+/*
+  Set the proper registers from the list of multicast addr. to listen to.
+  Promiscuous and allmulti modes are handled here as well. This function cannot
+  be called in atomic context since zd_io... function needs to sleep.
+*/
+
+void zd_mac_set_multicast_list_real(struct net_device * dev)
+{
+struct zd_mac * mac = zd_netdev_mac(dev);
+struct zd_chip * chip = &mac->chip;
+struct dev_mc_list * mc_list;
+unsigned int i;
+u32 tmp;
+
+/* check that the interface is UP */
+if (!(dev->flags & IFF_UP))
+return;
+
+zd_iowrite32(chip, CR_GROUP_HASH_P1, 0);
+zd_iowrite32(chip, CR_GROUP_HASH_P2, 0x8000);
+
+for (i=0, mc_list=dev->mc_list;
+ imc_count; i++, mc_list = mc_list->next) {
+
+u8 val;
+
+printk(__FILE__ " : multicast " MAC_FMT "\n",
+   MAC_ARG(mc_list->dmi_addr));
+
+val = mc_list->dmi_addr[5] >> 2;
+if (val < 32) {
+zd_ioread32(chip, CR_GROUP_HASH_P1, &tmp);
+tmp |= 1 << val;
+zd_iowrite32(chip, CR_GROUP_HASH_P1, tmp);
+} else {
+val -= 32;
+zd_ioread32(chip, CR_GROUP_HASH_P2, &tmp);
+tmp |= 1 << val;
+zd_iowrite32(chip, CR_GROUP_HASH_P2, tmp);
+}
+}
+
+if ((dev->flags & IFF_PROMISC) ||
+(dev->flags & IFF_ALLMULTI)) {
+zd_iowrite32(chip, CR_GROUP_HASH_P1, 0x);
+zd_iowrite32(chip, CR_GROUP_HASH_P2, 0x);
+}
+
+zd_ioread32(chip, CR_GROUP_HASH_P1, &tmp);
+printk(__FILE__ " : GroupHashP1 = %x\n", tmp);
+zd_ioread32(chip, CR_GROUP_HASH_P2, &tmp);
+printk(__FILE__ " : GroupHashP2 = %x\n", tmp);
+}
+
+/*
+  This is the function called by the netdev layer. This function is in an
+  atomic context and such registers cannot be set directly. As such, the work
+  is defered to the default workqueue, which will call zd_mac_keven().
+*/
+
+void zd_mac_set_multicast_list(struct net_device * dev)
+{
+struct zd_mac * mac = zd_netdev_mac(dev);
+
+set_bit(KEVENT_SET_MULTICAST, &mac->kevent_flags);
+schedule_work(&mac->kevent);
+}
+
+void zd_mac_kevent(void * data)
+{
+struct net_device * dev = (struct net_device *) data;
+struct zd_mac * mac = zd_netdev_mac(dev);
+
+if (test_bit(KEVENT_SET_MULTICAST, &mac->kevent_flags)) {
+zd_mac_set_multicast_list_real(dev);
+clear_bit(KEVENT_SET_MULTICAST, &mac->kevent_flags);
+}
+}
+
 int zd_mac_set_mac_address(struct net_device *netdev, void *p)
 {
 	int r;
@@ -771,6 +856,14 @@ static int is_data_packet_for_us(struct
 		IEEE80211_FCTL_FROMDS ||
 		memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) != 0)
 			return 0;
+
+/* broadcast or multicast packets are resent by the AP, so we
+   ignore packets we sent */
+
+if (is_multicast_ether_addr(hdr->addr1) && 
+(memcmp(hdr->addr3, netdev->dev_addr, ETH