[PATCH] ieee82011: Added ieee80211_tx_frame to convert generic 802.11 data frames, and callbacks
tree 40adc78b623ae70d56074934ec6334eb4f0ae6a5 parent db43d847bcebaa3df6414e26d0008eb21690e8cf author James Ketrenos <jketreno@linux.intel.com> 1124445938 -0500 committer James Ketrenos <jketreno@linux.intel.com> 1127313102 -0500 Added ieee80211_tx_frame to convert generic 802.11 data frames into txbs for transmission. Added several purpose specific callbacks (handle_assoc, handle_auth, etc.) which the driver can register with for being notified on reception of variouf frame elements. Signed-off-by: James Ketrenos <jketreno@linux.intel.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
This commit is contained in:
		
							parent
							
								
									3cdd00c582
								
							
						
					
					
						commit
						3f552bbf86
					
				| @ -769,6 +769,27 @@ struct ieee80211_device { | ||||
| 	int (*hard_start_xmit) (struct ieee80211_txb * txb, | ||||
| 				struct net_device * dev); | ||||
| 	int (*reset_port) (struct net_device * dev); | ||||
| 	int (*is_queue_full) (struct net_device * dev, int pri); | ||||
| 
 | ||||
| 	/* Typical STA methods */ | ||||
| 	int (*handle_auth) (struct net_device * dev, | ||||
| 			    struct ieee80211_auth * auth); | ||||
| 	int (*handle_disassoc) (struct net_device * dev, | ||||
| 				struct ieee80211_disassoc * assoc); | ||||
| 	int (*handle_beacon) (struct net_device * dev, | ||||
| 			      struct ieee80211_beacon * beacon, | ||||
| 			      struct ieee80211_network * network); | ||||
| 	int (*handle_probe_response) (struct net_device * dev, | ||||
| 				      struct ieee80211_probe_response * resp, | ||||
| 				      struct ieee80211_network * network); | ||||
| 	int (*handle_assoc_response) (struct net_device * dev, | ||||
| 				      struct ieee80211_assoc_response * resp, | ||||
| 				      struct ieee80211_network * network); | ||||
| 
 | ||||
| 	/* Typical AP methods */ | ||||
| 	int (*handle_assoc_request) (struct net_device * dev); | ||||
| 	int (*handle_reassoc_request) (struct net_device * dev, | ||||
| 				       struct ieee80211_reassoc_request * req); | ||||
| 
 | ||||
| 	/* This must be the last item so that it points to the data
 | ||||
| 	 * allocated beyond this structure by alloc_ieee80211 */ | ||||
| @ -877,6 +898,8 @@ extern int ieee80211_set_encryption(struct ieee80211_device *ieee); | ||||
| /* ieee80211_tx.c */ | ||||
| extern int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev); | ||||
| extern void ieee80211_txb_free(struct ieee80211_txb *); | ||||
| extern int ieee80211_tx_frame(struct ieee80211_device *ieee, | ||||
| 			      struct ieee80211_hdr *frame, int len); | ||||
| 
 | ||||
| /* ieee80211_rx.c */ | ||||
| extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, | ||||
|  | ||||
| @ -1029,12 +1029,18 @@ static inline void update_network(struct ieee80211_network *dst, | ||||
| 	/* dst->last_associate is not overwritten */ | ||||
| } | ||||
| 
 | ||||
| static inline int is_beacon(int fc) | ||||
| { | ||||
| 	return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON); | ||||
| } | ||||
| 
 | ||||
