iPXE
Functions
802.11 driver interface API

Functions

struct net80211_devicenet80211_alloc (size_t priv_size)
 Allocate 802.11 device.
int net80211_register (struct net80211_device *dev, struct net80211_device_operations *ops, struct net80211_hw_info *hw)
 Register 802.11 device with network stack.
u16 net80211_duration (struct net80211_device *dev, int bytes, u16 rate)
 Calculate one frame's contribution to 802.11 duration field.
void net80211_rx (struct net80211_device *dev, struct io_buffer *iob, int signal, u16 rate)
 Handle receipt of 802.11 frame.
void net80211_rx_err (struct net80211_device *dev, struct io_buffer *iob, int rc)
 Indicate an error in receiving a packet.
void net80211_tx_complete (struct net80211_device *dev, struct io_buffer *iob, int retries, int rc)
 Indicate the completed transmission of a packet.
void net80211_unregister (struct net80211_device *dev)
 Unregister 802.11 device from network stack.
void net80211_free (struct net80211_device *dev)
 Free 802.11 device.

Function Documentation

struct net80211_device* net80211_alloc ( size_t  priv_size) [read]

Allocate 802.11 device.

Parameters:
priv_sizeSize of driver-private allocation area
Return values:
devNewly allocated 802.11 device

This function allocates a net_device with space in its private area for both the net80211_device it will wrap and the driver-private data space requested. It initializes the link-layer-specific parts of the net_device, and links the net80211_device to the net_device appropriately.

Definition at line 754 of file net80211.c.

References alloc_netdev(), net_device::dev, eth_broadcast, IEEE80211_MAX_DATA_LEN, INIT_LIST_HEAD, net_device::ll_broadcast, net_device::ll_protocol, net_device::max_pkt_len, net80211_device::mgmt_info_queue, net80211_device::mgmt_queue, net80211_null_ops, netdev, net80211_device::netdev, netdev_init(), NULL, net80211_device::op, net_device::priv, net80211_device::priv, net80211_device::proc_assoc, process_init_stopped(), and net_device::refcnt.

Referenced by ath5k_probe(), ath_pci_probe(), and rtl818x_probe().

{
        struct net80211_device *dev;
        struct net_device *netdev =
                alloc_netdev ( sizeof ( *dev ) + priv_size );

        if ( ! netdev )
                return NULL;

        netdev->ll_protocol = &net80211_ll_protocol;
        netdev->ll_broadcast = eth_broadcast;
        netdev->max_pkt_len = IEEE80211_MAX_DATA_LEN;
        netdev_init ( netdev, &net80211_netdev_ops );

        dev = netdev->priv;
        dev->netdev = netdev;
        dev->priv = ( u8 * ) dev + sizeof ( *dev );
        dev->op = &net80211_null_ops;

        process_init_stopped ( &dev->proc_assoc, &net80211_process_desc,
                               &netdev->refcnt );
        INIT_LIST_HEAD ( &dev->mgmt_queue );
        INIT_LIST_HEAD ( &dev->mgmt_info_queue );

        return dev;
}
int net80211_register ( struct net80211_device dev,
struct net80211_device_operations ops,
struct net80211_hw_info hw 
)

Register 802.11 device with network stack.

Parameters:
dev802.11 device
ops802.11 device operations
hw802.11 hardware information

This also registers the wrapping net_device with the higher network layers.

Definition at line 791 of file net80211.c.

References net80211_device::channel, net80211_hw_info::channels, net80211_device::channels, ENOMEM, ETH_ALEN, net80211_device::hw, net_device::hw_addr, net80211_hw_info::hwaddr, net80211_device_operations::irq, net80211_device::list, list_add_tail, malloc(), memcpy(), NET80211_MAX_CHANNELS, net80211_device::netdev, NETDEV_IRQ_UNSUPPORTED, net80211_device::op, register_netdev(), and net_device::state.

