iPXE
Functions | Variables
lotest.c File Reference

Loopback testing. More...

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/iobuf.h>
#include <ipxe/netdevice.h>
#include <ipxe/if_ether.h>
#include <ipxe/keys.h>
#include <ipxe/console.h>
#include <usr/ifmgmt.h>
#include <usr/lotest.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static LIST_HEAD (lotest_queue)
 Loopback testing received packets.
static int lotest_rx (struct io_buffer *iobuf, struct net_device *netdev, const void *ll_dest __unused, const void *ll_source __unused, unsigned int flags __unused)
 Process received packet.
static struct io_bufferlotest_dequeue (void)
 Dequeue received packet.
static const char * lotest_ntoa (const void *net_addr __unused)
 Transcribe network-layer address.
static void lotest_flush (void)
 Discard all received loopback test packets.
static int loopback_wait (void *data, size_t len)
 Wait for packet to be received.
int loopback_test (struct net_device *sender, struct net_device *receiver, size_t mtu, int broadcast)
 Perform loopback test between two network devices.

Variables

static struct net_devicelotest_receiver
 Current loopback test receiver.
static struct net_protocol
lotest_protocol 
__net_protocol
 Loopback test network-layer protocol.

Detailed Description

Loopback testing.

Definition in file lotest.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static LIST_HEAD ( lotest_queue  ) [static]

Loopback testing received packets.

static int lotest_rx ( struct io_buffer iobuf,
struct net_device netdev,
const void *ll_dest  __unused,
const void *ll_source  __unused,
unsigned int flags  __unused 
) [static]

Process received packet.

Parameters:
iobufI/O buffer
netdevNetwork device
ll_destLink-layer destination address
ll_sourceLink-layer source address
flagsPacket flags
Return values:
rcReturn status code

Definition at line 62 of file lotest.c.

References free_iob(), io_buffer::list, and list_add_tail.

                                                     {

        /* Add to received packet queue if currently performing a test */
        if ( netdev == lotest_receiver ) {
                list_add_tail ( &iobuf->list, &lotest_queue );
        } else {
                free_iob ( iobuf );
        }

        return 0;
}
static struct io_buffer* lotest_dequeue ( void  ) [static, read]

Dequeue received packet.

Return values:
iobufI/O buffer, or NULL

Definition at line 83 of file lotest.c.

References io_buffer::list, list_del, list_first_entry, and NULL.

Referenced by loopback_wait(), and lotest_flush().

                                                  {
        struct io_buffer *iobuf;

        /* Remove first packet (if any) from received packet queue */
        iobuf = list_first_entry ( &lotest_queue, struct io_buffer, list );
        if ( ! iobuf )
                return NULL;
        list_del ( &iobuf->list );

        return iobuf;
}
static const char* lotest_ntoa ( const void *net_addr  __unused) [static]

Transcribe network-layer address.

Parameters:
net_addrNetwork-layer address
Return values:
stringHuman-readable transcription of address

Definition at line 101 of file lotest.c.

                                                                  {
        return "<INVALID>";
}
static void lotest_flush ( void  ) [static]

Discard all received loopback test packets.

Definition at line 124 of file lotest.c.

References free_iob(), lotest_dequeue(), and NULL.

Referenced by loopback_test().

                                  {
        struct io_buffer *iobuf;

        while ( ( iobuf = lotest_dequeue() ) != NULL )
                free_iob ( iobuf );
}
static int loopback_wait ( void *  data,
size_t  len 
) [static]

Wait for packet to be received.

Parameters:
dataExpected data
lenExpected data length
Return values:
rcReturn status code

Definition at line 138 of file lotest.c.

References CTRL_C, io_buffer::data, DBG, DBG_HDA, ECANCELED, EINVAL, free_iob(), getchar(), iob_disown, iob_len(), iskey(), lotest_dequeue(), memcmp(), net_poll(), and printf().

Referenced by loopback_test().

                                                    {
        struct io_buffer *iobuf;

        /* Poll until packet arrives */
        while ( 1 ) {

                /* Check for cancellation */
                if ( iskey() && ( getchar() == CTRL_C ) )
                        return -ECANCELED;

                /* Poll network devices */
                net_poll();

                /* Dequeue packet, if available */
                iobuf = lotest_dequeue();
                if ( ! iobuf )
                        continue;

                /* Check packet length */
                if ( iob_len ( iobuf ) != len ) {
                        printf ( "\nLength mismatch: sent %zd, received %zd",
                                 len, iob_len ( iobuf ) );
                        DBG ( "\nSent:\n" );
                        DBG_HDA ( 0, data, len );
                        DBG ( "Received:\n" );
                        DBG_HDA ( 0, iobuf->data, iob_len ( iobuf ) );
                        free_iob ( iob_disown ( iobuf ) );
                        return -EINVAL;
                }

                /* Check packet content */
                if ( memcmp ( iobuf->data, data, len ) != 0 ) {
                        printf ( "\nContent mismatch" );
                        DBG ( "\nSent:\n" );
                        DBG_HDA ( 0, data, len );
                        DBG ( "Received:\n" );
                        DBG_HDA ( 0, iobuf->data, iob_len ( iobuf ) );
                        free_iob ( iob_disown ( iobuf ) );
                        return -EINVAL;
                }

                /* Discard packet and return */
                free_iob ( iob_disown ( iobuf ) );
                return 0;
        }
}
int loopback_test ( struct net_device sender,
struct net_device receiver,
size_t  mtu,
int  broadcast 
)

