[PATCH] ieee82011: Added ieee80211_tx_frame to convert generic 802.11 data frames...
authorJames Ketrenos <jketreno@linux.intel.com>
Wed, 21 Sep 2005 16:54:47 +0000 (11:54 -0500)
committerJeff Garzik <jgarzik@pobox.com>
Thu, 22 Sep 2005 03:02:31 +0000 (23:02 -0400)
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>
include/net/ieee80211.h
net/ieee80211/ieee80211_rx.c
net/ieee80211/ieee80211_tx.c

index 5e11ccf8a7631cffaa1848c1d3aecdd92c7cf411..43cf2e57719126fa650503b878b77e99d3498c6d 100644 (file)
@@ -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,
index 71d14c7d915c6460846cbfea27b2bf6cdf56d3f4..d1ae28280d7e82c3ea4b387c8dd1b590e91d8a9e 100644 (file)
@@ -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",
index cdee41cefb263dbfdf1299796abc4b1be6025213..f505aa127e21cc9e1378e18329a9addfad836c43 100644 (file)
@@ -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);