Referenced by ath5k_attach(), ath9k_init_device(), and rtl818x_probe().

{
        dev->op = ops;
        dev->hw = malloc ( sizeof ( *hw ) );
        if ( ! dev->hw )
                return -ENOMEM;

        memcpy ( dev->hw, hw, sizeof ( *hw ) );
        memcpy ( dev->netdev->hw_addr, hw->hwaddr, ETH_ALEN );

        /* Set some sensible channel defaults for driver's open() function */
        memcpy ( dev->channels, dev->hw->channels,
                 NET80211_MAX_CHANNELS * sizeof ( dev->channels[0] ) );
        dev->channel = 0;

        /* Mark device as not supporting interrupts, if applicable */
        if ( ! ops->irq )
                dev->netdev->state |= NETDEV_IRQ_UNSUPPORTED;

        list_add_tail ( &dev->list, &net80211_devices );
        return register_netdev ( dev->netdev );
}
u16 net80211_duration ( struct net80211_device dev,
int  bytes,
u16  rate 
)

Calculate one frame's contribution to 802.11 duration field.

Parameters:
dev802.11 device
bytesAmount of data to calculate duration for
Return values:
durDuration field in microseconds

To avoid multiple stations attempting to transmit at once, 802.11 provides that every packet shall include a duration field specifying a length of time for which the wireless medium will be reserved after it is transmitted. The duration is measured in microseconds and is calculated with respect to the current physical-layer parameters of the 802.11 device.

For an unfragmented data or management frame, or the last fragment of a fragmented frame, the duration captures only the 10 data bytes of one ACK; call once with bytes = 10.

For a fragment of a data or management rame that will be followed by more fragments, the duration captures an ACK, the following fragment, and its ACK; add the results of three calls, two with bytes = 10 and one with bytes set to the next fragment's size.

For an RTS control frame, the duration captures the responding CTS, the frame being sent, and its ACK; add the results of three calls, two with bytes = 10 and one with bytes set to the next frame's size (assuming unfragmented).

For a CTS-to-self control frame, the duration captures the frame being protected and its ACK; add the results of two calls, one with bytes = 10 and one with bytes set to the next frame's size.

No other frame types are currently supported by iPXE.

Definition at line 441 of file net80211.c.

References net80211_channel::band, net80211_device::channel, net80211_device::channels, NET80211_BAND_5GHZ, NET80211_PHY_USE_SHORT_PREAMBLE, net80211_rate_is_erp(), and net80211_device::phy_flags.

Referenced by ath5k_hw_write_rate_duration(), net80211_cts_duration(), net80211_ll_push(), and net80211_tx_mgmt().

{
        struct net80211_channel *chan = &dev->channels[dev->channel];
        u32 kbps = rate * 100;

        if ( chan->band == NET80211_BAND_5GHZ || net80211_rate_is_erp ( rate ) ) {
                /* OFDM encoding (802.11a/g) */
                int bits_per_symbol = ( kbps * 4 ) / 1000;      /* 4us/symbol */
                int bits = 22 + ( bytes << 3 ); /* 22-bit PLCP */
                int symbols = ( bits + bits_per_symbol - 1 ) / bits_per_symbol;

                return 16 + 20 + ( symbols * 4 ); /* 16us SIFS, 20us preamble */
        } else {
                /* CCK encoding (802.11b) */
                int phy_time = 144 + 48;        /* preamble + PLCP */
                int bits = bytes << 3;
                int data_time = ( bits * 1000 + kbps - 1 ) / kbps;

                if ( dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE )
                        phy_time >>= 1;

                return 10 + phy_time + data_time; /* 10us SIFS */
        }
}
void net80211_rx ( struct net80211_device dev,
struct io_buffer iob,
int  signal,
u16  rate 
)

Handle receipt of 802.11 frame.

Parameters:
dev802.11 device
iobI/O buffer
signalReceived signal strength
rateBitrate at which frame was received, in 100 kbps units

