]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[lotest] Accept non-loopback packets during test
authorMichael Brown <mcb30@ipxe.org>
Wed, 7 Dec 2011 00:41:48 +0000 (00:41 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 8 Dec 2011 00:30:28 +0000 (00:30 +0000)
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>
src/usr/lotest.c

index 6ed31ea5444cd9a097d786b2a4fd9f956110b044..525252610580e907c0386e6b3881652f4dd5326a 100644 (file)
@@ -84,6 +84,86 @@ static struct net_protocol lotest_protocol __net_protocol = {
        .net_addr_len = 0,
 };
 
+/**
+ * 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
  *
@@ -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 */