Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

lotest.c 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. FILE_LICENCE ( GPL2_OR_LATER );
  19. #include <stdint.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <stdio.h>
  23. #include <errno.h>
  24. #include <byteswap.h>
  25. #include <ipxe/iobuf.h>
  26. #include <ipxe/netdevice.h>
  27. #include <ipxe/if_ether.h>
  28. #include <ipxe/keys.h>
  29. #include <ipxe/console.h>
  30. #include <usr/ifmgmt.h>
  31. #include <usr/lotest.h>
  32. /** @file
  33. *
  34. * Loopback testing
  35. *
  36. */
  37. #define LINK_WAIT_MS 15000
  38. /**
  39. * Process received packet
  40. *
  41. * @v iobuf I/O buffer
  42. * @v netdev Network device
  43. * @v ll_dest Link-layer destination address
  44. * @v ll_source Link-layer source address
  45. * @ret rc Return status code
  46. */
  47. static int lotest_rx ( struct io_buffer *iobuf,
  48. struct net_device *netdev __unused,
  49. const void *ll_dest __unused,
  50. const void *ll_source __unused ) {
  51. free_iob ( iobuf );
  52. return -ENOTSUP;
  53. }
  54. /**
  55. * Transcribe network-layer address
  56. *
  57. * @v net_addr Network-layer address
  58. * @ret string Human-readable transcription of address
  59. */
  60. static const char * lotest_ntoa ( const void *net_addr __unused ) {
  61. return "<INVALID>";
  62. }
  63. /**
  64. * Loopback test network-layer protocol
  65. *
  66. * Using a dedicated network-layer protocol avoids problems caused by
  67. * cards supporting features such as IPv4 checksum offload trying to
  68. * interpret the (randomly generated) network-layer content.
  69. */
  70. static struct net_protocol lotest_protocol __net_protocol = {
  71. .name = "LOTEST",
  72. .rx = lotest_rx,
  73. .ntoa = lotest_ntoa,
  74. .net_proto = htons ( 0x6950 ), /* Not a genuine protocol number */
  75. .net_addr_len = 0,
  76. };
  77. /**
  78. * Perform loopback test between two network devices
  79. *
  80. * @v sender Sending network device
  81. * @v receiver Received network device
  82. * @v mtu Packet size (excluding link-layer headers)
  83. * @ret rc Return status code
  84. */
  85. int loopback_test ( struct net_device *sender, struct net_device *receiver,
  86. size_t mtu ) {
  87. uint8_t buf[mtu];
  88. struct io_buffer *iobuf;
  89. const void *ll_dest;
  90. const void *ll_source;
  91. uint16_t net_proto;
  92. unsigned int i;
  93. unsigned int successes;
  94. int rc;
  95. /* Open network devices */
  96. if ( ( rc = ifopen ( sender ) ) != 0 )
  97. return rc;
  98. if ( ( rc = ifopen ( receiver ) ) != 0 )
  99. return rc;
  100. /* Wait for link-up */
  101. if ( ( rc = iflinkwait ( sender, LINK_WAIT_MS ) ) != 0 )
  102. return rc;
  103. if ( ( rc = iflinkwait ( receiver, LINK_WAIT_MS ) ) != 0 )
  104. return rc;
  105. /* Print initial statistics */
  106. printf ( "Performing loopback test from %s to %s with %zd byte MTU\n",
  107. sender->name, receiver->name, mtu );
  108. ifstat ( sender );
  109. ifstat ( receiver );
  110. /* Freeze receive queue processing on the receiver, so that we
  111. * can extract all received packets.
  112. */
  113. netdev_rx_freeze ( receiver );
  114. /* Perform loopback test */
  115. for ( successes = 0 ; ; successes++ ) {
  116. /* Print running total */
  117. printf ( "\r%d", successes );
  118. /* Generate random packet */
  119. for ( i = 0 ; i < sizeof ( buf ) ; i++ )
  120. buf[i] = random();
  121. iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( buf ) );
  122. if ( ! iobuf ) {
  123. printf ( "\nFailed to allocate I/O buffer" );
  124. rc = -ENOMEM;
  125. goto done;
  126. }
  127. iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
  128. memcpy ( iob_put ( iobuf, sizeof ( buf ) ),
  129. buf, sizeof ( buf ) );
  130. /* Transmit packet */
  131. if ( ( rc = net_tx ( iob_disown ( iobuf ), sender,
  132. &lotest_protocol, receiver->ll_addr,
  133. sender->ll_addr ) ) != 0 ) {
  134. printf ( "\nFailed to transmit packet: %s",
  135. strerror ( rc ) );
  136. goto done;
  137. }
  138. /* Poll until packet arrives */
  139. do {
  140. /* Check for cancellation */
  141. if ( iskey() && ( getchar() == CTRL_C ) ) {
  142. rc = -ECANCELED;
  143. goto done;
  144. }
  145. /* Poll network devices */
  146. net_poll();
  147. } while ( ( iobuf = netdev_rx_dequeue ( receiver ) ) == NULL );
  148. /* Check received packet */
  149. if ( ( rc = receiver->ll_protocol->pull ( receiver, iobuf,
  150. &ll_dest, &ll_source,
  151. &net_proto ) ) != 0 ){
  152. printf ( "\nFailed to strip link-layer header: %s",
  153. strerror ( rc ) );
  154. goto done;
  155. }
  156. if ( net_proto == lotest_protocol.net_proto ) {
  157. if ( iob_len ( iobuf ) != sizeof ( buf ) ) {
  158. printf ( "\nLength mismatch: sent %zd, "
  159. "received %zd",
  160. sizeof ( buf ), iob_len ( iobuf ) );
  161. DBG ( "\nSent:\n" );
  162. DBG_HDA ( 0, buf, sizeof ( buf ) );
  163. DBG ( "Received:\n" );
  164. DBG_HDA ( 0, iobuf->data, iob_len ( iobuf ) );
  165. rc = -EINVAL;
  166. goto done;
  167. }
  168. if ( memcmp ( iobuf->data, buf, sizeof ( buf ) ) != 0){
  169. printf ( "\nContent mismatch" );
  170. DBG ( "\nSent:\n" );
  171. DBG_HDA ( 0, buf, sizeof ( buf ) );
  172. DBG ( "Received:\n" );
  173. DBG_HDA ( 0, iobuf->data, iob_len ( iobuf ) );
  174. rc = -EINVAL;
  175. goto done;
  176. }
  177. } else {
  178. printf ( "\nReceived spurious packet type %04x\n",
  179. ntohs ( net_proto ) );
  180. /* Continue; this allows for the fact that
  181. * there may have been packets outstanding on
  182. * the wire when we started the test.
  183. */
  184. }
  185. free_iob ( iob_disown ( iobuf ) );
  186. }
  187. done:
  188. printf ( "\n");
  189. free_iob ( iobuf );
  190. netdev_rx_unfreeze ( receiver );
  191. /* Dump final statistics */
  192. ifstat ( sender );
  193. ifstat ( receiver );
  194. return 0;
  195. }