If the rate or signal is unknown, 0 should be passed.

Definition at line 2689 of file net80211.c.

References ieee80211_frame::addr1, ieee80211_frame::addr2, net80211_device::bssid, net80211_device::crypto, io_buffer::data, DBGC, DBGC2, net80211_crypto::decrypt, EINVAL_CRYPTO_REQUEST, ETH_ALEN, ieee80211_frame::fc, net80211_hw_info::flags, free_iob(), net80211_device::gcrypto, hdr, net80211_device::hw, IEEE80211_FC_MORE_FRAG, IEEE80211_FC_PROTECTED, IEEE80211_FC_RETRY, IEEE80211_FC_SUBTYPE, IEEE80211_FC_TYPE, IEEE80211_FC_VERSION, IEEE80211_FRAG, IEEE80211_STYPE_DATA, IEEE80211_THIS_VERSION, IEEE80211_TYPE_CTRL, IEEE80211_TYPE_MGMT, iob_unput, net80211_device::last_rx_seq, net80211_device::last_signal, memcmp(), NET80211_ASSOCIATED, net80211_handle_mgmt(), net80211_rx_frag(), net80211_device::netdev, netdev_rx(), netdev_rx_err(), NULL, rc80211_update_rx(), net80211_device::rctl, ieee80211_frame::seq, net80211_device::state, and type.

Referenced by ath5k_handle_rx(), ath_rx_tasklet(), net80211_rx_frag(), and rtl818x_handle_rx().

{
        struct ieee80211_frame *hdr = iob->data;
        u16 type = hdr->fc & IEEE80211_FC_TYPE;
        if ( ( hdr->fc & IEEE80211_FC_VERSION ) != IEEE80211_THIS_VERSION )
                goto drop;      /* drop invalid-version packets */

        if ( type == IEEE80211_TYPE_CTRL )
                goto drop;      /* we don't handle control packets,
                                   the hardware does */

        if ( dev->last_rx_seq == hdr->seq )
                goto drop;      /* avoid duplicate packet */
        dev->last_rx_seq = hdr->seq;

        if ( dev->hw->flags & NET80211_HW_RX_HAS_FCS ) {
                /* discard the FCS */
                iob_unput ( iob, 4 );
        }

        /* Only decrypt packets from our BSSID, to avoid spurious errors */
        if ( ( hdr->fc & IEEE80211_FC_PROTECTED ) &&
             ! memcmp ( hdr->addr2, dev->bssid, ETH_ALEN ) ) {
                /* Decrypt packet; record and drop if it fails */
                struct io_buffer *niob;
                struct net80211_crypto *crypto = dev->crypto;

                if ( ! dev->crypto ) {
                        DBGC ( dev, "802.11 %p cannot decrypt packet "
                               "without a cryptosystem\n", dev );
                        goto drop_crypt;
                }

                if ( ( hdr->addr1[0] & 1 ) && dev->gcrypto ) {
                        /* Use group decryption if needed */
                        crypto = dev->gcrypto;
                }

                niob = crypto->decrypt ( crypto, iob );
                if ( ! niob ) {
                        DBGC ( dev, "802.11 %p decryption error\n", dev );
                        goto drop_crypt;
                }
                free_iob ( iob );
                iob = niob;
                hdr = iob->data;
        }

        dev->last_signal = signal;

        /* Fragments go into the frag cache or get dropped. */
        if ( IEEE80211_FRAG ( hdr->seq ) != 0
             || ( hdr->fc & IEEE80211_FC_MORE_FRAG ) ) {
                net80211_rx_frag ( dev, iob, signal );
                return;
        }

        /* Management frames get handled, enqueued, or dropped. */
        if ( type == IEEE80211_TYPE_MGMT ) {
                net80211_handle_mgmt ( dev, iob, signal );
                return;
        }

        /* Data frames get dropped or sent to the net_device. */
        if ( ( hdr->fc & IEEE80211_FC_SUBTYPE ) != IEEE80211_STYPE_DATA )
                goto drop;      /* drop QoS, CFP, or null data packets */

        /* Update rate-control algorithm */
        if ( dev->rctl )
                rc80211_update_rx ( dev, hdr->fc & IEEE80211_FC_RETRY, rate );

        /* Pass packet onward */
        if ( dev->state & NET80211_ASSOCIATED ) {
                netdev_rx ( dev->netdev, iob );
                return;
        }

        /* No association? Drop it. */
        goto drop;

 drop_crypt:
        netdev_rx_err ( dev->netdev, NULL, EINVAL_CRYPTO_REQUEST );
 drop:
        DBGC2 ( dev, "802.11 %p dropped packet fc=%04x seq=%04x\n", dev,
                hdr->fc, hdr->seq );
        free_iob ( iob );
        return;
}
void net80211_rx_err ( struct net80211_device dev,
struct io_buffer iob,
int  rc 
)