Perform loopback test between two network devices.

Parameters:
senderSending network device
receiverReceived network device
mtuPacket size (excluding link-layer headers)
broadcastUse broadcast link-layer address
Return values:
rcReturn status code

Definition at line 194 of file lotest.c.

References alloc_iob(), ENOMEM, free, htonl, iflinkwait(), ifopen(), ifstat(), iob_disown, iob_put, iob_reserve, net_device::ll_addr, net_device::ll_broadcast, loopback_wait(), lotest_flush(), malloc(), MAX_LL_HEADER_LEN, memcpy(), mtu, net_device::name, net_tx(), NULL, printf(), random(), rc, seq, and strerror().

Referenced by lotest_exec().

                                                {
        uint8_t *buf;
        uint32_t *seq;
        struct io_buffer *iobuf;
        const void *ll_dest;
        unsigned int i;
        unsigned int successes;
        int rc;

        /* Open network devices */
        if ( ( rc = ifopen ( sender ) ) != 0 )
                return rc;
        if ( ( rc = ifopen ( receiver ) ) != 0 )
                return rc;

        /* Wait for link-up */
        if ( ( rc = iflinkwait ( sender, 0 ) ) != 0 )
                return rc;
        if ( ( rc = iflinkwait ( receiver, 0 ) ) != 0 )
                return rc;

        /* Allocate data buffer */
        if ( mtu < sizeof ( *seq ) )
                mtu = sizeof ( *seq );
        buf = malloc ( mtu );
        if ( ! buf )
                return -ENOMEM;
        seq = ( ( void * ) buf );

        /* Determine destination address */
        ll_dest = ( broadcast ? sender->ll_broadcast : receiver->ll_addr );

        /* Print initial statistics */
        printf ( "Performing %sloopback test from %s to %s with %zd byte MTU\n",
                 ( broadcast ? "broadcast " : "" ), sender->name,
                 receiver->name, mtu );
        ifstat ( sender );
        ifstat ( receiver );

        /* Start loopback test */
        lotest_flush();
        lotest_receiver = receiver;

        /* Perform loopback test */
        for ( successes = 0 ; ; successes++ ) {

                /* Print running total */
                printf ( "\r%d", successes );

                /* Generate random packet */
                *seq = htonl ( successes );
                for ( i = sizeof ( *seq ) ; i < mtu ; i++ )
                        buf[i] = random();
                iobuf = alloc_iob ( MAX_LL_HEADER_LEN + mtu );
                if ( ! iobuf ) {
                        printf ( "\nFailed to allocate I/O buffer" );
                        rc = -ENOMEM;
                        break;
                }
                iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
                memcpy ( iob_put ( iobuf, mtu ), buf, mtu );

                /* Transmit packet */
                if ( ( rc = net_tx ( iob_disown ( iobuf ), sender,
                                     &lotest_protocol, ll_dest,
                                     sender->ll_addr ) ) != 0 ) {
                        printf ( "\nFailed to transmit packet: %s",
                                 strerror ( rc ) );
                        break;
                }

                /* Wait for received packet */
                if ( ( rc = loopback_wait ( buf, mtu ) ) != 0 )
                        break;
        }

        printf ( "\n");

        /* Stop loopback testing */
        lotest_receiver = NULL;
        lotest_flush();

        /* Dump final statistics */
        ifstat ( sender );
        ifstat ( receiver );

        /* Free buffer */
        free ( buf );

        return 0;
}

Variable Documentation

struct net_device* lotest_receiver [static]

Current loopback test receiver.

Definition at line 47 of file lotest.c.

struct net_protocol lotest_protocol __net_protocol [static]
Initial value:
 {
        .name = "LOTEST",
        .rx = lotest_rx,
        .ntoa = lotest_ntoa,
        .net_proto = htons ( 0x6950 ), 
        .net_addr_len = 0,
}

Loopback test network-layer protocol.

Using a dedicated network-layer protocol avoids problems caused by cards supporting features such as IPv4 checksum offload trying to interpret the (randomly generated) network-layer content.

Definition at line 112 of file lotest.c.