mirror of
https://github.com/ipxe/ipxe
synced 2026-02-14 02:31:26 +03:00
[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:
@@ -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
|
* Process received packet
|
||||||
*
|
*
|
||||||
@@ -54,8 +60,32 @@ static int lotest_rx ( struct io_buffer *iobuf,
|
|||||||
const void *ll_dest __unused,
|
const void *ll_dest __unused,
|
||||||
const void *ll_source __unused,
|
const void *ll_source __unused,
|
||||||
unsigned int flags __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,
|
.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
|
* Wait for packet to be received
|
||||||
*
|
*
|
||||||
* @v receiver Receiving network device*
|
|
||||||
* @v data Expected data
|
* @v data Expected data
|
||||||
* @v len Expected data length
|
* @v len Expected data length
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int loopback_wait ( struct net_device *receiver, void *data,
|
static int loopback_wait ( void *data, size_t len ) {
|
||||||
size_t len ) {
|
|
||||||
struct ll_protocol *ll_protocol = receiver->ll_protocol;
|
|
||||||
struct io_buffer *iobuf;
|
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 */
|
/* Poll until packet arrives */
|
||||||
while ( 1 ) {
|
while ( 1 ) {
|
||||||
@@ -112,28 +145,10 @@ static int loopback_wait ( struct net_device *receiver, void *data,
|
|||||||
net_poll();
|
net_poll();
|
||||||
|
|
||||||
/* Dequeue packet, if available */
|
/* Dequeue packet, if available */
|
||||||
iobuf = netdev_rx_dequeue ( receiver );
|
iobuf = lotest_dequeue();
|
||||||
if ( ! iobuf )
|
if ( ! iobuf )
|
||||||
continue;
|
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 */
|
/* Check packet length */
|
||||||
if ( iob_len ( iobuf ) != len ) {
|
if ( iob_len ( iobuf ) != len ) {
|
||||||
printf ( "\nLength mismatch: sent %zd, received %zd",
|
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 ( sender );
|
||||||
ifstat ( receiver );
|
ifstat ( receiver );
|
||||||
|
|
||||||
/* Freeze receive queue processing on the receiver, so that we
|
/* Start loopback test */
|
||||||
* can extract all received packets.
|
lotest_flush();
|
||||||
*/
|
lotest_active = 1;
|
||||||
netdev_rx_freeze ( receiver );
|
|
||||||
|
|
||||||
/* Perform loopback test */
|
/* Perform loopback test */
|
||||||
for ( successes = 0 ; ; successes++ ) {
|
for ( successes = 0 ; ; successes++ ) {
|
||||||
@@ -240,12 +254,15 @@ int loopback_test ( struct net_device *sender, struct net_device *receiver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for received packet */
|
/* Wait for received packet */
|
||||||
if ( ( rc = loopback_wait ( receiver, buf, mtu ) ) != 0 )
|
if ( ( rc = loopback_wait ( buf, mtu ) ) != 0 )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf ( "\n");
|
printf ( "\n");
|
||||||
netdev_rx_unfreeze ( receiver );
|
|
||||||
|
/* Stop loopback testing */
|
||||||
|
lotest_active = 0;
|
||||||
|
lotest_flush();
|
||||||
|
|
||||||
/* Dump final statistics */
|
/* Dump final statistics */
|
||||||
ifstat ( sender );
|
ifstat ( sender );
|
||||||
|
|||||||
Reference in New Issue
Block a user