david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[lotest] Allow loopback testing on shared networks

Allow for extraneous packets to be received during loopback testing,
and so permit loopback tests to be performed when ports are connected
to a switch (rather than requiring ports to be directly connected with
a loopback cable).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2014-03-13 23:35:18 +00:00
parent a17ee3610d
commit 24bbaf6a38
1 changed files with 53 additions and 36 deletions

View File

@ -39,6 +39,12 @@ FILE_LICENCE ( GPL2_OR_LATER );
*
*/
/** Loopback testing in progress flag */
static int lotest_active;
/** Loopback testing received packets */
static LIST_HEAD ( lotest_queue );
/**
* Process received packet
*
@ -54,8 +60,32 @@ static int lotest_rx ( struct io_buffer *iobuf,
const void *ll_dest __unused,
const void *ll_source __unused,
unsigned int flags __unused ) {
free_iob ( iobuf );
return -ENOTSUP;
/* Add to received packet queue if currently performing a test */
if ( lotest_active ) {
list_add_tail ( &iobuf->list, &lotest_queue );
} else {
free_iob ( iobuf );
}
return 0;
}
/**
* Dequeue received packet
*
* @ret iobuf I/O buffer, or NULL
*/
static struct io_buffer * lotest_dequeue ( void ) {
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;
}
/**
@ -83,23 +113,26 @@ static struct net_protocol lotest_protocol __net_protocol = {
.net_addr_len = 0,
};
/**
* Discard all received loopback test packets
*
*/
static void lotest_flush ( void ) {
struct io_buffer *iobuf;
while ( ( iobuf = lotest_dequeue() ) != NULL )
free_iob ( iobuf );
}
/**
* Wait for packet to be received
*
* @v receiver Receiving network device*
* @v data Expected data
* @v len Expected data length
* @ret rc Return status code
*/
static int loopback_wait ( struct net_device *receiver, void *data,
size_t len ) {
struct ll_protocol *ll_protocol = receiver->ll_protocol;
static int loopback_wait ( void *data, size_t len ) {
struct io_buffer *iobuf;
const void *ll_dest;
const void *ll_source;
uint16_t net_proto;
unsigned int flags;
int rc;
/* Poll until packet arrives */
while ( 1 ) {
@ -112,28 +145,10 @@ static int loopback_wait ( struct net_device *receiver, void *data,
net_poll();
/* Dequeue packet, if available */
iobuf = netdev_rx_dequeue ( receiver );
iobuf = lotest_dequeue();
if ( ! iobuf )
continue;
/* Strip link-layer header */
if ( ( rc = ll_protocol->pull ( receiver, iobuf, &ll_dest,
&ll_source, &net_proto,
&flags ) ) != 0 ) {
printf ( "\nFailed to strip link-layer header: %s",
strerror ( rc ) );
free_iob ( iob_disown ( iobuf ) );
return rc;
}
/* Ignore non-loopback packets */
if ( net_proto != lotest_protocol.net_proto ) {
printf ( "\nReceived spurious packet type %04x\n",
ntohs ( net_proto ) );
free_iob ( iob_disown ( iobuf ) );
continue;
}
/* Check packet length */
if ( iob_len ( iobuf ) != len ) {
printf ( "\nLength mismatch: sent %zd, received %zd",
@ -206,10 +221,9 @@ int loopback_test ( struct net_device *sender, struct net_device *receiver,
ifstat ( sender );
ifstat ( receiver );
/* Freeze receive queue processing on the receiver, so that we
* can extract all received packets.
*/
netdev_rx_freeze ( receiver );
/* Start loopback test */
lotest_flush();
lotest_active = 1;
/* Perform loopback test */
for ( successes = 0 ; ; successes++ ) {
@ -240,12 +254,15 @@ int loopback_test ( struct net_device *sender, struct net_device *receiver,
}
/* Wait for received packet */
if ( ( rc = loopback_wait ( receiver, buf, mtu ) ) != 0 )
if ( ( rc = loopback_wait ( buf, mtu ) ) != 0 )
break;
}
printf ( "\n");
netdev_rx_unfreeze ( receiver );
/* Stop loopback testing */
lotest_active = 0;
lotest_flush();
/* Dump final statistics */
ifstat ( sender );