forked from Minki/linux
[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