[802.11] Add net80211.h with preliminary declarations for gPXE's 802.11 layer
authorJoshua Oreman <oremanj@xenon.get-linux.org>
Fri, 29 May 2009 23:59:02 +0000 (16:59 -0700)
committerJoshua Oreman <oremanj@xenon.get-linux.org>
Fri, 29 May 2009 23:59:02 +0000 (16:59 -0700)
src/include/gpxe/net80211.h [new file with mode: 0644]

diff --git a/src/include/gpxe/net80211.h b/src/include/gpxe/net80211.h
new file mode 100644 (file)
index 0000000..4b69b17
--- /dev/null
@@ -0,0 +1,341 @@
+#ifndef _GPXE_NET80211_H
+#define _GPXE_NET80211_H
+
+#include <gpxe/ieee80211.h>
+#include <gpxe/iobuf.h>
+
+/** @file
+ * The gPXE 802.11 MAC layer.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+/* All 802.11 devices are handled using a generic "802.11 device"
+   net_device, with a link in its `priv' field to a net80211_device
+   which we use to handle 802.11-specific details. */
+
+/* Constants for the (*config)() callback */
+#define NET80211_CFG_CHANNEL     (1 << 0)
+#define NET80211_CFG_RATE        (1 << 1)
+#define NET80211_CFG_ASSOC       (1 << 2)
+#define NET80211_CFG_ERP_PARAMS  (1 << 3)
+#define NET80211_CFG_BASIC_RATES (1 << 4)
+
+struct net80211_device;
+
+/** Operations that must be implemented by an 802.11 driver. */
+struct net80211_device_operations {
+       /* These have the same semantics as they do in net_device. */
+       int (*open)(struct net80211_device *netdev);
+       void (*close)(struct net80211_device *netdev);
+       int (*transmit)(struct net80211_device *netdev, struct io_buffer *iobuf);
+       void (*poll)(struct net80211_device *netdev);
+       void (*irq)(struct net80211_device *netdev, int enable);
+
+       /* And these are specific to 802.11. */
+
+       /** Update hardware state to match the state in
+           net80211_device with respect to `what', a bitwise OR of
+           NET80211_CFG_* indicating what's changed. Only called when
+           the device is open. */
+       int (*config)(struct net80211_device *netdev, int what);
+};
+
+#define NET80211_BAND_2GHZ  (1 << 0)   /* the 2.4 GHz ISM band */
+#define NET80211_BAND_5GHZ  (1 << 1)   /* the band from 4.9 to 5.7 GHz */
+
+/** An 802.11 RF channel. */
+struct net80211_channel
+{
+       unsigned band;          /* one of NET80211_BAND_* */
+
+       unsigned channel_nr;    /* a traditional channel number,
+                                  e.g. 1-11 for the 2.4GHz band */
+
+       unsigned center_freq;   /* MHz of channel center */
+       unsigned txpower;       /* maximum allowable EIRP in dBm */
+
+       /* There are more regulatory issues than this - bandwidth and
+          antenna gain are the main ones - but we can't do anything
+          about them based on the information in beacon frames, so we
+          assume 20 MHz bandwidth and a sane antenna setup by the user. */
+};
+
+#define NET80211_MODE_A  (1 << 0)
+#define NET80211_MODE_B  (1 << 1)
+#define NET80211_MODE_G  (1 << 2)
+#define NET80211_MODE_N  (1 << 3)
+
+/** Information on the capabilities of the hardware supported by a
+    driver; must be filled in by said driver. */
+struct net80211_hw_info
+{
+       /** A bitwise OR of the 802.11x modes supported by this device. */
+       int modes;              /* e.g. NET80211_MODE_B | NET80211_MODE_G */
+
+       /** A bitwise OR of the bands on which this device can communicate. */
+       int bands;              /* e.g. NET80211_BAND_2GHZ */
+
+       enum {
+               /** Received frames include a frame check sequence we
+                   need to verify ourselves. */
+               NET80211_HW_RX_HAS_FCS = (1 << 1),
+
+               /** Hardware doesn't support short preambles on the
+                   2.4GHz band (802.11b). */
+               NET80211_HW_NO_SHORT_PREAMBLE = (1 << 2),
+
+               /** Hardware doesn't support short slot operation on
+                   the 2.4GHz band (802.11g). */
+               NET80211_HW_NO_SHORT_SLOT = (1 << 3),
+       } flags;
+
+       /** Set according to the type of signal strength information
+           that can be provided. */
+       enum {
+               NET80211_SIGNAL_NONE = 0,
+               NET80211_SIGNAL_ARBITRARY, /* arbitrary units */
+               NET80211_SIGNAL_DB,        /* dB relative to arbitrary base */
+               NET80211_SIGNAL_DBM,       /* dB relative to 1mW */
+               NET80211_SIGNAL_NOISE_DBM, /* both signal and noise in dBm */
+       } signal_type;
+       
+       /** If signal_type involves arbitrary units, it should be
+           reported on a scale from 0 to signal_max. */
+       unsigned signal_max;
+
+       /** Amount of time required to change channels, in
+           microseconds. */
+       unsigned channel_change_time;
+
+       /** Minimum and maximum power values the hardware is capable
+           of transmitting, in dBm. Set < 0 if we don't know. */
+       int txpower_min, txpower_max;
+};
+
+/** Milliseconds we'll wait to get all fragments of a packet. If this
+    timer expires, we drop the fragments we've received so far. */
+#define NET80211_FRAG_TIMEOUT  2000
+
+/** Keeps track of the fragments for a particular packet as we receive
+    them. We set up the frag_cache entry when we receive a fragment 0
+    with MOREFRAGS set; if all are unexpired we take over the one with
+    the most recent activity (and drop the frags it used to contain).
+    If we get a fragment after the zeroth with no cache entry for its
+    packet, we drop it. The standard says we're allowed to be cavalier
+    like this, as long as we have >= 3 cache entries. */
+struct net80211_frag_cache
+{
+       /** Is this fragment cache entry being used (0) or not (1)? */
+       u16 avail;
+
+       /** Sequence number of this MSDU (packet). */
+       u16 seqnr;
+
+       /** Timestamp of when we started collecting these frags. */
+       u32 start_ticks;
+
+       /** Buffers for each fragment (they can arrive out of order). */
+       struct io_buffer *iob[16];
+};
+
+#define NET80211_MAX_RATES 16
+
+/** Structure encapsulating the complete state of an 802.11
+    device. Stored in the `priv' member of some net_device. */
+struct net80211_device
+{
+       /** The net_device that wraps us. */
+       struct net_device *netdev;
+
+       /** Network device operations */
+       struct net80211_device_operations *op;
+
+       /** Driver private data */
+       void *priv;
+
+       /** Information about the hardware, which the driver is
+           responsible for setting. */
+       struct net80211_hw_info *hw;
+
+       /** A list of all possible channels, as computed from
+           regulatory information in the beacon frame. `channel' is
+           an index into this list. */
+       struct net80211_channel *channels;
+       /** The number of channels in the `channels' list. */
+       int nr_channels;
+       /** The channel currently in use, as an index into the
+           `channels' list. */
+       int channel;
+
+       /** A list of all transmission rates supported by the AP we're
+           associated with, in units of 100 kbps. */
+       u16 rates[NET80211_MAX_RATES];
+       /** The number of transmission rates in the `rates' array. */
+       int nr_rates;   
+       /** If basic_rates & (1 << i), then rates[i] is a basic rate. */
+       u32 basic_rates;
+       /** The rate currently in use, as an index into the `rates' array. */
+       int rate;
+
+       /** Are we associated to a network? */
+       int assoc;
+       /** Network to which we're associated, if `assoc' is set. */
+       u8 bssid[ETH_ALEN];
+       /** Name of the SSID we're connected to. */
+       char essid[32];
+       /** Association ID given to us by the AP. */
+       u16 aid;
+       /** ERP-related options, set dynamically based on the assoc
+           reply packet. */
+       int erp_flags;
+#define NET80211_ERP_USE_CTS_PROTECTION  (1 << 1)
+#define NET80211_ERP_USE_SHORT_PREAMBLE  (1 << 2)
+#define NET80211_ERP_USE_SHORT_SLOT      (1 << 3)
+
+       /** Signal strength. Driver sets this when it feels like
+           it. (units from hw->signal_type) */
+       int signal;
+       /** Noise level, if the driver can provide it. (dBm) */
+       int noise;
+
+       /** Fragment reassembly state. IEEE standard requires >= 3. */
+#define NET80211_NR_CONCURRENT_FRAGS  3
+       struct net80211_frag_cache frags[NET80211_NR_CONCURRENT_FRAGS];
+
+       /** Packet deduping state. We only are required to handle
+           immediate duplicates for each direct sender, and as we can
+           only have one direct sender (the AP), our job is easy. */
+       int last_seqnr;
+       int last_frag;
+
+       /** TX packet queue. */
+       struct list_head tx_queue;
+
+       /** RX packet queue. Packets here go into netdev_rx(),
+           mgmt_queue, or the aether. */
+       struct list_head rx_queue;
+
+       /** Sometimes we want to keep management packets we receive,
+           e.g. when we're scanning for networks. They will be stored
+           in this queue when keep_mgmt is true. */
+       struct list_head mgmt_queue;
+
+       /** Store management packets only when TRUE. */
+       int keep_mgmt;
+};
+
+/* 802.11 data security protocols: */
+#define NET80211_CRYPT_NONE   0        /* "Open" */
+#define NET80211_CRYPT_WEP40  2        /* "WEP 64-bit" (5-character key) */
+#define NET80211_CRYPT_WEP104 3 /* "WEP 128-bit" (13-character key) */
+#define NET80211_CRYPT_TKIP   4        /* "WPA Personal" */
+#define NET80211_CRYPT_CCMP   5        /* "WPA2 Personal" */
+#define NET80211_CRYPT_EAP    8        /* "WPA2 Enterprise" */
+
+struct net80211_wlan
+{
+       /** The human-readable ESSID (network name). */
+       char essid[32];
+
+       /** The MAC address of the "best" access point (strongest
+           signal) for this ESSID. */
+       u8 bssid[ETH_ALEN];
+
+       /** The signal strength of communications from that access
+           point, measured in whatever units the hardware provides. */
+       int signal;
+
+       /** The channel on which that access point communicates. */
+       struct net80211_channel *channel;
+
+       /** One of the NET80211_CRYPT_* constants indicating the
+           security mode of the network. */
+       int security;
+
+       /** Link to allow chaining multiple structures into a list to
+           be returned from net80211_scan(). */
+       struct net80211_wlan *next;
+};
+
+/* Regulatory hints when we don't get any beacons: */
+#define NET80211_REG_TXPOWER  20 /* conservative default, OK with
+                                   US/EU/JP at least */
+/* 2.4GHz channels 1-11 and 5GHz channels 36, 40, and 44 are safe. */
+
+
+/* -- gPXE API: -- */
+
+/** Scans the area, returning a list of net80211_wlan structures
+    corresponding to each of the reachable wireless networks. */
+struct net80211_wlan *net80211_scan(struct net80211_device *dev);
+
+/** Scans for the given ESSID specifically. Can be used to associate
+    with "hidden" networks on the 2.4GHz band. */
+struct net80211_wlan *net80211_probe(struct net80211_device *dev, const char *essid);
+
+/** Frees the list returned from a scan or probe call. */
+void net80211_free_netlist(struct net80211_wlan *nets);
+
+/** Requests that we associate with the network identified by
+    `wlan'. If authentication credentials are required, they must
+    have been set up using a previous call. This function blocks until
+    the association either completes or fails. */
+int net80211_associate(struct net80211_device *dev, struct net80211_wlan *wlan);
+
+/** Sets the state of the device keeping management packets. Only call
+    this with enable == 1 if you're planning to actually look at all
+    the packets using net80211_mgmt_dequeue(); otherwise they'll pile
+    up and waste memory. Keeping management packets is disabled by
+    default. Returns the setting of keeping management packets that
+    preceded the function call. */
+int net80211_keep_mgmt(struct net80211_device *dev, int enable);
+
+/** Returns the next packet from the device's received management
+    packet queue, or NULL if the queue is empty. You must have called
+    net80211_set_management(dev, 1) previously. Ownership of the
+    returned io_buffer passes to the calling function. */
+struct io_buffer *net80211_mgmt_dequeue(struct net80211_device *dev);
+
+
+/* -- Driver API: -- */
+
+/** Allocates a new 802.11 device with priv_size bytes of
+    driver-private data behind its `priv' pointer. This also allocates
+    the gPXE net_device and sets up its operations. */
+struct net80211_device *net80211_alloc(size_t priv_size);
+
+/** Set up an 802.11 device to use the provided operations and
+    hardware information. The hw info will be copied into a
+    dynamically allocated structure that the 802.11 layer takes
+    ownership of; the ops are simply pointed at, and should be defined
+    statically. */
+int net80211_init(struct net80211_device *dev,
+                 struct net80211_device_operations *ops,
+                 struct net80211_hw_info *hw);
+
+/** Register an 802.11 device with the network stack. */
+int net80211_register(struct net80211_device *dev);
+
+/** Indicate receipt of a raw packet from the network interface. Takes
+    ownership of the iob. */
+int net80211_rx(struct net80211_device *dev, struct io_buffer *iob);
+
+/** Indicate an error in receiving a packet. Pass iob if you want it
+    freed. */
+int net80211_rx_err(struct net80211_device *dev, struct io_buffer *iob,
+                   int errcode);
+
+/** Indicate the completed transmission of a packet passed to
+    (*transmit)(), successfully if errcode == 0 and unsuccessfully if
+    not. In either case this function takes ownership of the iob. */
+int net80211_tx_complete(struct net80211_device *dev, struct io_buffer *iob,
+                        int errcode);
+
+/** Removes the registration of an 802.11 device. */
+void net80211_unregister(struct net80211_device *dev);
+
+/** Frees all memory allocated by the 802.11 layer for a device. */
+void net80211_free(struct net80211_device *dev);
+
+#endif