| static inline void ieee80211_process_probe_response(struct ieee80211_device | ||||
| 						    *ieee, struct | ||||
| 						    ieee80211_probe_response | ||||
| 						    *beacon, struct ieee80211_rx_stats | ||||
| 						    *stats) | ||||
| { | ||||
| 	struct net_device *dev = ieee->dev; | ||||
| 	struct ieee80211_network network; | ||||
| 	struct ieee80211_network *target; | ||||
| 	struct ieee80211_network *oldest = NULL; | ||||
| @ -1070,11 +1076,10 @@ static inline void ieee80211_process_probe_response(struct ieee80211_device | ||||
| 				     escape_essid(info_element->data, | ||||
| 						  info_element->len), | ||||
| 				     MAC_ARG(beacon->header.addr3), | ||||
| 				     WLAN_FC_GET_STYPE(le16_to_cpu | ||||
| 						       (beacon->header. | ||||
| 							frame_ctl)) == | ||||
| 				     IEEE80211_STYPE_PROBE_RESP ? | ||||
| 				     "PROBE RESPONSE" : "BEACON"); | ||||
| 				     is_beacon(le16_to_cpu | ||||
| 					       (beacon->header. | ||||
| 						frame_ctl)) ? | ||||
| 				     "BEACON" : "PROBE RESPONSE"); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| @ -1123,11 +1128,10 @@ static inline void ieee80211_process_probe_response(struct ieee80211_device | ||||
| 				     escape_essid(network.ssid, | ||||
| 						  network.ssid_len), | ||||
| 				     MAC_ARG(network.bssid), | ||||
| 				     WLAN_FC_GET_STYPE(le16_to_cpu | ||||
| 						       (beacon->header. | ||||
| 							frame_ctl)) == | ||||
| 				     IEEE80211_STYPE_PROBE_RESP ? | ||||
| 				     "PROBE RESPONSE" : "BEACON"); | ||||
| 				     is_beacon(le16_to_cpu | ||||
| 					       (beacon->header. | ||||
| 						frame_ctl)) ? | ||||
| 				     "BEACON" : "PROBE RESPONSE"); | ||||
| #endif | ||||
| 		memcpy(target, &network, sizeof(*target)); | ||||
| 		list_add_tail(&target->list, &ieee->network_list); | ||||
| @ -1136,15 +1140,22 @@ static inline void ieee80211_process_probe_response(struct ieee80211_device | ||||
| 				     escape_essid(target->ssid, | ||||
| 						  target->ssid_len), | ||||
| 				     MAC_ARG(target->bssid), | ||||
| 				     WLAN_FC_GET_STYPE(le16_to_cpu | ||||
| 						       (beacon->header. | ||||
| 							frame_ctl)) == | ||||
| 				     IEEE80211_STYPE_PROBE_RESP ? | ||||
| 				     "PROBE RESPONSE" : "BEACON"); | ||||
| 				     is_beacon(le16_to_cpu | ||||
| 					       (beacon->header. | ||||
| 						frame_ctl)) ? | ||||
| 				     "BEACON" : "PROBE RESPONSE"); | ||||
| 		update_network(target, &network); | ||||
| 	} | ||||
| 
 | ||||
| 	spin_unlock_irqrestore(&ieee->lock, flags); | ||||
| 
 | ||||
| 	if (is_beacon(le16_to_cpu(beacon->header.frame_ctl))) { | ||||
| 		if (ieee->handle_beacon != NULL) | ||||
| 			ieee->handle_beacon(dev, beacon, &network); | ||||
| 	} else { | ||||
| 		if (ieee->handle_probe_response != NULL) | ||||
| 			ieee->handle_probe_response(dev, beacon, &network); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void ieee80211_rx_mgt(struct ieee80211_device *ieee, | ||||
| @ -1185,6 +1196,23 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee, | ||||
| 						  ieee80211_probe_response *) | ||||
| 						 header, stats); | ||||
| 		break; | ||||
| 	case IEEE80211_STYPE_AUTH: | ||||
| 
 | ||||
| 		IEEE80211_DEBUG_MGMT("recieved auth (%d)\n", | ||||
| 				     WLAN_FC_GET_STYPE(le16_to_cpu | ||||
| 						       (header->frame_ctl))); | ||||
| 
 | ||||
