]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[lotest] Allow loopback testing on shared networks
authorMichael Brown <mcb30@ipxe.org>
Thu, 13 Mar 2014 23:35:18 +0000 (23:35 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 13 Mar 2014 23:35:18 +0000 (23:35 +0000)
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>
src/usr/lotest.c

index 51d1a5d6e7c181b8af01625dfcc77d7d98ad5cdb..9e2ac331cdfddf5cd8b18a593936ffb257294354 100644 (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 );