netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/9] d80211: pull request
@ 2006-07-18 15:45 Jiri Benc
  2006-07-18 15:45 ` [PATCH 1/9] d80211: do not receive through master interface when not scanning Jiri Benc
                   ` (10 more replies)
  0 siblings, 11 replies; 14+ messages in thread
From: Jiri Benc @ 2006-07-18 15:45 UTC (permalink / raw)
  To: netdev

Please pull from
git://git.kernel.org/pub/scm/linux/kernel/git/jbenc/dscape.git master
to obtain following patches:

Jiri Benc:
      d80211: do not receive through master interface when not scanning
      d80211: host_gen_beacon_template flag
      d80211: better deallocation of mdev
      d80211: fix receiving through virtual interfaces
      d80211: fix defragmentation
      d80211: optimize defragmentation
      d80211: SET_NETDEV_DEV for non-master devices

Michael Wu:
      d80211: Replace rc4 code with crypto api arc4
      d80211: Add sparse bitwise annotations

 include/net/d80211.h         |   12 +-
 include/net/d80211_mgmt.h    |   42 +++---
 net/d80211/Kconfig           |    1 
 net/d80211/ieee80211.c       |  290 ++++++++++++++++++++++++++++--------------
 net/d80211/ieee80211_i.h     |   19 ++-
 net/d80211/ieee80211_iface.c |   21 +++
 net/d80211/ieee80211_ioctl.c |    2 
 net/d80211/ieee80211_sta.c   |    7 -
 net/d80211/tkip.c            |   14 +-
 net/d80211/tkip.h            |   10 +
 net/d80211/wep.c             |  193 ++++++----------------------
 net/d80211/wep.h             |   11 +-
 net/d80211/wpa.c             |    8 +
 13 files changed, 327 insertions(+), 303 deletions(-)

-- 
Jiri Benc
SUSE Labs

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

* [PATCH 1/9] d80211: do not receive through master interface when not scanning
  2006-07-18 15:45 [PATCH 0/9] d80211: pull request Jiri Benc
@ 2006-07-18 15:45 ` Jiri Benc
  2006-07-18 15:45 ` [PATCH 2/9] d80211: host_gen_beacon_template flag Jiri Benc
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Jiri Benc @ 2006-07-18 15:45 UTC (permalink / raw)
  To: netdev

Arrived packets should not go into master interface except when scanning
- it leads to duplicate packets reception. This also fixes a race when
scanning is finished during invoking of rx handlers.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c   |   17 +++++++++++++++--
 net/d80211/ieee80211_i.h |    1 +
 2 files changed, 16 insertions(+), 2 deletions(-)

62cefb2dabe7ea740481200408a07a797b7281ab
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 7ceef10..18d910d 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -3346,6 +3346,12 @@ ieee80211_rx_h_passive_scan(struct ieee8
                 }
         }
 
+	if (unlikely(rx->u.rx.in_scan)) {
+		/* scanning finished during invoking of handlers */
+		I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
+		return TXRX_DROP;
+	}
+
         return TXRX_CONTINUE;
 }
 
@@ -3537,6 +3543,9 @@ void __ieee80211_rx(struct net_device *d
 		goto end;
         }
 
+	if (unlikely(local->sta_scanning || local->scan.in_scan))
+		rx.u.rx.in_scan = 1;
+
 	if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS) &&
 	    !local->iff_promiscs && !multicast) {
 		rx.dev = sta->dev;
@@ -3579,11 +3588,15 @@ void __ieee80211_rx(struct net_device *d
 					if (memcmp(sdata->dev->dev_addr,
 						   hdr->addr1, ETH_ALEN) != 0)
 						continue;
-				} else if (!local->sta_scanning &&
-					   !local->scan.in_scan &&
+				} else if (!rx.u.rx.in_scan &&
 					   !ieee80211_bssid_match(bssid,
 							sdata->dev->dev_addr))
 					continue;
+				if (sdata->dev == sdata->master &&
+				    !rx.u.rx.in_scan)
+					/* do not receive anything via
+					 * master device when not scanning */
+					continue;
 				break;
 			case IEEE80211_IF_TYPE_WDS:
 				if (bssid ||
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 0409c52..9e1fff2 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -137,6 +137,7 @@ struct ieee80211_txrx_data {
 			struct ieee80211_rx_status *status;
 			int sent_ps_buffered;
 			int queue;
+			int in_scan:1;
 		} rx;
 	} u;
 #ifdef CONFIG_HOSTAPD_WPA_TESTING
-- 
1.3.0


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

* [PATCH 2/9] d80211: host_gen_beacon_template flag
  2006-07-18 15:45 [PATCH 0/9] d80211: pull request Jiri Benc
  2006-07-18 15:45 ` [PATCH 1/9] d80211: do not receive through master interface when not scanning Jiri Benc
@ 2006-07-18 15:45 ` Jiri Benc
  2006-07-18 15:45 ` [PATCH 3/9] d80211: better deallocation of mdev Jiri Benc
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Jiri Benc @ 2006-07-18 15:45 UTC (permalink / raw)
  To: netdev

This is a partial support for devices requiring beacon template. Please note
that there is no support for PS mode for such cards yet.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 include/net/d80211.h         |    6 ++++++
 net/d80211/ieee80211.c       |   22 +++++++++++++++++++++-
 net/d80211/ieee80211_i.h     |    1 +
 net/d80211/ieee80211_ioctl.c |    2 +-
 4 files changed, 29 insertions(+), 2 deletions(-)

00f22bc8c0745572f3aebd5b6fd7a721199b3a4a
diff --git a/include/net/d80211.h b/include/net/d80211.h
index 6ae4325..fdb082c 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -349,6 +349,9 @@ struct ieee80211_if_init_conf {
  *	only during config_interface() callback (so copy the value somewhere
  *	if you need it).
  * @generic_elem_len: length of the generic element.
+ * @beacon: beacon template. Valid only if @host_gen_beacon_template in
+ *	&struct ieee80211_hw is set. The driver is responsible of freeing
+ *	the sk_buff.
  *
  * This structure is passed to config_interface() callback of
  * &struct ieee80211_hw.
@@ -360,6 +363,7 @@ struct ieee80211_if_conf {
 	size_t ssid_len;
 	u8 *generic_elem;
 	size_t generic_elem_len;
+	struct sk_buff *beacon;
 };
 
 typedef enum { ALG_NONE, ALG_WEP, ALG_TKIP, ALG_CCMP, ALG_NULL }
@@ -439,6 +443,8 @@ struct ieee80211_hw {
 	 * beacon frame. */
 	int host_gen_beacon:1;
 
+	/* The device needs to be supplied with a beacon template only. */
+	int host_gen_beacon_template:1;
 
 	/* Some devices handle decryption internally and do not
 	 * indicate whether the frame was encrypted (unencrypted frames
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 18d910d..549c8a4 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1900,7 +1900,8 @@ ieee80211_get_buffered_bc(struct net_dev
 	return skb;
 }
 
-int ieee80211_if_config(struct net_device *dev)
+static int __ieee80211_if_config(struct net_device *dev,
+				 struct sk_buff *beacon)
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = dev->ieee80211_ptr;
@@ -1923,10 +1924,29 @@ int ieee80211_if_config(struct net_devic
 		conf.ssid_len = sdata->u.ap.ssid_len;
 		conf.generic_elem = sdata->u.ap.generic_elem;
 		conf.generic_elem_len = sdata->u.ap.generic_elem_len;
+		conf.beacon = beacon;
 	}
 	return local->hw->config_interface(local->mdev, dev->ifindex, &conf);
 }
 
+int ieee80211_if_config(struct net_device *dev)
+{
+	return __ieee80211_if_config(dev, NULL);
+}
+
+int ieee80211_if_config_beacon(struct net_device *dev)
+{
+	struct ieee80211_local *local = dev->ieee80211_ptr;
+	struct sk_buff *skb;
+
+	if (!local->hw->host_gen_beacon_template)
+		return 0;
+	skb = ieee80211_beacon_get(local->mdev, dev->ifindex, NULL);
+	if (!skb)
+		return -ENOMEM;
+	return __ieee80211_if_config(dev, skb);
+}
+
 int ieee80211_hw_config(struct net_device *dev)
 {
 	struct ieee80211_local *local = dev->ieee80211_ptr;
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 9e1fff2..7ffeae2 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -546,6 +546,7 @@ struct sta_attribute {
 void ieee80211_release_hw(struct ieee80211_local *local);
 int ieee80211_hw_config(struct net_device *dev);
 int ieee80211_if_config(struct net_device *dev);
+int ieee80211_if_config_beacon(struct net_device *dev);
 struct ieee80211_key_conf *
 ieee80211_key_data2conf(struct ieee80211_local *local,
 			struct ieee80211_key *data);
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 7c2a847..d73693e 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -110,7 +110,7 @@ static int ieee80211_ioctl_set_beacon(st
 		}
 	}
 
-	return 0;
+	return ieee80211_if_config_beacon(dev);
 }
 
 
-- 
1.3.0


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

* [PATCH 3/9] d80211: better deallocation of mdev
  2006-07-18 15:45 [PATCH 0/9] d80211: pull request Jiri Benc
  2006-07-18 15:45 ` [PATCH 1/9] d80211: do not receive through master interface when not scanning Jiri Benc
  2006-07-18 15:45 ` [PATCH 2/9] d80211: host_gen_beacon_template flag Jiri Benc
@ 2006-07-18 15:45 ` Jiri Benc
  2006-07-19  3:07   ` Simon Barber
  2006-07-18 15:45 ` [PATCH 4/9] d80211: fix receiving through virtual interfaces Jiri Benc
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 14+ messages in thread
From: Jiri Benc @ 2006-07-18 15:45 UTC (permalink / raw)
  To: netdev

Master device and ieee80211_local are allocated separately now, so master
device can be freed by the same function as other virtual interfaces.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c       |    2 +-
 net/d80211/ieee80211_iface.c |    3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

603ee5045dad050a66b94a847cd5385fc7678ce9
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 549c8a4..3d7091a 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -4534,7 +4534,7 @@ void ieee80211_free_hw(struct net_device
 {
 	struct ieee80211_local *local = dev->ieee80211_ptr;
 
-	free_netdev(dev);
+	ieee80211_if_free(dev);
 	ieee80211_dev_free(local);
 }
 
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index 5abd713..566bb36 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -337,7 +337,8 @@ void ieee80211_if_free(struct net_device
 {
 	struct ieee80211_local *local = dev->ieee80211_ptr;
 
-	BUG_ON(dev == local->mdev || dev == local->apdev);
+	/* local->apdev must be NULL when freeing management interface */
+	BUG_ON(dev == local->apdev);
 	free_netdev(dev);
 }
 
-- 
1.3.0


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

* [PATCH 4/9] d80211: fix receiving through virtual interfaces
  2006-07-18 15:45 [PATCH 0/9] d80211: pull request Jiri Benc
                   ` (2 preceding siblings ...)
  2006-07-18 15:45 ` [PATCH 3/9] d80211: better deallocation of mdev Jiri Benc
@ 2006-07-18 15:45 ` Jiri Benc
  2006-07-18 15:45 ` [PATCH 5/9] d80211: fix defragmentation Jiri Benc
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Jiri Benc @ 2006-07-18 15:45 UTC (permalink / raw)
  To: netdev

This fixes several problems with receiving when multiple interfaces are
present or when some interface is in promiscious mode:

- Packet type (PACKET_HOST and PACKET_OTHER_HOST) is set correctly now.
- Failed decryption of a frame is reported only once for each frame.
- Failed decryption of a frame not destined to the interface (e.g. when the
  interface is in promisc mode) is not reported.
- Channel utilization is counted correctly (i.e. once for each frame only,
  independently on number of active virtual interfaces). To achieve this,
  ieee80211_rx_handlers needed to be separated into new
  ieee80211_rx_handlers and ieee80211_rx_pre_handlers structures.

Defragmentation still doesn't work correctly in promisc mode. This is fixed
by subsequent patches.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c   |  171 +++++++++++++++++++++++++++++++---------------
 net/d80211/ieee80211_i.h |    5 +
 net/d80211/wpa.c         |    4 +
 3 files changed, 124 insertions(+), 56 deletions(-)

53a84c48f3862bebeccf6b97f750be1e42f2bf14
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 3d7091a..0b6d8a5 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -2461,27 +2461,15 @@ ieee80211_rx_h_data(struct ieee80211_txr
 		memcpy(ehdr->h_source, src, ETH_ALEN);
                 ehdr->h_proto = len;
 	}
-
-        if (rx->sta && !rx->sta->assoc_ap &&
-	    !(rx->sta && (rx->sta->flags & WLAN_STA_WDS)))
-                skb->dev = rx->sta->dev;
-        else
-                skb->dev = dev;
+	skb->dev = dev;
 
         skb2 = NULL;
-        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-        /*
-         * don't count the master since the low level code
-         * counts it already for us.
-         */
-        if (skb->dev != sdata->master) {
-		sdata->stats.rx_packets++;
-		sdata->stats.rx_bytes += skb->len;
-        }
+	sdata->stats.rx_packets++;
+	sdata->stats.rx_bytes += skb->len;
 
 	if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP
-	    || sdata->type == IEEE80211_IF_TYPE_VLAN)) {
+	    || sdata->type == IEEE80211_IF_TYPE_VLAN) && rx->u.rx.ra_match) {
 		if (is_multicast_ether_addr(skb->data)) {
 			/* send multicast frames both to higher layers in
 			 * local net stack and back to the wireless media */
@@ -2758,13 +2746,14 @@ #endif /* IEEE80211_VERBOSE_DEBUG_PS */
 
 
 static ieee80211_txrx_result
-ieee80211_rx_h_ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
+ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
 {
 	struct sk_buff *skb;
 	int no_pending_pkts;
 
 	if (likely(!rx->sta || WLAN_FC_GET_TYPE(rx->fc) != WLAN_FC_TYPE_CTRL ||
-		   WLAN_FC_GET_STYPE(rx->fc) != WLAN_FC_STYPE_PSPOLL))
+		   WLAN_FC_GET_STYPE(rx->fc) != WLAN_FC_STYPE_PSPOLL ||
+		   !rx->u.rx.ra_match))
 		return TXRX_CONTINUE;
 
 	skb = skb_dequeue(&rx->sta->tx_filtered);
@@ -3040,8 +3029,10 @@ ieee80211_rx_h_check(struct ieee80211_tx
 		if (unlikely(rx->fc & WLAN_FC_RETRY &&
 			     rx->sta->last_seq_ctrl[rx->u.rx.queue] ==
 			     hdr->seq_ctrl)) {
-			rx->local->dot11FrameDuplicateCount++;
-			rx->sta->num_duplicates++;
+			if (rx->u.rx.ra_match) {
+				rx->local->dot11FrameDuplicateCount++;
+				rx->sta->num_duplicates++;
+			}
 			return TXRX_DROP;
 		} else
 			rx->sta->last_seq_ctrl[rx->u.rx.queue] = hdr->seq_ctrl;
@@ -3055,7 +3046,9 @@ ieee80211_rx_h_check(struct ieee80211_tx
 		return TXRX_DROP;
 	}
 
-	if (memcmp(rx->dev->dev_addr, hdr->addr1, ETH_ALEN) == 0)
+	if (!rx->u.rx.ra_match)
+		rx->skb->pkt_type = PACKET_OTHERHOST;
+	else if (memcmp(rx->dev->dev_addr, hdr->addr1, ETH_ALEN) == 0)
 		rx->skb->pkt_type = PACKET_HOST;
 	else if (is_multicast_ether_addr(hdr->addr1)) {
 		if (is_broadcast_ether_addr(hdr->addr1))
@@ -3078,8 +3071,10 @@ ieee80211_rx_h_check(struct ieee80211_tx
 		       WLAN_FC_GET_STYPE(rx->fc) == WLAN_FC_STYPE_PSPOLL)) &&
 		     rx->sdata->type != IEEE80211_IF_TYPE_IBSS &&
 		     (!rx->sta || !(rx->sta->flags & WLAN_STA_ASSOC)))) {
-		if (!(rx->fc & WLAN_FC_FROMDS) && !(rx->fc & WLAN_FC_TODS)) {
-			/* Drop IBSS frames silently. */
+		if ((!(rx->fc & WLAN_FC_FROMDS) && !(rx->fc & WLAN_FC_TODS)) ||
+		    !rx->u.rx.ra_match) {
+			/* Drop IBSS frames and frames for other hosts
+			 * silently. */
 			return TXRX_DROP;
 		}
 
@@ -3111,6 +3106,8 @@ ieee80211_rx_h_check(struct ieee80211_tx
 				rx->key = rx->sdata->keys[keyidx];
 			}
 			if (!rx->key) {
+				if (!rx->u.rx.ra_match)
+					return TXRX_DROP;
 				printk(KERN_DEBUG "%s: RX WEP frame with "
 				       "unknown keyidx %d (A1=" MACSTR " A2="
 				       MACSTR " A3=" MACSTR ")\n",
@@ -3126,7 +3123,7 @@ ieee80211_rx_h_check(struct ieee80211_tx
 		}
         }
 
-	if (rx->fc & WLAN_FC_ISWEP && rx->key) {
+	if (rx->fc & WLAN_FC_ISWEP && rx->key && rx->u.rx.ra_match) {
 		rx->key->tx_rx_count++;
 		if (unlikely(rx->local->key_tx_rx_threshold &&
 			     rx->key->tx_rx_count >
@@ -3166,6 +3163,10 @@ ieee80211_rx_h_sta_process(struct ieee80
 		 */
 		sta->last_rx = jiffies;
 	}
+
+	if (!rx->u.rx.ra_match)
+		return TXRX_CONTINUE;
+
 	sta->rx_fragments++;
 	sta->rx_bytes += rx->skb->len;
 	sta->last_rssi = rx->u.rx.status->ssi;
@@ -3201,7 +3202,7 @@ ieee80211_rx_h_wep_weak_iv_detection(str
 {
 	if (!rx->sta || !(rx->fc & WLAN_FC_ISWEP) ||
 	    WLAN_FC_GET_TYPE(rx->fc) != WLAN_FC_TYPE_DATA || !rx->key ||
-	    rx->key->alg != ALG_WEP)
+	    rx->key->alg != ALG_WEP || !rx->u.rx.ra_match)
 		return TXRX_CONTINUE;
 
 	/* Check for weak IVs, if hwaccel did not remove IV from the frame */
@@ -3258,7 +3259,7 @@ static ieee80211_txrx_result
 ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx)
 {
 	if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb) &&
-	    rx->sdata->type != IEEE80211_IF_TYPE_STA) {
+	    rx->sdata->type != IEEE80211_IF_TYPE_STA && rx->u.rx.ra_match) {
 		/* Pass both encrypted and unencrypted EAPOL frames to user
 		 * space for processing. */
 		ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status,
@@ -3311,6 +3312,10 @@ static ieee80211_txrx_result
 ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx)
 {
         struct ieee80211_sub_if_data *sdata;
+
+	if (!rx->u.rx.ra_match)
+		return TXRX_DROP;
+
 	sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
 	if ((sdata->type == IEEE80211_IF_TYPE_STA ||
 	     sdata->type == IEEE80211_IF_TYPE_IBSS) &&
@@ -3349,7 +3354,8 @@ ieee80211_rx_h_passive_scan(struct ieee8
                 fc = le16_to_cpu(hdr->frame_control);
 
                 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
-		    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) {
+		    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON &&
+		    rx->dev == local->mdev) {
 			local->scan.rx_beacon++;
 			/* Need to trim FCS here because it is normally
 			 * removed only after this passive scan handler. */
@@ -3500,14 +3506,16 @@ static void ieee80211_rx_michael_mic_rep
 	rx->skb = NULL;
 }
 
-static inline void ieee80211_invoke_rx_handlers(struct ieee80211_local *local,
-						struct ieee80211_txrx_data *rx,
-						struct sta_info *sta)
+static inline ieee80211_txrx_result __ieee80211_invoke_rx_handlers(
+				struct ieee80211_local *local,
+				ieee80211_rx_handler *handlers,
+				struct ieee80211_txrx_data *rx,
+				struct sta_info *sta)
 {
 	ieee80211_rx_handler *handler;
         ieee80211_txrx_result res = TXRX_DROP;
 
-	for (handler = local->rx_handlers; *handler != NULL; handler++) {
+	for (handler = handlers; *handler != NULL; handler++) {
 		res = (*handler)(rx);
 		if (res != TXRX_CONTINUE) {
 			if (res == TXRX_DROP) {
@@ -3521,8 +3529,19 @@ static inline void ieee80211_invoke_rx_h
 		}
 	}
 
+	if (res == TXRX_DROP) {
+		dev_kfree_skb(rx->skb);
+	}
+	return res;
+}
 
-	if (res == TXRX_DROP || *handler == NULL)
+static inline void ieee80211_invoke_rx_handlers(struct ieee80211_local *local,
+						ieee80211_rx_handler *handlers,
+						struct ieee80211_txrx_data *rx,
+						struct sta_info *sta)
+{
+	if (__ieee80211_invoke_rx_handlers(local, handlers, rx, sta) ==
+	    TXRX_CONTINUE)
 		dev_kfree_skb(rx->skb);
 }
 
@@ -3566,37 +3585,57 @@ void __ieee80211_rx(struct net_device *d
 	if (unlikely(local->sta_scanning || local->scan.in_scan))
 		rx.u.rx.in_scan = 1;
 
+	if (__ieee80211_invoke_rx_handlers(local, local->rx_pre_handlers, &rx,
+					   sta) != TXRX_CONTINUE)
+		goto end;
+	skb = rx.skb;
+
 	if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS) &&
 	    !local->iff_promiscs && !multicast) {
 		rx.dev = sta->dev;
 		rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
-		ieee80211_invoke_rx_handlers(local, &rx, sta);
+		rx.u.rx.ra_match = 1;
+		ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx,
+					     sta);
 	} else {
 		struct ieee80211_sub_if_data *prev = NULL;
 		struct sk_buff *skb_new;
 		u8 *bssid = ieee80211_get_bssid(hdr, skb->len);
 
 		list_for_each_entry(sdata, &local->sub_if_list, list) {
+			rx.u.rx.ra_match = 1;
 			switch (sdata->type) {
 			case IEEE80211_IF_TYPE_STA:
-				if (!bssid || memcmp(sdata->u.sta.bssid,
-						     bssid, ETH_ALEN) != 0)
-					continue;
-				if (!multicast && !sdata->promisc &&
-				    memcmp(sdata->dev->dev_addr, hdr->addr1,
-					   ETH_ALEN) != 0)
+				if (!bssid)
 					continue;
+				if (!ieee80211_bssid_match(bssid,
+							sdata->u.sta.bssid)) {
+					if (!rx.u.rx.in_scan)
+						continue;
+					rx.u.rx.ra_match = 0;
+				} else if (!multicast &&
+					   memcmp(sdata->dev->dev_addr,
+						  hdr->addr1, ETH_ALEN) != 0) {
+					if (!sdata->promisc)
+						continue;
+					rx.u.rx.ra_match = 0;
+				}
 				break;
 			case IEEE80211_IF_TYPE_IBSS:
-				if (!bssid ||
-				    !ieee80211_bssid_match(bssid,
-							   sdata->u.sta.bssid))
-					continue;
-				if (!multicast && !sdata->promisc &&
-				    memcmp(sdata->dev->dev_addr, hdr->addr1,
-					   ETH_ALEN) != 0)
+				if (!bssid)
 					continue;
-				if (sta == NULL) {
+				if (!ieee80211_bssid_match(bssid,
+							sdata->u.sta.bssid)) {
+					if (!rx.u.rx.in_scan)
+						continue;
+					rx.u.rx.ra_match = 0;
+				} else if (!multicast &&
+					   memcmp(sdata->dev->dev_addr,
+						  hdr->addr1, ETH_ALEN) != 0) {
+					if (!sdata->promisc)
+						continue;
+					rx.u.rx.ra_match = 0;
+				} else if (sta == NULL) {
 					sta = rx.sta =
 						ieee80211_ibss_add_sta(dev, skb, bssid,
 								       hdr->addr2);
@@ -3608,10 +3647,12 @@ void __ieee80211_rx(struct net_device *d
 					if (memcmp(sdata->dev->dev_addr,
 						   hdr->addr1, ETH_ALEN) != 0)
 						continue;
-				} else if (!rx.u.rx.in_scan &&
-					   !ieee80211_bssid_match(bssid,
-							sdata->dev->dev_addr))
-					continue;
+				} else if (!ieee80211_bssid_match(bssid,
+							sdata->dev->dev_addr)) {
+					if (!rx.u.rx.in_scan)
+						continue;
+					rx.u.rx.ra_match = 0;
+				}
 				if (sdata->dev == sdata->master &&
 				    !rx.u.rx.in_scan)
 					/* do not receive anything via
@@ -3641,7 +3682,9 @@ void __ieee80211_rx(struct net_device *d
 				rx.skb = skb_new;
 				rx.dev = prev->dev;
 				rx.sdata = prev;
-				ieee80211_invoke_rx_handlers(local, &rx, sta);
+				ieee80211_invoke_rx_handlers(local,
+							     local->rx_handlers,
+							     &rx, sta);
 			}
 			prev = sdata;
 		}
@@ -3649,7 +3692,8 @@ void __ieee80211_rx(struct net_device *d
 			rx.skb = skb;
 			rx.dev = prev->dev;
 			rx.sdata = prev;
-			ieee80211_invoke_rx_handlers(local, &rx, sta);
+			ieee80211_invoke_rx_handlers(local, local->rx_handlers,
+						     &rx, sta);
 		} else
 			dev_kfree_skb(skb);
 	}
@@ -3763,11 +3807,17 @@ ieee80211_rx_h_load_stats(struct ieee802
         local->channel_use_raw += load;
 	if (rx->sta)
 		rx->sta->channel_use_raw += load;
-        rx->sdata->channel_use_raw += load;
+	rx->u.rx.load = load;
 
 	return TXRX_CONTINUE;
 }
 
+static ieee80211_txrx_result
+ieee80211_rx_h_if_stats(struct ieee80211_txrx_data *rx)
+{
+	rx->sdata->channel_use_raw += rx->u.rx.load;
+	return TXRX_CONTINUE;
+}
 
 static void ieee80211_stat_refresh(unsigned long data)
 {
@@ -4111,10 +4161,18 @@ #endif /* IEEE80211_LEDS */
 /* TODO: implement register/unregister functions for adding TX/RX handlers
  * into ordered list */
 
-static ieee80211_rx_handler ieee80211_rx_handlers[] =
+/* rx_pre handlers don't have dev and sdata fields available in
+ * ieee80211_txrx_data */
+static ieee80211_rx_handler ieee80211_rx_pre_handlers[] =
 {
 	ieee80211_rx_h_parse_qos,
 	ieee80211_rx_h_load_stats,
+	NULL
+};
+
+static ieee80211_rx_handler ieee80211_rx_handlers[] =
+{
+	ieee80211_rx_h_if_stats,
 	ieee80211_rx_h_monitor,
 	ieee80211_rx_h_passive_scan,
 	ieee80211_rx_h_check,
@@ -4124,7 +4182,7 @@ static ieee80211_rx_handler ieee80211_rx
 	ieee80211_rx_h_wep_weak_iv_detection,
 	ieee80211_rx_h_wep_decrypt,
 	ieee80211_rx_h_defragment,
-	ieee80211_rx_h_ieee80211_rx_h_ps_poll,
+	ieee80211_rx_h_ps_poll,
 	ieee80211_rx_h_michael_mic_verify,
 	/* this must be after decryption - so header is counted in MPDU mic
 	 * must be before pae and data, so QOS_DATA format frames
@@ -4282,6 +4340,7 @@ struct net_device *ieee80211_alloc_hw(si
 			   NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
 
 	local->mdev = mdev;
+	local->rx_pre_handlers = ieee80211_rx_pre_handlers;
         local->rx_handlers = ieee80211_rx_handlers;
         local->tx_handlers = ieee80211_tx_handlers;
 
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 7ffeae2..3f4d00e 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -137,7 +137,11 @@ struct ieee80211_txrx_data {
 			struct ieee80211_rx_status *status;
 			int sent_ps_buffered;
 			int queue;
+			int load;
 			int in_scan:1;
+			int ra_match:1; /* frame is destined to interface
+					 * currently processed (including
+					 * multicast frames) */
 		} rx;
 	} u;
 #ifdef CONFIG_HOSTAPD_WPA_TESTING
@@ -413,6 +417,7 @@ #define IEEE80211_IRQSAFE_QUEUE_LIMIT 12
 	struct ieee80211_passive_scan scan;
 
 
+	ieee80211_rx_handler *rx_pre_handlers;
 	ieee80211_rx_handler *rx_handlers;
         ieee80211_tx_handler *tx_handlers;
 
diff --git a/net/d80211/wpa.c b/net/d80211/wpa.c
index 04856a9..37f5af4 100644
--- a/net/d80211/wpa.c
+++ b/net/d80211/wpa.c
@@ -235,6 +235,10 @@ #endif /* CONFIG_HOSTAPD_WPA_TESTING */
 #ifdef CONFIG_HOSTAPD_WPA_TESTING
 		int i;
 #endif /* CONFIG_HOSTAPD_WPA_TESTING */
+
+		if (!rx->u.rx.ra_match)
+			return TXRX_DROP;
+
 		printk(KERN_DEBUG "%s: invalid Michael MIC in data frame from "
 		       MACSTR "\n", rx->dev->name, MAC2STR(sa));
 #ifdef CONFIG_HOSTAPD_WPA_TESTING
-- 
1.3.0


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

* [PATCH 5/9] d80211: fix defragmentation
  2006-07-18 15:45 [PATCH 0/9] d80211: pull request Jiri Benc
                   ` (3 preceding siblings ...)
  2006-07-18 15:45 ` [PATCH 4/9] d80211: fix receiving through virtual interfaces Jiri Benc
@ 2006-07-18 15:45 ` Jiri Benc
  2006-07-18 15:45 ` [PATCH 6/9] d80211: optimize defragmentation Jiri Benc
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Jiri Benc @ 2006-07-18 15:45 UTC (permalink / raw)
  To: netdev

When multiple virtual interfaces are active and some of them is in promisc
mode, defragmentation does not work. Fix it by introducing separate fragment
table for each virtual interface.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c       |   26 +++++++++++---------------
 net/d80211/ieee80211_i.h     |    8 ++++----
 net/d80211/ieee80211_iface.c |    5 +++++
 3 files changed, 20 insertions(+), 19 deletions(-)

bb23c7cde283025bab76f0422003c45a2f82c937
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 0b6d8a5..ac2c03f 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -2810,17 +2810,17 @@ #endif /* IEEE80211_VERBOSE_DEBUG_PS */
 
 
 static inline struct ieee80211_fragment_entry *
-ieee80211_reassemble_add(struct ieee80211_local *local,
+ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
 			 unsigned int frag, unsigned int seq, int rx_queue,
 			 struct sk_buff **skb)
 {
         struct ieee80211_fragment_entry *entry;
 	int idx;
 
-	idx = local->fragment_next;
-	entry = &local->fragments[local->fragment_next++];
-	if (local->fragment_next >= IEEE80211_FRAGMENT_MAX)
-		local->fragment_next = 0;
+	idx = sdata->fragment_next;
+	entry = &sdata->fragments[sdata->fragment_next++];
+	if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX)
+		sdata->fragment_next = 0;
 
 	if (entry->skb) {
 #ifdef CONFIG_D80211_DEBUG
@@ -2829,7 +2829,7 @@ #ifdef CONFIG_D80211_DEBUG
 		printk(KERN_DEBUG "%s: RX reassembly removed oldest "
 		       "fragment entry (idx=%d age=%lu seq=%d last_frag=%d "
 		       "addr1=" MACSTR " addr2=" MACSTR "\n",
-		       local->mdev->name, idx,
+		       sdata->dev->name, idx,
 		       jiffies - entry->first_frag_time, entry->seq,
 		       entry->last_frag, MAC2STR(hdr->addr1),
 		       MAC2STR(hdr->addr2));
@@ -2850,14 +2850,14 @@ #endif /* CONFIG_D80211_DEBUG */
 
 
 static inline struct ieee80211_fragment_entry *
-ieee80211_reassemble_find(struct ieee80211_local *local,
+ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
 			  u16 fc, unsigned int frag, unsigned int seq,
 			  int rx_queue, struct ieee80211_hdr *hdr)
 {
 	struct ieee80211_fragment_entry *entry;
         int i, idx;
 
-	idx = local->fragment_next;
+	idx = sdata->fragment_next;
 	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
 		struct ieee80211_hdr *f_hdr;
 		u16 f_fc;
@@ -2866,7 +2866,7 @@ ieee80211_reassemble_find(struct ieee802
 		if (idx < 0)
 			idx = IEEE80211_FRAGMENT_MAX - 1;
 
-		entry = &local->fragments[idx];
+		entry = &sdata->fragments[idx];
 		if (!entry->skb || entry->seq != seq ||
 		    entry->rx_queue != rx_queue ||
 		    entry->last_frag + 1 != frag)
@@ -2916,7 +2916,7 @@ ieee80211_rx_h_defragment(struct ieee802
 
 	if (frag == 0) {
 		/* This is the first fragment of a new frame. */
-		entry = ieee80211_reassemble_add(rx->local, frag, seq,
+		entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
 						 rx->u.rx.queue, &(rx->skb));
 		if (rx->key && rx->key->alg == ALG_CCMP &&
 		    (rx->fc & WLAN_FC_ISWEP)) {
@@ -2933,7 +2933,7 @@ ieee80211_rx_h_defragment(struct ieee802
 	/* This is a fragment for a frame that should already be pending in
 	 * fragment cache. Add this fragment to the end of the pending entry.
 	 */
-	entry = ieee80211_reassemble_find(rx->local, rx->fc, frag, seq,
+	entry = ieee80211_reassemble_find(rx->sdata, rx->fc, frag, seq,
 					  rx->u.rx.queue, hdr);
 	if (!entry) {
 		I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
@@ -4571,10 +4571,6 @@ void ieee80211_unregister_hw(struct net_
 				  &local->class_dev.kobj);
 	ieee80211_dev_sysfs_del(local);
 
-	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
-		if (local->fragments[i].skb)
-			dev_kfree_skb(local->fragments[i].skb);
-
 	for (i = 0; i < NUM_IEEE80211_MODES; i++) {
 		kfree(local->supp_rates[i]);
 		kfree(local->basic_rates[i]);
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 3f4d00e..6a952bd 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -307,6 +307,10 @@ struct ieee80211_sub_if_data {
 	int ieee802_1x; /* IEEE 802.1X PAE - drop packet to/from unauthorized
 			 * port */
 
+	/* Fragment table for host-based reassembly */
+	struct ieee80211_fragment_entry	fragments[IEEE80211_FRAGMENT_MAX];
+	unsigned int fragment_next;
+
 #define NUM_DEFAULT_KEYS 4
         struct ieee80211_key *keys[NUM_DEFAULT_KEYS];
         struct ieee80211_key *default_key;
@@ -406,10 +410,6 @@ #define IEEE80211_IRQSAFE_QUEUE_LIMIT 12
 				  * or RX before generating a rekey
 				  * notification; 0 = notification disabled. */
 
-	/* Fragment table for host-based reassembly */
-	struct ieee80211_fragment_entry	fragments[IEEE80211_FRAGMENT_MAX];
-	unsigned int fragment_next;
-
 	int bridge_packets; /* bridge packets between associated stations and
 			     * deliver multicast frames both back to wireless
 			     * media and to the local net stack */
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index 566bb36..f49ce8a 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -336,9 +336,14 @@ int ieee80211_if_remove(struct net_devic
 void ieee80211_if_free(struct net_device *dev)
 {
 	struct ieee80211_local *local = dev->ieee80211_ptr;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	int i;
 
 	/* local->apdev must be NULL when freeing management interface */
 	BUG_ON(dev == local->apdev);
+	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
+		if (sdata->fragments[i].skb)
+			dev_kfree_skb(sdata->fragments[i].skb);
 	free_netdev(dev);
 }
 
-- 
1.3.0


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

* [PATCH 6/9] d80211: optimize defragmentation
  2006-07-18 15:45 [PATCH 0/9] d80211: pull request Jiri Benc
                   ` (4 preceding siblings ...)
  2006-07-18 15:45 ` [PATCH 5/9] d80211: fix defragmentation Jiri Benc
@ 2006-07-18 15:45 ` Jiri Benc
  2006-07-18 15:45 ` [PATCH 7/9] d80211: SET_NETDEV_DEV for non-master devices Jiri Benc
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Jiri Benc @ 2006-07-18 15:45 UTC (permalink / raw)
  To: netdev

Optimize defragmentation by storing all fragments in skb queue and
reallocating skb only once all fragments are received.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c       |   46 ++++++++++++++++++++++--------------------
 net/d80211/ieee80211_i.h     |    3 ++-
 net/d80211/ieee80211_iface.c |   19 ++++++++++++++---
 3 files changed, 41 insertions(+), 27 deletions(-)

162a9ab0920090224f0af03b4a79b45b35dd437f
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index ac2c03f..cc06675 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -2822,10 +2822,10 @@ ieee80211_reassemble_add(struct ieee8021
 	if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX)
 		sdata->fragment_next = 0;
 
-	if (entry->skb) {
+	if (!skb_queue_empty(&entry->skb_list)) {
 #ifdef CONFIG_D80211_DEBUG
 		struct ieee80211_hdr *hdr =
-			(struct ieee80211_hdr *) entry->skb->data;
+			(struct ieee80211_hdr *) entry->skb_list.next->data;
 		printk(KERN_DEBUG "%s: RX reassembly removed oldest "
 		       "fragment entry (idx=%d age=%lu seq=%d last_frag=%d "
 		       "addr1=" MACSTR " addr2=" MACSTR "\n",
@@ -2834,16 +2834,17 @@ #ifdef CONFIG_D80211_DEBUG
 		       entry->last_frag, MAC2STR(hdr->addr1),
 		       MAC2STR(hdr->addr2));
 #endif /* CONFIG_D80211_DEBUG */
-		dev_kfree_skb(entry->skb);
+		__skb_queue_purge(&entry->skb_list);
 	}
 
-	entry->skb = *skb;
+	__skb_queue_tail(&entry->skb_list, *skb); /* no need for locking */
 	*skb = NULL;
 	entry->first_frag_time = jiffies;
 	entry->seq = seq;
 	entry->rx_queue = rx_queue;
         entry->last_frag = frag;
 	entry->ccmp = 0;
+	entry->extra_len = 0;
 
 	return entry;
 }
@@ -2867,12 +2868,12 @@ ieee80211_reassemble_find(struct ieee802
 			idx = IEEE80211_FRAGMENT_MAX - 1;
 
 		entry = &sdata->fragments[idx];
-		if (!entry->skb || entry->seq != seq ||
+		if (skb_queue_empty(&entry->skb_list) || entry->seq != seq ||
 		    entry->rx_queue != rx_queue ||
 		    entry->last_frag + 1 != frag)
 			continue;
 
-		f_hdr = (struct ieee80211_hdr *) entry->skb->data;
+		f_hdr = (struct ieee80211_hdr *) entry->skb_list.next->data;
 		f_fc = le16_to_cpu(f_hdr->frame_control);
 
 		if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_GET_TYPE(f_fc) ||
@@ -2881,8 +2882,7 @@ ieee80211_reassemble_find(struct ieee802
 			continue;
 
 		if (entry->first_frag_time + 2 * HZ < jiffies) {
-			dev_kfree_skb(entry->skb);
-			entry->skb = NULL;
+			__skb_queue_purge(&entry->skb_list);
 			continue;
 		}
 		return entry;
@@ -2899,6 +2899,7 @@ ieee80211_rx_h_defragment(struct ieee802
 	u16 sc;
 	unsigned int frag, seq;
 	struct ieee80211_fragment_entry *entry;
+	struct sk_buff *skb;
 
 	hdr = (struct ieee80211_hdr *) rx->skb->data;
 	sc = le16_to_cpu(hdr->seq_ctrl);
@@ -2966,30 +2967,30 @@ ieee80211_rx_h_defragment(struct ieee802
 		memcpy(entry->last_pn, pn, CCMP_PN_LEN);
 	}
 
-	/* TODO: could gather list of skb's and reallocate data buffer only
-	 * after finding out the total length of the frame */
 	skb_pull(rx->skb, ieee80211_get_hdrlen(rx->fc));
-	if (skb_tailroom(entry->skb) < rx->skb->len) {
+	__skb_queue_tail(&entry->skb_list, rx->skb);
+	entry->last_frag = frag;
+	entry->extra_len += rx->skb->len;
+	if (rx->fc & WLAN_FC_MOREFRAG) {
+		rx->skb = NULL;
+		return TXRX_QUEUED;
+	}
+
+	rx->skb = __skb_dequeue(&entry->skb_list);
+	if (skb_tailroom(rx->skb) < entry->extra_len) {
 		I802_DEBUG_INC(rx->local->rx_expand_skb_head2);
-		if (unlikely(pskb_expand_head(entry->skb, 0, rx->skb->len,
+		if (unlikely(pskb_expand_head(rx->skb, 0, entry->extra_len,
 					      GFP_ATOMIC))) {
 			I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
+			__skb_queue_purge(&entry->skb_list);
 			return TXRX_DROP;
 		}
 	}
-	memcpy(skb_put(entry->skb, rx->skb->len), rx->skb->data, rx->skb->len);
-	entry->last_frag = frag;
-	dev_kfree_skb(rx->skb);
-
-	if (rx->fc & WLAN_FC_MOREFRAG) {
-                rx->skb = NULL;
-		return TXRX_QUEUED;
-	}
+	while ((skb = __skb_dequeue(&entry->skb_list)))
+		memcpy(skb_put(rx->skb, skb->len), skb->data, skb->len);
 
 	/* Complete frame has been reassembled - process it now */
-	rx->skb = entry->skb;
 	rx->fragmented = 1;
-        entry->skb = NULL;
 
  out:
 	if (rx->sta)
@@ -4390,6 +4391,7 @@ struct net_device *ieee80211_alloc_hw(si
         sdata->dev = mdev;
         sdata->master = mdev;
         sdata->local = local;
+	ieee80211_if_sdata_init(sdata);
         list_add_tail(&sdata->list, &local->sub_if_list);
 
 	tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 6a952bd..b4e294c 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -62,7 +62,8 @@ struct ieee80211_fragment_entry {
 	unsigned int seq;
 	unsigned int rx_queue;
 	unsigned int last_frag;
-	struct sk_buff *skb;
+	unsigned int extra_len;
+	struct sk_buff_head skb_list;
 	int ccmp; /* Whether fragments were encrypted with CCMP */
 	u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
 };
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index f49ce8a..f64b4de 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -18,9 +18,22 @@ #include "sta_info.h"
 
 void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
 {
+	int i;
+
 	/* Default values for sub-interface parameters */
 	sdata->drop_unencrypted = 0;
 	sdata->eapol = 1;
+	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
+		skb_queue_head_init(&sdata->fragments[i].skb_list);
+}
+
+static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
+{
+	int i;
+
+	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
+		__skb_queue_purge(&sdata->fragments[i].skb_list);
+	}
 }
 
 /* Must be called with rtnl lock held. */
@@ -212,6 +225,7 @@ void ieee80211_if_reinit(struct net_devi
 	int i;
 
 	ASSERT_RTNL();
+	ieee80211_if_sdata_deinit(sdata);
 	for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
 		if (!sdata->keys[i])
 			continue;
@@ -337,13 +351,10 @@ void ieee80211_if_free(struct net_device
 {
 	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	int i;
 
 	/* local->apdev must be NULL when freeing management interface */
 	BUG_ON(dev == local->apdev);
-	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
-		if (sdata->fragments[i].skb)
-			dev_kfree_skb(sdata->fragments[i].skb);
+	ieee80211_if_sdata_deinit(sdata);
 	free_netdev(dev);
 }
 
-- 
1.3.0


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

* [PATCH 7/9] d80211: SET_NETDEV_DEV for non-master devices
  2006-07-18 15:45 [PATCH 0/9] d80211: pull request Jiri Benc
                   ` (5 preceding siblings ...)
  2006-07-18 15:45 ` [PATCH 6/9] d80211: optimize defragmentation Jiri Benc
@ 2006-07-18 15:45 ` Jiri Benc
  2006-07-18 15:45 ` [PATCH 8/9] d80211: Replace rc4 code with crypto api arc4 Jiri Benc
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Jiri Benc @ 2006-07-18 15:45 UTC (permalink / raw)
  To: netdev

This adds /sys/class/net/*/device symlinks for non-master (wlan* and wmgmt*)
devices.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211_iface.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

80f18b79eacc07319afe473023a5358cfbc11ae6
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index f64b4de..fa3d9e2 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -76,6 +76,7 @@ int ieee80211_if_add(struct net_device *
 	ndev->mem_start = dev->mem_start;
 	ndev->mem_end = dev->mem_end;
 	ndev->flags = dev->flags & IFF_MULTICAST;
+	SET_NETDEV_DEV(ndev, dev->class_dev.dev);
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
 	sdata->type = IEEE80211_IF_TYPE_AP;
@@ -130,6 +131,7 @@ int ieee80211_if_add_mgmt(struct net_dev
 	ndev->irq = dev->irq;
 	ndev->mem_start = dev->mem_start;
 	ndev->mem_end = dev->mem_end;
+	SET_NETDEV_DEV(ndev, dev->class_dev.dev);
 
 	nsdata = IEEE80211_DEV_TO_SUB_IF(ndev);
 	nsdata->type = IEEE80211_IF_TYPE_MGMT;
-- 
1.3.0


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

* [PATCH 8/9] d80211: Replace rc4 code with crypto api arc4
  2006-07-18 15:45 [PATCH 0/9] d80211: pull request Jiri Benc
                   ` (6 preceding siblings ...)
  2006-07-18 15:45 ` [PATCH 7/9] d80211: SET_NETDEV_DEV for non-master devices Jiri Benc
@ 2006-07-18 15:45 ` Jiri Benc
  2006-07-18 15:45 ` [PATCH 9/9] d80211: Add sparse bitwise annotations Jiri Benc
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Jiri Benc @ 2006-07-18 15:45 UTC (permalink / raw)
  To: netdev

From: Michael Wu <flamingice@sourmilk.net>

This patch replaces the rc4 code used in wep.c with crypto api's arc4
cipher. The struct crypto_tfm passing in tkip isn't great, but it'll get fixed
when tkip is converted to use crypto api entirely. (michael_mic)

Signed-off-by: Michael Wu <flamingice@sourmilk.net>
Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/Kconfig       |    1 
 net/d80211/ieee80211.c   |   10 ++
 net/d80211/ieee80211_i.h |    1 
 net/d80211/tkip.c        |   14 ++-
 net/d80211/tkip.h        |   10 +-
 net/d80211/wep.c         |  193 ++++++++++------------------------------------
 net/d80211/wep.h         |   11 +--
 net/d80211/wpa.c         |    4 -
 8 files changed, 73 insertions(+), 171 deletions(-)

a495f8ec7590d6df5edc36bff419f25b8c3440de
diff --git a/net/d80211/Kconfig b/net/d80211/Kconfig
index e61e189..36df52d 100644
--- a/net/d80211/Kconfig
+++ b/net/d80211/Kconfig
@@ -1,6 +1,7 @@
 config D80211
 	tristate "Generic IEEE 802.11 Networking Stack (dscape)"
 	select CRYPTO
+	select CRYPTO_ARC4
 	select CRYPTO_AES
 	---help---
 	This option enables the hardware independent IEEE 802.11
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index cc06675..4e80767 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -4475,11 +4475,16 @@ int ieee80211_register_hw(struct net_dev
 		goto fail_rate_attrs;
 	}
 
+	result = ieee80211_wep_init(local);
+
+	if (result < 0) {
+		printk(KERN_DEBUG "%s: Failed to initialize wep\n", dev->name);
+		goto fail_rate_attrs;
+	}
+
 	/* TODO: add rtnl locking around device creation and qdisc install */
 	ieee80211_install_qdisc(dev);
 
-        ieee80211_wep_init(local);
-
 	/* add one default STA interface */
 	rtnl_lock();
 	result = ieee80211_if_add(dev, "wlan%d", 1, &sta_dev);
@@ -4592,6 +4597,7 @@ void ieee80211_free_hw(struct net_device
 	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	ieee80211_if_free(dev);
+	ieee80211_wep_free(local);
 	ieee80211_dev_free(local);
 }
 
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index b4e294c..9e1e5e8 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -406,6 +406,7 @@ #define IEEE80211_IRQSAFE_QUEUE_LIMIT 12
 	int long_retry_limit; /* dot11LongRetryLimit */
 	int short_preamble; /* use short preamble with IEEE 802.11b */
 
+	struct crypto_tfm *wep_tfm;
 	u32 wep_iv;
 	int key_tx_rx_threshold; /* number of times any key can be used in TX
 				  * or RX before generating a rekey
diff --git a/net/d80211/tkip.c b/net/d80211/tkip.c
index a487673..337e31a 100644
--- a/net/d80211/tkip.c
+++ b/net/d80211/tkip.c
@@ -211,8 +211,8 @@ u8 * ieee80211_tkip_add_iv(u8 *pos, stru
  * headroom of eight octets for IV and Ext. IV and taildroom of four octets
  * for ICV. @payload_len is the length of payload (_not_ including extra
  * headroom and tailroom). @ta is the transmitter addresses. */
-void ieee80211_tkip_encrypt_data(struct ieee80211_key *key, u8 *pos,
-				 size_t payload_len, u8 *ta)
+void ieee80211_tkip_encrypt_data(struct crypto_tfm *tfm, struct ieee80211_key *key,
+				 u8 *pos, size_t payload_len, u8 *ta)
 {
 	u8 rc4key[16];
 
@@ -228,7 +228,7 @@ void ieee80211_tkip_encrypt_data(struct 
 			   key->u.tkip.iv16, rc4key);
 
 	pos = ieee80211_tkip_add_iv(pos, key, rc4key[0], rc4key[1], rc4key[2]);
-	ieee80211_wep_encrypt_data(rc4key, 16, pos, payload_len);
+	ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len);
 }
 
 
@@ -236,9 +236,9 @@ void ieee80211_tkip_encrypt_data(struct 
  * beginning of the buffer containing IEEE 802.11 header payload, i.e.,
  * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the
  * length of payload, including IV, Ext. IV, MIC, ICV.  */
-int ieee80211_tkip_decrypt_data(struct ieee80211_key *key, u8 *payload,
-				size_t payload_len, u8 *ta, int only_iv,
-				int queue)
+int ieee80211_tkip_decrypt_data(struct crypto_tfm *tfm, struct ieee80211_key *key,
+				u8 *payload, size_t payload_len, u8 *ta,
+				int only_iv, int queue)
 {
 	u32 iv32;
 	u32 iv16;
@@ -325,7 +325,7 @@ #ifdef CONFIG_TKIP_DEBUG
 	}
 #endif /* CONFIG_TKIP_DEBUG */
 
-	res = ieee80211_wep_decrypt_data(rc4key, 16, pos, payload_len - 12);
+	res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12);
  done:
 	if (res == TKIP_DECRYPT_OK) {
 		/* FIX: these should be updated only after Michael MIC has been
diff --git a/net/d80211/tkip.h b/net/d80211/tkip.h
index 4239cec..dc66421 100644
--- a/net/d80211/tkip.h
+++ b/net/d80211/tkip.h
@@ -14,16 +14,16 @@ #include "ieee80211_key.h"
 
 u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key,
 			   u8 iv0, u8 iv1, u8 iv2);
-void ieee80211_tkip_encrypt_data(struct ieee80211_key *key, u8 *pos,
-				 size_t payload_len, u8 *ta);
+void ieee80211_tkip_encrypt_data(struct crypto_tfm *tfm, struct ieee80211_key *key,
+				 u8 *pos, size_t payload_len, u8 *ta);
 enum {
 	TKIP_DECRYPT_OK = 0,
 	TKIP_DECRYPT_NO_EXT_IV = -1,
 	TKIP_DECRYPT_INVALID_KEYIDX = -2,
 	TKIP_DECRYPT_REPLAY = -3,
 };
-int ieee80211_tkip_decrypt_data(struct ieee80211_key *key, u8 *payload,
-				size_t payload_len, u8 *ta, int only_iv,
-				int queue);
+int ieee80211_tkip_decrypt_data(struct crypto_tfm *tfm, struct ieee80211_key *key,
+				u8 *payload, size_t payload_len, u8 *ta,
+				int only_iv, int queue);
 
 #endif /* TKIP_H */
diff --git a/net/d80211/wep.c b/net/d80211/wep.c
index 172b4a1..f60e449 100644
--- a/net/d80211/wep.c
+++ b/net/d80211/wep.c
@@ -14,74 +14,31 @@ #include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/random.h>
 #include <linux/compiler.h>
+#include <linux/crc32.h>
+#include <linux/crypto.h>
+#include <asm/scatterlist.h>
 
 #include <net/d80211.h>
 #include "ieee80211_i.h"
 #include "wep.h"
 
 
-static const __u32 crc32_table[256] = {
-	0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
-	0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
-	0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
-	0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
-	0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
-	0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
-	0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
-	0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
-	0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
-	0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
-	0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
-	0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
-	0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
-	0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
-	0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
-	0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
-	0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
-	0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
-	0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
-	0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
-	0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
-	0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
-	0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
-	0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
-	0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
-	0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
-	0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
-	0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
-	0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
-	0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
-	0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
-	0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
-	0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
-	0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
-	0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
-	0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
-	0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
-	0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
-	0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
-	0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
-	0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
-	0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
-	0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
-	0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
-	0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
-	0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
-	0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
-	0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
-	0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
-	0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
-	0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
-	0x2d02ef8dL
-};
-
-
-void ieee80211_wep_init(struct ieee80211_local *local)
+int ieee80211_wep_init(struct ieee80211_local *local)
 {
 	/* start WEP IV from a random value */
 	get_random_bytes(&local->wep_iv, WEP_IV_LEN);
+
+	local->wep_tfm = crypto_alloc_tfm("arc4", 0);
+	if (!local->wep_tfm)
+		return -ENOMEM;
+
+	return 0;
 }
 
+void ieee80211_wep_free(struct ieee80211_local *local)
+{
+	crypto_free_tfm(local->wep_tfm);
+}
 
 static inline int ieee80211_wep_weak_iv(u32 iv, int keylen)
 {
@@ -161,51 +118,20 @@ void ieee80211_wep_remove_iv(struct ieee
 /* Perform WEP encryption using given key. data buffer must have tailroom
  * for 4-byte ICV. data_len must not include this ICV. Note: this function
  * does _not_ add IV. data = RC4(data | CRC32(data)) */
-void ieee80211_wep_encrypt_data(u8 *rc4key, size_t klen, u8 *data,
-				size_t data_len)
+void ieee80211_wep_encrypt_data(struct crypto_tfm *tfm, u8 *rc4key,
+				size_t klen, u8 *data, size_t data_len)
 {
-	u32 i, j, k, crc;
-	u8 S[256];
-	u8 kpos, *pos;
-#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
-
-	/* Setup RC4 state */
-	for (i = 0; i < 256; i++)
-		S[i] = i;
-	j = 0;
-	kpos = 0;
-	for (i = 0; i < 256; i++) {
-		j = (j + S[i] + rc4key[kpos]) & 0xff;
-		kpos++;
-		if (kpos >= klen)
-			kpos = 0;
-		S_SWAP(i, j);
-	}
+	struct scatterlist sg;
+	u32 *icv;
 
-	/* Compute CRC32 over unencrypted data and apply RC4 to data */
-	pos = data;
-	crc = ~0;
-	i = j = 0;
-	for (k = 0; k < data_len; k++) {
-		crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8);
-		i = (i + 1) & 0xff;
-		j = (j + S[i]) & 0xff;
-		S_SWAP(i, j);
-		*pos++ ^= S[(S[i] + S[j]) & 0xff];
-	}
-	crc = ~crc;
-
-	/* Append little-endian CRC32 and encrypt it to produce ICV */
-	pos[0] = crc;
-	pos[1] = crc >> 8;
-	pos[2] = crc >> 16;
-	pos[3] = crc >> 24;
-	for (k = 0; k < 4; k++) {
-		i = (i + 1) & 0xff;
-		j = (j + S[i]) & 0xff;
-		S_SWAP(i, j);
-		*pos++ ^= S[(S[i] + S[j]) & 0xff];
-	}
+	icv = (u32 *)(data + data_len);
+	*icv = ~crc32_le(~0, data, data_len);
+
+	crypto_cipher_setkey(tfm, rc4key, klen);
+	sg.page = virt_to_page(data);
+	sg.offset = offset_in_page(data);
+	sg.length = data_len + WEP_ICV_LEN;
+	crypto_cipher_encrypt(tfm, &sg, &sg, sg.length);
 }
 
 
@@ -248,7 +174,7 @@ int ieee80211_wep_encrypt(struct ieee802
 	/* Add room for ICV */
 	skb_put(skb, WEP_ICV_LEN);
 
-	ieee80211_wep_encrypt_data(rc4key, klen, iv + WEP_IV_LEN, len);
+	ieee80211_wep_encrypt_data(local->wep_tfm, rc4key, klen, iv + WEP_IV_LEN, len);
 
 	kfree(rc4key);
 
@@ -259,55 +185,22 @@ int ieee80211_wep_encrypt(struct ieee802
 /* Perform WEP decryption using given key. data buffer includes encrypted
  * payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV.
  * Return 0 on success and -1 on ICV mismatch. */
-int ieee80211_wep_decrypt_data(u8 *rc4key, size_t klen, u8 *data,
-			       size_t data_len)
+int ieee80211_wep_decrypt_data(struct crypto_tfm *tfm, u8 *rc4key,
+			       size_t klen, u8 *data, size_t data_len)
 {
-	u32 i, j, k, crc;
-	u8 S[256];
-	u8 kpos, *pos, crcbuf[WEP_ICV_LEN], *cpos;
-
-	/* Setup RC4 state */
-	for (i = 0; i < 256; i++)
-		S[i] = i;
-	j = 0;
-	kpos = 0;
-	for (i = 0; i < 256; i++) {
-		j = (j + S[i] + rc4key[kpos]) & 0xff;
-		kpos++;
-		if (kpos >= klen)
-			kpos = 0;
-		S_SWAP(i, j);
-	}
-
-	/* Apply RC4 to data and compute CRC32 over decrypted data */
-	pos = data;
-	crc = ~0;
-	i = j = 0;
-	for (k = 0; k < data_len; k++) {
-		i = (i + 1) & 0xff;
-		j = (j + S[i]) & 0xff;
-		S_SWAP(i, j);
-		*pos ^= S[(S[i] + S[j]) & 0xff];
-		crc = crc32_table[(crc ^ *pos++) & 0xff] ^ (crc >> 8);
-	}
-	crc = ~crc;
-
-	/* Decrypt little-endian CRC32 and verify that it matches with the
-	 * received ICV */
-	cpos = crcbuf;
-	crcbuf[0] = crc;
-	crcbuf[1] = crc >> 8;
-	crcbuf[2] = crc >> 16;
-	crcbuf[3] = crc >> 24;
-	for (k = 0; k < WEP_ICV_LEN; k++) {
-		i = (i + 1) & 0xff;
-		j = (j + S[i]) & 0xff;
-		S_SWAP(i, j);
-		if (*cpos++ != (*pos++ ^ S[(S[i] + S[j]) & 0xff])) {
-			/* ICV mismatch */
-			return -1;
-		}
-	}
+	struct scatterlist sg;
+	u32 crc;
+
+	crypto_cipher_setkey(tfm, rc4key, klen);
+	sg.page = virt_to_page(data);
+	sg.offset = offset_in_page(data);
+	sg.length = data_len + WEP_ICV_LEN;
+	crypto_cipher_decrypt(tfm, &sg, &sg, sg.length);
+
+	crc = ~crc32_le(~0, data, data_len);
+	if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0)
+		/* ICV mismatch */
+		return -1;
 
 	return 0;
 }
@@ -361,7 +254,7 @@ int ieee80211_wep_decrypt(struct ieee802
 	/* Copy rest of the WEP key (the secret part) */
 	memcpy(rc4key + 3, key->key, key->keylen);
 
-	if (ieee80211_wep_decrypt_data(rc4key, klen,
+	if (ieee80211_wep_decrypt_data(local->wep_tfm, rc4key, klen,
 				       skb->data + hdrlen + WEP_IV_LEN,
 				       len)) {
 		printk(KERN_DEBUG "WEP decrypt failed (ICV)\n");
diff --git a/net/d80211/wep.h b/net/d80211/wep.h
index 1d76639..e019b19 100644
--- a/net/d80211/wep.h
+++ b/net/d80211/wep.h
@@ -16,7 +16,8 @@ #include <linux/types.h>
 #include "ieee80211_i.h"
 #include "ieee80211_key.h"
 
-void ieee80211_wep_init(struct ieee80211_local *local);
+int ieee80211_wep_init(struct ieee80211_local *local);
+void ieee80211_wep_free(struct ieee80211_local *local);
 void ieee80211_wep_get_iv(struct ieee80211_local *local,
 			  struct ieee80211_key *key, u8 *iv);
 u8 * ieee80211_wep_add_iv(struct ieee80211_local *local,
@@ -25,10 +26,10 @@ u8 * ieee80211_wep_add_iv(struct ieee802
 void ieee80211_wep_remove_iv(struct ieee80211_local *local,
 			     struct sk_buff *skb,
 			     struct ieee80211_key *key);
-void ieee80211_wep_encrypt_data(u8 *rc4key, size_t klen, u8 *data,
-				size_t data_len);
-int ieee80211_wep_decrypt_data(u8 *rc4key, size_t klen, u8 *data,
-			       size_t data_len);
+void ieee80211_wep_encrypt_data(struct crypto_tfm *tfm, u8 *rc4key, size_t klen,
+				u8 *data, size_t data_len);
+int ieee80211_wep_decrypt_data(struct crypto_tfm *tfm, u8 *rc4key, size_t klen,
+			       u8 *data, size_t data_len);
 int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb,
 			  struct ieee80211_key *key);
 int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb,
diff --git a/net/d80211/wpa.c b/net/d80211/wpa.c
index 37f5af4..811a107 100644
--- a/net/d80211/wpa.c
+++ b/net/d80211/wpa.c
@@ -359,7 +359,7 @@ #endif /* CONFIG_HOSTAPD_WPA_TESTING */
 	skb_put(skb, TKIP_ICV_LEN);
 
 	hdr = (struct ieee80211_hdr *) skb->data;
-	ieee80211_tkip_encrypt_data(key, pos, len, hdr->addr2);
+	ieee80211_tkip_encrypt_data(tx->local->wep_tfm, key, pos, len, hdr->addr2);
 	return 0;
 }
 
@@ -502,7 +502,7 @@ #endif /* CONFIG_HOSTAPD_WPA_TESTING */
 		hwaccel = 1;
 	}
 
-	res = ieee80211_tkip_decrypt_data(key, skb->data + hdrlen,
+	res = ieee80211_tkip_decrypt_data(rx->local->wep_tfm, key, skb->data + hdrlen,
 					  skb->len - hdrlen, rx->sta->addr,
 					  hwaccel, rx->u.rx.queue);
 	if (res != TKIP_DECRYPT_OK || wpa_test) {
-- 
1.3.0


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

* [PATCH 9/9] d80211: Add sparse bitwise annotations
  2006-07-18 15:45 [PATCH 0/9] d80211: pull request Jiri Benc
                   ` (7 preceding siblings ...)
  2006-07-18 15:45 ` [PATCH 8/9] d80211: Replace rc4 code with crypto api arc4 Jiri Benc
@ 2006-07-18 15:45 ` Jiri Benc
  2006-07-18 15:46 ` [PATCH 0/9] d80211: pull request Jiri Benc
  2006-07-28 14:25 ` Jiri Benc
  10 siblings, 0 replies; 14+ messages in thread
From: Jiri Benc @ 2006-07-18 15:45 UTC (permalink / raw)
  To: netdev

From: Michael Wu <flamingice@sourmilk.net>

This patch adds sparse bitwise annotations to d80211.

Signed-off-by: Michael Wu <flamingice@sourmilk.net>
Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 include/net/d80211.h       |    6 +++---
 include/net/d80211_mgmt.h  |   42 +++++++++++++++++++++---------------------
 net/d80211/ieee80211_sta.c |    7 +------
 3 files changed, 25 insertions(+), 30 deletions(-)

2816781dfb1c8a2051a962e75cdba34da1811e22
diff --git a/include/net/d80211.h b/include/net/d80211.h
index fdb082c..85817ab 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -965,12 +965,12 @@ #define IEEE80211_MAX_FRAG_THRESHOLD 234
 #define IEEE80211_MAX_RTS_THRESHOLD 2347
 
 struct ieee80211_hdr {
-	u16 frame_control;
-	u16 duration_id;
+	__le16 frame_control;
+	__le16 duration_id;
 	u8 addr1[6];
 	u8 addr2[6];
 	u8 addr3[6];
-	u16 seq_ctrl;
+	__le16 seq_ctrl;
 	u8 addr4[6];
 } __attribute__ ((packed));
 
diff --git a/include/net/d80211_mgmt.h b/include/net/d80211_mgmt.h
index 8066af7..f623db3 100644
--- a/include/net/d80211_mgmt.h
+++ b/include/net/d80211_mgmt.h
@@ -15,50 +15,50 @@ #define D802_11_MGMT_H
 #include <linux/types.h>
 
 struct ieee80211_mgmt {
-	u16 frame_control;
-	u16 duration;
+	__le16 frame_control;
+	__le16 duration;
 	u8 da[6];
 	u8 sa[6];
 	u8 bssid[6];
-	u16 seq_ctrl;
+	__le16 seq_ctrl;
 	union {
 		struct {
-			u16 auth_alg;
-			u16 auth_transaction;
-			u16 status_code;
+			__le16 auth_alg;
+			__le16 auth_transaction;
+			__le16 status_code;
 			/* possibly followed by Challenge text */
 			u8 variable[0];
 		} __attribute__ ((packed)) auth;
 		struct {
-			u16 reason_code;
+			__le16 reason_code;
 		} __attribute__ ((packed)) deauth;
 		struct {
-			u16 capab_info;
-			u16 listen_interval;
+			__le16 capab_info;
+			__le16 listen_interval;
 			/* followed by SSID and Supported rates */
 			u8 variable[0];
 		} __attribute__ ((packed)) assoc_req;
 		struct {
-			u16 capab_info;
-			u16 status_code;
-			u16 aid;
+			__le16 capab_info;
+			__le16 status_code;
+			__le16 aid;
 			/* followed by Supported rates */
 			u8 variable[0];
 		} __attribute__ ((packed)) assoc_resp, reassoc_resp;
 		struct {
-			u16 capab_info;
-			u16 listen_interval;
+			__le16 capab_info;
+			__le16 listen_interval;
 			u8 current_ap[6];
 			/* followed by SSID and Supported rates */
 			u8 variable[0];
 		} __attribute__ ((packed)) reassoc_req;
 		struct {
-			u16 reason_code;
+			__le16 reason_code;
 		} __attribute__ ((packed)) disassoc;
 		struct {
-			u8 timestamp[8];
-			u16 beacon_int;
-			u16 capab_info;
+			__le64 timestamp;
+			__le16 beacon_int;
+			__le16 capab_info;
 			/* followed by some of SSID, Supported rates,
 			 * FH Params, DS Params, CF Params, IBSS Params, TIM */
 			u8 variable[0];
@@ -68,9 +68,9 @@ struct ieee80211_mgmt {
 			u8 variable[0];
 		} __attribute__ ((packed)) probe_req;
 		struct {
-			u8 timestamp[8];
-			u16 beacon_int;
-			u16 capab_info;
+			__le64 timestamp;
+			__le16 beacon_int;
+			__le16 capab_info;
 			/* followed by some of SSID, Supported rates,
 			 * FH Params, DS Params, CF Params, IBSS Params */
 			u8 variable[0];
diff --git a/net/d80211/ieee80211_sta.c b/net/d80211/ieee80211_sta.c
index 82fbe3d..b0cfff1 100644
--- a/net/d80211/ieee80211_sta.c
+++ b/net/d80211/ieee80211_sta.c
@@ -1344,7 +1344,6 @@ static void ieee80211_rx_bss_info(struct
 	struct sta_info *sta;
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	u64 timestamp;
-	u8 *pos;
 
 	if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN))
 		return; /* ignore ProbeResp to foreign address */
@@ -1359,11 +1358,7 @@ #endif
 	if (baselen > len)
 		return;
 
-	pos = mgmt->u.beacon.timestamp;
-	timestamp = ((u64) pos[7] << 56) | ((u64) pos[6] << 48) |
-		((u64) pos[5] << 40) | ((u64) pos[4] << 32) |
-		((u64) pos[3] << 24) | ((u64) pos[2] << 16) |
-		((u64) pos[1] << 8) | ((u64) pos[0]);
+	timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
 
 	if (sdata->type == IEEE80211_IF_TYPE_IBSS && beacon &&
 	    memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
-- 
1.3.0


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

* Re: [PATCH 0/9] d80211: pull request
  2006-07-18 15:45 [PATCH 0/9] d80211: pull request Jiri Benc
                   ` (8 preceding siblings ...)
  2006-07-18 15:45 ` [PATCH 9/9] d80211: Add sparse bitwise annotations Jiri Benc
@ 2006-07-18 15:46 ` Jiri Benc
  2006-07-28 14:25 ` Jiri Benc
  10 siblings, 0 replies; 14+ messages in thread
From: Jiri Benc @ 2006-07-18 15:46 UTC (permalink / raw)
  To: John W. Linville; +Cc: netdev

On Tue, 18 Jul 2006 17:45:20 +0200 (CEST), Jiri Benc wrote:
> Please pull from
> git://git.kernel.org/pub/scm/linux/kernel/git/jbenc/dscape.git master
> to obtain following patches:
> 
> Jiri Benc:
>       d80211: do not receive through master interface when not scanning
>       d80211: host_gen_beacon_template flag
>       d80211: better deallocation of mdev
>       d80211: fix receiving through virtual interfaces
>       d80211: fix defragmentation
>       d80211: optimize defragmentation
>       d80211: SET_NETDEV_DEV for non-master devices
> 
> Michael Wu:
>       d80211: Replace rc4 code with crypto api arc4
>       d80211: Add sparse bitwise annotations

Sorry, John, forgot to add you to the To: list.

 Jiri

-- 
Jiri Benc
SUSE Labs

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

* RE: [PATCH 3/9] d80211: better deallocation of mdev
  2006-07-18 15:45 ` [PATCH 3/9] d80211: better deallocation of mdev Jiri Benc
@ 2006-07-19  3:07   ` Simon Barber
  2006-07-19 10:15     ` Jiri Benc
  0 siblings, 1 reply; 14+ messages in thread
From: Simon Barber @ 2006-07-19  3:07 UTC (permalink / raw)
  To: Jiri Benc, netdev

Hi Jiri,

I have been thinking about a slightly different approach for the master
device. Since the master device represents the physical hardware, I am
thinking that the hardware driver could register the master device
directly itself. It would use the normal netdev_register call to do so.
Received frames would be marked as having a protocol type of 802.11, and
the 802.11 code would register itself as a protocol handler for this
protocol type. Now netif_rx() could be used within the hardware driver
to pass frames to the kernel 802.11 code - this has the benefit of
better performance for the hardirq/softirq transition than the current
scheme. On the transmit side - currently the 802.11 code does much
processing within the hard_start_xmit function on the master device. I
would move all this processing into the 802.11 qdisc - putting it into
the dequeue function. Now the hard_start_xmit function would be the real
hardware drivers transmit function.

What do you think?

Simon
 

-----Original Message-----
From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
On Behalf Of Jiri Benc
Sent: Tuesday, July 18, 2006 8:45 AM
To: netdev@vger.kernel.org
Subject: [PATCH 3/9] d80211: better deallocation of mdev

Master device and ieee80211_local are allocated separately now, so
master device can be freed by the same function as other virtual
interfaces.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c       |    2 +-
 net/d80211/ieee80211_iface.c |    3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

603ee5045dad050a66b94a847cd5385fc7678ce9
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c index
549c8a4..3d7091a 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -4534,7 +4534,7 @@ void ieee80211_free_hw(struct net_device  {
 	struct ieee80211_local *local = dev->ieee80211_ptr;
 
-	free_netdev(dev);
+	ieee80211_if_free(dev);
 	ieee80211_dev_free(local);
 }
 
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index 5abd713..566bb36 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -337,7 +337,8 @@ void ieee80211_if_free(struct net_device  {
 	struct ieee80211_local *local = dev->ieee80211_ptr;
 
-	BUG_ON(dev == local->mdev || dev == local->apdev);
+	/* local->apdev must be NULL when freeing management interface
*/
+	BUG_ON(dev == local->apdev);
 	free_netdev(dev);
 }
 
--
1.3.0

-
To unsubscribe from this list: send the line "unsubscribe netdev" in the
body of a message to majordomo@vger.kernel.org More majordomo info at
http://vger.kernel.org/majordomo-info.html


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

* Re: [PATCH 3/9] d80211: better deallocation of mdev
  2006-07-19  3:07   ` Simon Barber
@ 2006-07-19 10:15     ` Jiri Benc
  0 siblings, 0 replies; 14+ messages in thread
From: Jiri Benc @ 2006-07-19 10:15 UTC (permalink / raw)
  To: Simon Barber; +Cc: netdev

On Tue, 18 Jul 2006 20:07:34 -0700, Simon Barber wrote:
> I have been thinking about a slightly different approach for the master
> device. Since the master device represents the physical hardware, I am
> thinking that the hardware driver could register the master device
> directly itself. It would use the normal netdev_register call to do so.

How will you allocate structures for 802.11 specific data? You will
require the driver to call some ieee80211_allocate function anyway, so
you will probably want to leave allocation of net_device structure to
this function too. And it is probably better to have correspondent
ieee80211_register function to prevent confusion (even if the only thing
done in ieee80211_register is calling netdev_register).

> Received frames would be marked as having a protocol type of 802.11, and
> the 802.11 code would register itself as a protocol handler for this
> protocol type. Now netif_rx() could be used within the hardware driver
> to pass frames to the kernel 802.11 code

How will you pass data like signal strength or rate to 802.11 stack?

> - this has the benefit of
> better performance for the hardirq/softirq transition than the current
> scheme.

I don't see much benefit in this. Instead of rewriting big part of the
stack (and drivers as well) for questionable performance gain I would
rather see a work on putting the stack to mainline - the only blockers
left are SMP safety and stack<->hostapd netlink protocol. Oh, and better
communication with tools like NetworkManager.

> On the transmit side - currently the 802.11 code does much
> processing within the hard_start_xmit function on the master device. I
> would move all this processing into the 802.11 qdisc - putting it into
> the dequeue function.

This makes sense, especially fragmentation is a good candidate (and this
implies nearly the whole processing needs to be moved there as well).
Though most of these problems will vanish when the Ethernet<->802.11
conversion routines are removed and the stack starts working with native
802.11 frames.

> Now the hard_start_xmit function would be the real
> hardware drivers transmit function.

No need for this.

I also think that moving xmit processing to qdisc doesn't need to be
done now. It can be done without changing drivers, so we can do it after
the stack goes into mainline.

Thanks,

 Jiri

-- 
Jiri Benc
SUSE Labs

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

* Re: [PATCH 0/9] d80211: pull request
  2006-07-18 15:45 [PATCH 0/9] d80211: pull request Jiri Benc
                   ` (9 preceding siblings ...)
  2006-07-18 15:46 ` [PATCH 0/9] d80211: pull request Jiri Benc
@ 2006-07-28 14:25 ` Jiri Benc
  10 siblings, 0 replies; 14+ messages in thread
From: Jiri Benc @ 2006-07-28 14:25 UTC (permalink / raw)
  To: John W. Linville; +Cc: netdev

On Tue, 18 Jul 2006 17:45:20 +0200 (CEST), Jiri Benc wrote:
> Please pull from
> git://git.kernel.org/pub/scm/linux/kernel/git/jbenc/dscape.git master

I renamed that branch to 'up'. Please pull from 'up' branch.

> to obtain following patches:
> 
> Jiri Benc:
>       d80211: do not receive through master interface when not scanning
>       d80211: host_gen_beacon_template flag
>       d80211: better deallocation of mdev
>       d80211: fix receiving through virtual interfaces
>       d80211: fix defragmentation
>       d80211: optimize defragmentation
>       d80211: SET_NETDEV_DEV for non-master devices
> 
> Michael Wu:
>       d80211: Replace rc4 code with crypto api arc4
>       d80211: Add sparse bitwise annotations

-- 
Jiri Benc
SUSE Labs

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

end of thread, other threads:[~2006-07-28 14:25 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-07-18 15:45 [PATCH 0/9] d80211: pull request Jiri Benc
2006-07-18 15:45 ` [PATCH 1/9] d80211: do not receive through master interface when not scanning Jiri Benc
2006-07-18 15:45 ` [PATCH 2/9] d80211: host_gen_beacon_template flag Jiri Benc
2006-07-18 15:45 ` [PATCH 3/9] d80211: better deallocation of mdev Jiri Benc
2006-07-19  3:07   ` Simon Barber
2006-07-19 10:15     ` Jiri Benc
2006-07-18 15:45 ` [PATCH 4/9] d80211: fix receiving through virtual interfaces Jiri Benc
2006-07-18 15:45 ` [PATCH 5/9] d80211: fix defragmentation Jiri Benc
2006-07-18 15:45 ` [PATCH 6/9] d80211: optimize defragmentation Jiri Benc
2006-07-18 15:45 ` [PATCH 7/9] d80211: SET_NETDEV_DEV for non-master devices Jiri Benc
2006-07-18 15:45 ` [PATCH 8/9] d80211: Replace rc4 code with crypto api arc4 Jiri Benc
2006-07-18 15:45 ` [PATCH 9/9] d80211: Add sparse bitwise annotations Jiri Benc
2006-07-18 15:46 ` [PATCH 0/9] d80211: pull request Jiri Benc
2006-07-28 14:25 ` Jiri Benc

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).