Indicate an error in receiving a packet.

Parameters:
dev802.11 device
iobI/O buffer with received packet, or NULL
rcError code

This logs the error with the wrapping net_device, and frees iob if it is passed.

Definition at line 2788 of file net80211.c.

References net80211_device::netdev, and netdev_rx_err().

Referenced by ath5k_handle_rx(), and rtl818x_handle_rx().

{
        netdev_rx_err ( dev->netdev, iob, rc );
}
void net80211_tx_complete ( struct net80211_device dev,
struct io_buffer iob,
int  retries,
int  rc 
)

Indicate the completed transmission of a packet.

Parameters:
dev802.11 device
iobI/O buffer of transmitted packet
retriesNumber of times this packet was retransmitted
rcError code, or 0 for success

This logs an error with the wrapping net_device if one occurred, and removes and frees the I/O buffer from its TX queue. The provided retry information is used to tune our transmission rate.

If the packet did not need to be retransmitted because it was properly ACKed the first time, retries should be 0.

Definition at line 2808 of file net80211.c.

References net80211_device::netdev, netdev_tx_complete_err(), rc80211_update_tx(), and net80211_device::rctl.

Referenced by ath5k_tx_processq(), ath5k_txbuf_free(), ath_tx_complete(), rtl818x_free_tx_ring(), and rtl818x_handle_tx().

{
        /* Update rate-control algorithm */
        if ( dev->rctl )
                rc80211_update_tx ( dev, retries, rc );

        /* Pass completion onward */
        netdev_tx_complete_err ( dev->netdev, iob, rc );
}
void net80211_unregister ( struct net80211_device dev)

Unregister 802.11 device from network stack.

Parameters:
dev802.11 device

After this call, the device operations are cleared so that they will not be called.

Definition at line 824 of file net80211.c.

References net80211_device::list, list_del, net80211_null_ops, net80211_device::netdev, net80211_device::op, and unregister_netdev().

Referenced by ath5k_detach(), ath9k_deinit_device(), and rtl818x_remove().

{
        unregister_netdev ( dev->netdev );
        list_del ( &dev->list );
        dev->op = &net80211_null_ops;
}
void net80211_free ( struct net80211_device dev)

Free 802.11 device.

Parameters:
dev802.11 device

The device should be unregistered before this function is called.

Definition at line 838 of file net80211.c.

References free, net80211_device::hw, net80211_device::netdev, netdev_nullify(), netdev_put(), rc80211_free(), and net80211_device::rctl.

Referenced by ath5k_probe(), ath5k_remove(), ath_pci_probe(), ath_pci_remove(), rtl818x_probe(), and rtl818x_remove().

{
        free ( dev->hw );
        rc80211_free ( dev->rctl );
        netdev_nullify ( dev->netdev );
        netdev_put ( dev->netdev );
}