iPXE
Functions
802.11 fragment handling functions

Functions

static void net80211_free_frags (struct net80211_device *dev, int fcid)
 Free buffers used by 802.11 fragment cache entry.
static struct io_buffernet80211_accum_frags (struct net80211_device *dev, int fcid, int nfrags, int size)
 Accumulate 802.11 fragments into one I/O buffer.
static void net80211_rx_frag (struct net80211_device *dev, struct io_buffer *iob, int signal)
 Handle receipt of 802.11 fragment.

Function Documentation

static void net80211_free_frags ( struct net80211_device dev,
int  fcid 
) [static]

Free buffers used by 802.11 fragment cache entry.

Parameters:
dev802.11 device
fcidFragment cache entry index

After this function, the referenced entry will be marked unused.

Definition at line 2533 of file net80211.c.

References net80211_device::frags, free_iob(), net80211_frag_cache::in_use, net80211_frag_cache::iob, NULL, net80211_frag_cache::seqnr, and net80211_frag_cache::start_ticks.

Referenced by net80211_rx_frag().

{
        int j;
        struct net80211_frag_cache *frag = &dev->frags[fcid];

        for ( j = 0; j < 16; j++ ) {
                if ( frag->iob[j] ) {
                        free_iob ( frag->iob[j] );
                        frag->iob[j] = NULL;
                }
        }

        frag->seqnr = 0;
        frag->start_ticks = 0;
        frag->in_use = 0;
}
static struct io_buffer * net80211_accum_frags ( struct net80211_device dev,
int  fcid,
int  nfrags,
int  size 
) [static, read]

Accumulate 802.11 fragments into one I/O buffer.

Parameters:
dev802.11 device
fcidFragment cache entry index
nfragsNumber of fragments received
sizeSum of sizes of all fragments, including headers
Return values:
iobI/O buffer containing reassembled packet

This function does not free the fragment buffers.

Definition at line 2561 of file net80211.c.

References alloc_iob(), io_buffer::data, ieee80211_frame::fc, net80211_device::frags, hdr, IEEE80211_FC_MORE_FRAG, IEEE80211_TYP_FRAME_HEADER_LEN, net80211_frag_cache::iob, iob_len(), iob_put, len, and memcpy().

Referenced by net80211_rx_frag().

{
        struct net80211_frag_cache *frag = &dev->frags[fcid];
        int hdrsize = IEEE80211_TYP_FRAME_HEADER_LEN;
        int nsize = size - hdrsize * ( nfrags - 1 );
        int i;

        struct io_buffer *niob = alloc_iob ( nsize );
        struct ieee80211_frame *hdr;

        /* Add the header from the first one... */
        memcpy ( iob_put ( niob, hdrsize ), frag->iob[0]->data, hdrsize );

        /* ... and all the data from all of them. */
        for ( i = 0; i < nfrags; i++ ) {
                int len = iob_len ( frag->iob[i] ) - hdrsize;
                memcpy ( iob_put ( niob, len ),
                         frag->iob[i]->data + hdrsize, len );
        }

        /* Turn off the fragment bit. */
        hdr = niob->data;
        hdr->fc &= ~IEEE80211_FC_MORE_FRAG;

        return niob;
}
static void net80211_rx_frag ( struct net80211_device dev,
struct io_buffer iob,
int  signal 
) [static]

Handle receipt of 802.11 fragment.

Parameters:
dev802.11 device
iobI/O buffer containing fragment
signalSignal strength with which fragment was received

Definition at line 2596 of file net80211.c.

References currticks(), io_buffer::data, DBGC, ieee80211_frame::fc, net80211_device::frags, free_iob(), hdr, IEEE80211_FC_MORE_FRAG, IEEE80211_FRAG, IEEE80211_SEQNR, net80211_frag_cache::in_use, net80211_frag_cache::iob, iob_len(), net80211_accum_frags(), NET80211_FRAG_TIMEOUT, net80211_free_frags(), NET80211_NR_CONCURRENT_FRAGS, net80211_rx(), NULL, ieee80211_frame::seq, net80211_frag_cache::seqnr, size, net80211_frag_cache::start_ticks, TICKS_PER_SEC, and timeout().

Referenced by net80211_rx().

{
        struct ieee80211_frame *hdr = iob->data;
        int fragnr = IEEE80211_FRAG ( hdr->seq );

        if ( fragnr == 0 && ( hdr->fc & IEEE80211_FC_MORE_FRAG ) ) {
                /* start a frag cache entry */
                int i, newest = -1;
                u32 curr_ticks = currticks(), newest_ticks = 0;
                u32 timeout = TICKS_PER_SEC * NET80211_FRAG_TIMEOUT;

                for ( i = 0; i < NET80211_NR_CONCURRENT_FRAGS; i++ ) {
                        if ( dev->frags[i].in_use == 0 )
                                break;

                        if ( dev->frags[i].start_ticks + timeout >=
                             curr_ticks ) {
                                net80211_free_frags ( dev, i );
                                break;
                        }

                        if ( dev->frags[i].start_ticks > newest_ticks ) {
                                newest = i;
                                newest_ticks = dev->frags[i].start_ticks;
                        }
                }

                /* If we're being sent more concurrent fragmented
                   packets than we can handle, drop the newest so the
                   older ones have time to complete. */
                if ( i == NET80211_NR_CONCURRENT_FRAGS ) {
                        i = newest;
                        net80211_free_frags ( dev, i );
                }

                dev->frags[i].in_use = 1;
                dev->frags[i].seqnr = IEEE80211_SEQNR ( hdr->seq );
                dev->frags[i].start_ticks = currticks();
                dev->frags[i].iob[0] = iob;
                return;
        } else {
                int i;
                for ( i = 0; i < NET80211_NR_CONCURRENT_FRAGS; i++ ) {
                        if ( dev->frags[i].in_use && dev->frags[i].seqnr ==
                             IEEE80211_SEQNR ( hdr->seq ) )
                                break;
                }
                if ( i == NET80211_NR_CONCURRENT_FRAGS ) {
                        /* Drop non-first not-in-cache fragments */
                        DBGC ( dev, "802.11 %p dropped fragment fc=%04x "
                               "seq=%04x\n", dev, hdr->fc, hdr->seq );
                        free_iob ( iob );
                        return;
                }

                dev->frags[i].iob[fragnr] = iob;

                if ( ! ( hdr->fc & IEEE80211_FC_MORE_FRAG ) ) {
                        int j, size = 0;
                        for ( j = 0; j < fragnr; j++ ) {
                                size += iob_len ( dev->frags[i].iob[j] );
                                if ( dev->frags[i].iob[j] == NULL )
                                        break;
                        }
                        if ( j == fragnr ) {
                                /* We've got everything */
                                struct io_buffer *niob =
                                    net80211_accum_frags ( dev, i, fragnr,
                                                           size );
                                net80211_free_frags ( dev, i );
                                net80211_rx ( dev, niob, signal, 0 );
                        } else {
                                DBGC ( dev, "802.11 %p dropping fragmented "
                                       "packet due to out-of-order arrival, "
                                       "fc=%04x seq=%04x\n", dev, hdr->fc,
                                       hdr->seq );
                                net80211_free_frags ( dev, i );
                        }
                }
        }
}