| 		if (ieee->handle_auth != NULL) | ||||
| 			ieee->handle_auth(ieee->dev, | ||||
| 					  (struct ieee80211_auth *)header); | ||||
| 		break; | ||||
| 
 | ||||
| 	case IEEE80211_STYPE_DISASSOC: | ||||
| 		if (ieee->handle_disassoc != NULL) | ||||
| 			ieee->handle_disassoc(ieee->dev, | ||||
| 					      (struct ieee80211_disassoc *) | ||||
| 					      header); | ||||
| 		break; | ||||
| 
 | ||||
| 	default: | ||||
| 		IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n", | ||||
|  | ||||
| @ -459,7 +459,71 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | ||||
| 	netif_stop_queue(dev); | ||||
| 	stats->tx_errors++; | ||||
| 	return 1; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /* Incoming 802.11 strucure is converted to a TXB
 | ||||
|  * a block of 802.11 fragment packets (stored as skbs) */ | ||||
| int ieee80211_tx_frame(struct ieee80211_device *ieee, | ||||
| 		       struct ieee80211_hdr *frame, int len) | ||||
| { | ||||
| 	struct ieee80211_txb *txb = NULL; | ||||
| 	unsigned long flags; | ||||
| 	struct net_device_stats *stats = &ieee->stats; | ||||
| 	struct sk_buff *skb_frag; | ||||
| 
 | ||||
| 	spin_lock_irqsave(&ieee->lock, flags); | ||||
| 
 | ||||
| 	/* If there is no driver handler to take the TXB, dont' bother
 | ||||
| 	 * creating it... */ | ||||
| 	if (!ieee->hard_start_xmit) { | ||||
| 		printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); | ||||
| 		goto success; | ||||
| 	} | ||||
| 
 | ||||
| 	if (unlikely(len < 24)) { | ||||
| 		printk(KERN_WARNING "%s: skb too small (%d).\n", | ||||
| 		       ieee->dev->name, len); | ||||
| 		goto success; | ||||
| 	} | ||||
| 
 | ||||
| 	/* When we allocate the TXB we allocate enough space for the reserve
 | ||||
| 	 * and full fragment bytes (bytes_per_frag doesn't include prefix, | ||||
| 	 * postfix, header, FCS, etc.) */ | ||||
| 	txb = ieee80211_alloc_txb(1, len, GFP_ATOMIC); | ||||
| 	if (unlikely(!txb)) { | ||||
| 		printk(KERN_WARNING "%s: Could not allocate TXB\n", | ||||
| 		       ieee->dev->name); | ||||
| 		goto failed; | ||||
| 	} | ||||
| 	txb->encrypted = 0; | ||||
| 	txb->payload_size = len; | ||||
| 
 | ||||
| 	skb_frag = txb->fragments[0]; | ||||
| 
 | ||||
| 	memcpy(skb_put(skb_frag, len), frame, len); | ||||
| 
 | ||||
| 	if (ieee->config & | ||||
| 	    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) | ||||
| 		skb_put(skb_frag, 4); | ||||
| 
 | ||||
|       success: | ||||
| 	spin_unlock_irqrestore(&ieee->lock, flags); | ||||
| 
 | ||||
| 	if (txb) { | ||||
| 		if ((*ieee->hard_start_xmit) (txb, ieee->dev) == 0) { | ||||
| 			stats->tx_packets++; | ||||
| 			stats->tx_bytes += txb->payload_size; | ||||
| 			return 0; | ||||
| 		} | ||||
| 		ieee80211_txb_free(txb); | ||||
| 	} | ||||
| 	return 0; | ||||
| 
 | ||||
|       failed: | ||||
| 	spin_unlock_irqrestore(&ieee->lock, flags); | ||||
| 	stats->tx_errors++; | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| EXPORT_SYMBOL(ieee80211_tx_frame); | ||||
| EXPORT_SYMBOL(ieee80211_txb_free); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user