summaryrefslogtreecommitdiffstats
path: root/src/usr/lotest.c
diff options
context:
space:
mode:
authorMichael Brown2011-12-07 01:41:48 +0100
committerMichael Brown2011-12-08 01:30:28 +0100
commit29651e0c020dcf475690fdf24083392f88fcdfb5 (patch)
treee72d1c1179ac14022d496316757fc5a216ab89ec /src/usr/lotest.c
parent[e1000e] Strip the Ethernet CRC from received packets (diff)
downloadipxe-29651e0c020dcf475690fdf24083392f88fcdfb5.tar.gz
ipxe-29651e0c020dcf475690fdf24083392f88fcdfb5.tar.xz
ipxe-29651e0c020dcf475690fdf24083392f88fcdfb5.zip
[lotest] Accept non-loopback packets during test
It can sometimes be awkward to prevent additional packets from being received during a loopback test. Allow such additional packets to be present without terminating the test. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/usr/lotest.c')
-rw-r--r--src/usr/lotest.c144
1 files changed, 86 insertions, 58 deletions
diff --git a/src/usr/lotest.c b/src/usr/lotest.c
index 6ed31ea5..52525261 100644
--- a/src/usr/lotest.c
+++ b/src/usr/lotest.c
@@ -85,6 +85,86 @@ static struct net_protocol lotest_protocol __net_protocol = {
};
/**
+ * 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;
+ 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 ) {
+
+ /* Check for cancellation */
+ if ( iskey() && ( getchar() == CTRL_C ) )
+ return -ECANCELED;
+
+ /* Poll network devices */
+ net_poll();
+
+ /* Dequeue packet, if available */
+ iobuf = netdev_rx_dequeue ( receiver );
+ 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",
+ 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;
+ }
+}
+
+/**
* Perform loopback test between two network devices
*
* @v sender Sending network device
@@ -96,10 +176,6 @@ int loopback_test ( struct net_device *sender, struct net_device *receiver,
size_t mtu ) {
uint8_t buf[mtu];
struct io_buffer *iobuf;
- const void *ll_dest;
- const void *ll_source;
- uint16_t net_proto;
- unsigned int flags;
unsigned int i;
unsigned int successes;
int rc;
@@ -140,7 +216,7 @@ int loopback_test ( struct net_device *sender, struct net_device *receiver,
if ( ! iobuf ) {
printf ( "\nFailed to allocate I/O buffer" );
rc = -ENOMEM;
- goto done;
+ break;
}
iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
memcpy ( iob_put ( iobuf, sizeof ( buf ) ),
@@ -152,65 +228,17 @@ int loopback_test ( struct net_device *sender, struct net_device *receiver,
sender->ll_addr ) ) != 0 ) {
printf ( "\nFailed to transmit packet: %s",
strerror ( rc ) );
- goto done;
+ break;
}
- /* Poll until packet arrives */
- do {
- /* Check for cancellation */
- if ( iskey() && ( getchar() == CTRL_C ) ) {
- rc = -ECANCELED;
- goto done;
- }
- /* Poll network devices */
- net_poll();
- } while ( ( iobuf = netdev_rx_dequeue ( receiver ) ) == NULL );
-
- /* Check received packet */
- if ( ( rc = receiver->ll_protocol->pull ( receiver, iobuf,
- &ll_dest, &ll_source,
- &net_proto,
- &flags ) ) != 0 ) {
- printf ( "\nFailed to strip link-layer header: %s",
- strerror ( rc ) );
- goto done;
- }
- if ( net_proto == lotest_protocol.net_proto ) {
- if ( iob_len ( iobuf ) != sizeof ( buf ) ) {
- printf ( "\nLength mismatch: sent %zd, "
- "received %zd",
- sizeof ( buf ), iob_len ( iobuf ) );
- DBG ( "\nSent:\n" );
- DBG_HDA ( 0, buf, sizeof ( buf ) );
- DBG ( "Received:\n" );
- DBG_HDA ( 0, iobuf->data, iob_len ( iobuf ) );
- rc = -EINVAL;
- goto done;
- }
- if ( memcmp ( iobuf->data, buf, sizeof ( buf ) ) != 0){
- printf ( "\nContent mismatch" );
- DBG ( "\nSent:\n" );
- DBG_HDA ( 0, buf, sizeof ( buf ) );
- DBG ( "Received:\n" );
- DBG_HDA ( 0, iobuf->data, iob_len ( iobuf ) );
- rc = -EINVAL;
- goto done;
- }
- } else {
- printf ( "\nReceived spurious packet type %04x\n",
- ntohs ( net_proto ) );
- /* Continue; this allows for the fact that
- * there may have been packets outstanding on
- * the wire when we started the test.
- */
+ /* Wait for received packet */
+ if ( ( rc = loopback_wait ( receiver, buf,
+ sizeof ( buf ) ) ) != 0 ) {
+ break;
}
-
- free_iob ( iob_disown ( iobuf ) );
}
- done:
printf ( "\n");
- free_iob ( iobuf );
netdev_rx_unfreeze ( receiver );
/* Dump final statistics */