diff options
author | Michael Brown <mcb30@ipxe.org> | 2011-12-07 00:41:48 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2011-12-08 00:30:28 +0000 |
commit | 29651e0c020dcf475690fdf24083392f88fcdfb5 (patch) | |
tree | e72d1c1179ac14022d496316757fc5a216ab89ec /src/usr | |
parent | f2893911345c82a69d53e06dd5bad612200a3517 (diff) | |
download | ipxe-29651e0c020dcf475690fdf24083392f88fcdfb5.tar.gz |
[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')
-rw-r--r-- | src/usr/lotest.c | 144 |
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 */ |