Search Linux Wireless

Re: [PATCH 1/1] mac80211: restructuring data Rx handlers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 2007-11-22 at 19:49 +0200, Ron Rindjunsky wrote:
> This patch restructures the Rx handlers chain by incorporating previously
> handlers ieee80211_rx_h_802_1x_pae and ieee80211_rx_h_drop_unencrypted
> into ieee80211_rx_h_data, already in 802.3 form. this scheme follows more
> precisely after the IEEE802.11 data plane archituecture, and will prevent
> code duplication to IEEE8021.11n A-MSDU handler.
> 
> added function:
>  - ieee80211_data_to_8023: transfering 802.11 data frames to 802.3 frame
>  - ieee80211_deliver_skb: delivering the 802.3 frames to upper stack
> eliminated handlers:
>  - ieee80211_rx_h_drop_unencrypted: now function ieee80211_drop_unencrypted
>  - ieee80211_rx_h_802_1x_pae: now function ieee80211_802_1x_pae
> changed handlers:
>  - ieee80211_rx_h_data: now contains calls to four above function
> 
> Signed-off-by: Ron Rindjunsky <ron.rindjunsky@xxxxxxxxx>

Looks good to me, thanks.

Acked-by: Johannes Berg <johannes@xxxxxxxxxxxxxxxx>

I'll clean out the eapol handling that looks a bit odd now w/o the
management interface in a later patch.

> ---
>  net/mac80211/ieee80211_i.h |    2 +-
>  net/mac80211/rx.c          |  124 +++++++++++++++++++++++++++-----------------
>  net/mac80211/tx.c          |   12 +++--
>  net/mac80211/util.c        |   14 +-----
>  4 files changed, 86 insertions(+), 66 deletions(-)
> 
> diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
> index b4e32ab..0444809 100644
> --- a/net/mac80211/ieee80211_i.h
> +++ b/net/mac80211/ieee80211_i.h
> @@ -792,7 +792,7 @@ extern void *mac80211_wiphy_privid; /* for wiphy privid */
>  extern const unsigned char rfc1042_header[6];
>  extern const unsigned char bridge_tunnel_header[6];
>  u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len);
> -int ieee80211_is_eapol(const struct sk_buff *skb);
> +int ieee80211_is_eapol(const struct sk_buff *skb, int hdrlen);
>  int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
>  			     int rate, int erp, int short_preamble);
>  void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx,
> diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
> index 428a9fc..6333c98 100644
> --- a/net/mac80211/rx.c
> +++ b/net/mac80211/rx.c
> @@ -956,68 +956,64 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx)
>  	return TXRX_CONTINUE;
>  }
>  
> -static ieee80211_txrx_result
> -ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx)
> +static int
> +ieee80211_drop_802_1x_pae(struct ieee80211_txrx_data *rx, int hdrlen)
>  {
> -	if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb) &&
> +	if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb, hdrlen) &&
>  	    rx->sdata->type != IEEE80211_IF_TYPE_STA &&
>  	    (rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
> -		return TXRX_CONTINUE;
> +		return 0;
>  
>  	if (unlikely(rx->sdata->ieee802_1x &&
>  		     (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
>  		     (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&
>  		     (!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)) &&
> -		     !ieee80211_is_eapol(rx->skb))) {
> +		     !ieee80211_is_eapol(rx->skb, hdrlen))) {
>  #ifdef CONFIG_MAC80211_DEBUG
> -		struct ieee80211_hdr *hdr =
> -			(struct ieee80211_hdr *) rx->skb->data;
> -		DECLARE_MAC_BUF(mac);
> -		printk(KERN_DEBUG "%s: dropped frame from %s"
> -		       " (unauthorized port)\n", rx->dev->name,
> -		       print_mac(mac, hdr->addr2));
> +		printk(KERN_DEBUG "%s: dropped frame "
> +		       "(unauthorized port)\n", rx->dev->name);
>  #endif /* CONFIG_MAC80211_DEBUG */
> -		return TXRX_DROP;
> +		return -EACCES;
>  	}
>  
> -	return TXRX_CONTINUE;
> +	return 0;
>  }
>  
> -static ieee80211_txrx_result
> -ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx)
> +static int
> +ieee80211_drop_unencrypted(struct ieee80211_txrx_data *rx, int hdrlen)
>  {
>  	/*
>  	 * Pass through unencrypted frames if the hardware has
>  	 * decrypted them already.
>  	 */
>  	if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED)
> -		return TXRX_CONTINUE;
> +		return 0;
>  
>  	/* Drop unencrypted frames if key is set. */
>  	if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) &&
>  		     (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
>  		     (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&
>  		     rx->sdata->drop_unencrypted &&
> -		     (rx->sdata->eapol == 0 || !ieee80211_is_eapol(rx->skb)))) {
> +		     (!rx->sdata->eapol ||
> +		      !ieee80211_is_eapol(rx->skb, hdrlen)))) {
>  		if (net_ratelimit())
>  			printk(KERN_DEBUG "%s: RX non-WEP frame, but expected "
>  			       "encryption\n", rx->dev->name);
> -		return TXRX_DROP;
> +		return -EACCES;
>  	}
> -	return TXRX_CONTINUE;
> +	return 0;
>  }
>  
> -static ieee80211_txrx_result
> -ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
> +static int
> +ieee80211_data_to_8023(struct ieee80211_txrx_data *rx)
>  {
>  	struct net_device *dev = rx->dev;
> -	struct ieee80211_local *local = rx->local;
>  	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
>  	u16 fc, hdrlen, ethertype;
>  	u8 *payload;
>  	u8 dst[ETH_ALEN];
>  	u8 src[ETH_ALEN];
> -	struct sk_buff *skb = rx->skb, *skb2;
> +	struct sk_buff *skb = rx->skb;
>  	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
>  	DECLARE_MAC_BUF(mac);
>  	DECLARE_MAC_BUF(mac2);
> @@ -1025,11 +1021,9 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
>  	DECLARE_MAC_BUF(mac4);
>  
>  	fc = rx->fc;
> -	if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
> -		return TXRX_CONTINUE;
>  
>  	if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
> -		return TXRX_DROP;
> +		return -1;
>  
>  	hdrlen = ieee80211_get_hdrlen(fc);
>  
> @@ -1058,7 +1052,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
>  				       print_mac(mac, hdr->addr1),
>  				       print_mac(mac2, hdr->addr2),
>  				       print_mac(mac3, hdr->addr3));
> -			return TXRX_DROP;
> +			return -1;
>  		}
>  		break;
>  	case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
> @@ -1075,7 +1069,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
>  				       print_mac(mac2, hdr->addr2),
>  				       print_mac(mac3, hdr->addr3),
>  				       print_mac(mac4, hdr->addr4));
> -			return TXRX_DROP;
> +			return -1;
>  		}
>  		break;
>  	case IEEE80211_FCTL_FROMDS:
> @@ -1086,7 +1080,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
>  		if (sdata->type != IEEE80211_IF_TYPE_STA ||
>  		    (is_multicast_ether_addr(dst) &&
>  		     !compare_ether_addr(src, dev->dev_addr)))
> -			return TXRX_DROP;
> +			return -1;
>  		break;
>  	case 0:
>  		/* DA SA BSSID */
> @@ -1102,21 +1096,20 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
>  				       print_mac(mac2, hdr->addr2),
>  				       print_mac(mac3, hdr->addr3));
>  			}
> -			return TXRX_DROP;
> +			return -1;
>  		}
>  		break;
>  	}
>  
> -	payload = skb->data + hdrlen;
> -
>  	if (unlikely(skb->len - hdrlen < 8)) {
>  		if (net_ratelimit()) {
>  			printk(KERN_DEBUG "%s: RX too short data frame "
>  			       "payload\n", dev->name);
>  		}
> -		return TXRX_DROP;
> +		return -1;
>  	}
>  
> +	payload = skb->data + hdrlen;
>  	ethertype = (payload[6] << 8) | payload[7];
>  
>  	if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
> @@ -1137,12 +1130,19 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
>  		memcpy(ehdr->h_source, src, ETH_ALEN);
>  		ehdr->h_proto = len;
>  	}
> -	skb->dev = dev;
> +	return 0;
> +}
>  
> -	skb2 = NULL;
> +static void
> +ieee80211_deliver_skb(struct ieee80211_txrx_data *rx)
> +{
> +	struct net_device *dev = rx->dev;
> +	struct ieee80211_local *local = rx->local;
> +	struct sk_buff *skb, *xmit_skb;
> +	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
>  
> -	dev->stats.rx_packets++;
> -	dev->stats.rx_bytes += skb->len;
> +	skb = rx->skb;
> +	xmit_skb = NULL;
>  
>  	if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP
>  	    || sdata->type == IEEE80211_IF_TYPE_VLAN) &&
> @@ -1150,8 +1150,8 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
>  		if (is_multicast_ether_addr(skb->data)) {
>  			/* send multicast frames both to higher layers in
>  			 * local net stack and back to the wireless media */
> -			skb2 = skb_copy(skb, GFP_ATOMIC);
> -			if (!skb2 && net_ratelimit())
> +			xmit_skb = skb_copy(skb, GFP_ATOMIC);
> +			if (!xmit_skb && net_ratelimit())
>  				printk(KERN_DEBUG "%s: failed to clone "
>  				       "multicast frame\n", dev->name);
>  		} else {
> @@ -1166,7 +1166,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
>  				 * AP, so send the frame directly to it and
>  				 * do not pass the frame to local net stack.
>  				 */
> -				skb2 = skb;
> +				xmit_skb = skb;
>  				skb = NULL;
>  			}
>  			if (dsta)
> @@ -1181,13 +1181,45 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
>  		netif_rx(skb);
>  	}
>  
> -	if (skb2) {
> +	if (xmit_skb) {
>  		/* send to wireless media */
> -		skb2->protocol = __constant_htons(ETH_P_802_3);
> -		skb_set_network_header(skb2, 0);
> -		skb_set_mac_header(skb2, 0);
> -		dev_queue_xmit(skb2);
> +		xmit_skb->protocol = __constant_htons(ETH_P_802_3);
> +		skb_set_network_header(xmit_skb, 0);
> +		skb_set_mac_header(xmit_skb, 0);
> +		dev_queue_xmit(xmit_skb);
>  	}
> +}
> +
> +static ieee80211_txrx_result
> +ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
> +{
> +	struct net_device *dev = rx->dev;
> +	u16 fc;
> +	int err, hdrlen;
> +
> +	fc = rx->fc;
> +	if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
> +		return TXRX_CONTINUE;
> +
> +	if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
> +		return TXRX_DROP;
> +
> +	hdrlen = ieee80211_get_hdrlen(fc);
> +
> +	if ((ieee80211_drop_802_1x_pae(rx, hdrlen)) ||
> +	    (ieee80211_drop_unencrypted(rx, hdrlen)))
> +		return TXRX_DROP;
> +
> +	err = ieee80211_data_to_8023(rx);
> +	if (unlikely(err))
> +		return TXRX_DROP;
> +
> +	rx->skb->dev = dev;
> +
> +	dev->stats.rx_packets++;
> +	dev->stats.rx_bytes += rx->skb->len;
> +
> +	ieee80211_deliver_skb(rx);
>  
>  	return TXRX_QUEUED;
>  }
> @@ -1341,8 +1373,6 @@ ieee80211_rx_handler ieee80211_rx_handlers[] =
>  	 * are not passed to user space by these functions
>  	 */
>  	ieee80211_rx_h_remove_qos_control,
> -	ieee80211_rx_h_802_1x_pae,
> -	ieee80211_rx_h_drop_unencrypted,
>  	ieee80211_rx_h_data,
>  	ieee80211_rx_h_mgmt,
>  	NULL
> diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
> index 1a53154..8b3f056 100644
> --- a/net/mac80211/tx.c
> +++ b/net/mac80211/tx.c
> @@ -420,7 +420,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
>  	return TXRX_CONTINUE;
>  }
>  
> -
>  static ieee80211_txrx_result
>  ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
>  {
> @@ -433,13 +432,15 @@ ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
>  		return ieee80211_tx_h_multicast_ps_buf(tx);
>  }
>  
> -
> -
> -
>  static ieee80211_txrx_result
>  ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
>  {
>  	struct ieee80211_key *key;
> +	const struct ieee80211_hdr *hdr;
> +	u16 fc;
> +
> +	hdr = (const struct ieee80211_hdr *) tx->skb->data;
> +	fc = le16_to_cpu(hdr->frame_control);
>  
>  	if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
>  		tx->key = NULL;
> @@ -448,7 +449,8 @@ ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
>  	else if ((key = rcu_dereference(tx->sdata->default_key)))
>  		tx->key = key;
>  	else if (tx->sdata->drop_unencrypted &&
> -		 !(tx->sdata->eapol && ieee80211_is_eapol(tx->skb))) {
> +		 !(tx->sdata->eapol &&
> +		   ieee80211_is_eapol(tx->skb, ieee80211_get_hdrlen(fc)))) {
>  		I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
>  		return TXRX_DROP;
>  	} else {
> diff --git a/net/mac80211/util.c b/net/mac80211/util.c
> index 5a0564e..f90287a 100644
> --- a/net/mac80211/util.c
> +++ b/net/mac80211/util.c
> @@ -217,23 +217,11 @@ int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
>  }
>  EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
>  
> -int ieee80211_is_eapol(const struct sk_buff *skb)
> +int ieee80211_is_eapol(const struct sk_buff *skb, int hdrlen)
>  {
> -	const struct ieee80211_hdr *hdr;
> -	u16 fc;
> -	int hdrlen;
> -
>  	if (unlikely(skb->len < 10))
>  		return 0;
>  
> -	hdr = (const struct ieee80211_hdr *) skb->data;
> -	fc = le16_to_cpu(hdr->frame_control);
> -
> -	if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
> -		return 0;
> -
> -	hdrlen = ieee80211_get_hdrlen(fc);
> -
>  	if (unlikely(skb->len >= hdrlen + sizeof(eapol_header) &&
>  		     memcmp(skb->data + hdrlen, eapol_header,
>  			    sizeof(eapol_header)) == 0))

Attachment: signature.asc
Description: This is a digitally signed message part


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux