|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2010 Michael Brown <[email protected]>. ! 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: ! 19: FILE_LICENCE ( GPL2_OR_LATER ); ! 20: ! 21: #include <stdint.h> ! 22: #include <stdlib.h> ! 23: #include <string.h> ! 24: #include <stdio.h> ! 25: #include <errno.h> ! 26: #include <byteswap.h> ! 27: #include <ipxe/iobuf.h> ! 28: #include <ipxe/netdevice.h> ! 29: #include <ipxe/if_ether.h> ! 30: #include <ipxe/keys.h> ! 31: #include <ipxe/console.h> ! 32: #include <usr/ifmgmt.h> ! 33: #include <usr/lotest.h> ! 34: ! 35: /** @file ! 36: * ! 37: * Loopback testing ! 38: * ! 39: */ ! 40: ! 41: #define LINK_WAIT_MS 15000 ! 42: ! 43: /** ! 44: * Process received packet ! 45: * ! 46: * @v iobuf I/O buffer ! 47: * @v netdev Network device ! 48: * @v ll_dest Link-layer destination address ! 49: * @v ll_source Link-layer source address ! 50: * @ret rc Return status code ! 51: */ ! 52: static int lotest_rx ( struct io_buffer *iobuf, ! 53: struct net_device *netdev __unused, ! 54: const void *ll_dest __unused, ! 55: const void *ll_source __unused ) { ! 56: free_iob ( iobuf ); ! 57: return -ENOTSUP; ! 58: } ! 59: ! 60: /** ! 61: * Transcribe network-layer address ! 62: * ! 63: * @v net_addr Network-layer address ! 64: * @ret string Human-readable transcription of address ! 65: */ ! 66: static const char * lotest_ntoa ( const void *net_addr __unused ) { ! 67: return "<INVALID>"; ! 68: } ! 69: ! 70: /** ! 71: * Loopback test network-layer protocol ! 72: * ! 73: * Using a dedicated network-layer protocol avoids problems caused by ! 74: * cards supporting features such as IPv4 checksum offload trying to ! 75: * interpret the (randomly generated) network-layer content. ! 76: */ ! 77: static struct net_protocol lotest_protocol __net_protocol = { ! 78: .name = "LOTEST", ! 79: .rx = lotest_rx, ! 80: .ntoa = lotest_ntoa, ! 81: .net_proto = htons ( 0x6950 ), /* Not a genuine protocol number */ ! 82: .net_addr_len = 0, ! 83: }; ! 84: ! 85: /** ! 86: * Perform loopback test between two network devices ! 87: * ! 88: * @v sender Sending network device ! 89: * @v receiver Received network device ! 90: * @v mtu Packet size (excluding link-layer headers) ! 91: * @ret rc Return status code ! 92: */ ! 93: int loopback_test ( struct net_device *sender, struct net_device *receiver, ! 94: size_t mtu ) { ! 95: uint8_t buf[mtu]; ! 96: struct io_buffer *iobuf; ! 97: const void *ll_dest; ! 98: const void *ll_source; ! 99: uint16_t net_proto; ! 100: unsigned int i; ! 101: unsigned int successes; ! 102: int rc; ! 103: ! 104: /* Open network devices */ ! 105: if ( ( rc = ifopen ( sender ) ) != 0 ) ! 106: return rc; ! 107: if ( ( rc = ifopen ( receiver ) ) != 0 ) ! 108: return rc; ! 109: ! 110: /* Wait for link-up */ ! 111: if ( ( rc = iflinkwait ( sender, LINK_WAIT_MS ) ) != 0 ) ! 112: return rc; ! 113: if ( ( rc = iflinkwait ( receiver, LINK_WAIT_MS ) ) != 0 ) ! 114: return rc; ! 115: ! 116: /* Print initial statistics */ ! 117: printf ( "Performing loopback test from %s to %s with %zd byte MTU\n", ! 118: sender->name, receiver->name, mtu ); ! 119: ifstat ( sender ); ! 120: ifstat ( receiver ); ! 121: ! 122: /* Freeze receive queue processing on the receiver, so that we ! 123: * can extract all received packets. ! 124: */ ! 125: netdev_rx_freeze ( receiver ); ! 126: ! 127: /* Perform loopback test */ ! 128: for ( successes = 0 ; ; successes++ ) { ! 129: ! 130: /* Print running total */ ! 131: printf ( "\r%d", successes ); ! 132: ! 133: /* Generate random packet */ ! 134: for ( i = 0 ; i < sizeof ( buf ) ; i++ ) ! 135: buf[i] = random(); ! 136: iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( buf ) ); ! 137: if ( ! iobuf ) { ! 138: printf ( "\nFailed to allocate I/O buffer" ); ! 139: rc = -ENOMEM; ! 140: goto done; ! 141: } ! 142: iob_reserve ( iobuf, MAX_LL_HEADER_LEN ); ! 143: memcpy ( iob_put ( iobuf, sizeof ( buf ) ), ! 144: buf, sizeof ( buf ) ); ! 145: ! 146: /* Transmit packet */ ! 147: if ( ( rc = net_tx ( iob_disown ( iobuf ), sender, ! 148: &lotest_protocol, receiver->ll_addr, ! 149: sender->ll_addr ) ) != 0 ) { ! 150: printf ( "\nFailed to transmit packet: %s", ! 151: strerror ( rc ) ); ! 152: goto done; ! 153: } ! 154: ! 155: /* Poll until packet arrives */ ! 156: do { ! 157: /* Check for cancellation */ ! 158: if ( iskey() && ( getchar() == CTRL_C ) ) { ! 159: rc = -ECANCELED; ! 160: goto done; ! 161: } ! 162: /* Poll network devices */ ! 163: net_poll(); ! 164: } while ( ( iobuf = netdev_rx_dequeue ( receiver ) ) == NULL ); ! 165: ! 166: /* Check received packet */ ! 167: if ( ( rc = receiver->ll_protocol->pull ( receiver, iobuf, ! 168: &ll_dest, &ll_source, ! 169: &net_proto ) ) != 0 ){ ! 170: printf ( "\nFailed to strip link-layer header: %s", ! 171: strerror ( rc ) ); ! 172: goto done; ! 173: } ! 174: if ( net_proto == lotest_protocol.net_proto ) { ! 175: if ( iob_len ( iobuf ) != sizeof ( buf ) ) { ! 176: printf ( "\nLength mismatch: sent %zd, " ! 177: "received %zd", ! 178: sizeof ( buf ), iob_len ( iobuf ) ); ! 179: DBG ( "\nSent:\n" ); ! 180: DBG_HDA ( 0, buf, sizeof ( buf ) ); ! 181: DBG ( "Received:\n" ); ! 182: DBG_HDA ( 0, iobuf->data, iob_len ( iobuf ) ); ! 183: rc = -EINVAL; ! 184: goto done; ! 185: } ! 186: if ( memcmp ( iobuf->data, buf, sizeof ( buf ) ) != 0){ ! 187: printf ( "\nContent mismatch" ); ! 188: DBG ( "\nSent:\n" ); ! 189: DBG_HDA ( 0, buf, sizeof ( buf ) ); ! 190: DBG ( "Received:\n" ); ! 191: DBG_HDA ( 0, iobuf->data, iob_len ( iobuf ) ); ! 192: rc = -EINVAL; ! 193: goto done; ! 194: } ! 195: } else { ! 196: printf ( "\nReceived spurious packet type %04x\n", ! 197: ntohs ( net_proto ) ); ! 198: /* Continue; this allows for the fact that ! 199: * there may have been packets outstanding on ! 200: * the wire when we started the test. ! 201: */ ! 202: } ! 203: ! 204: free_iob ( iob_disown ( iobuf ) ); ! 205: } ! 206: ! 207: done: ! 208: printf ( "\n"); ! 209: free_iob ( iobuf ); ! 210: netdev_rx_unfreeze ( receiver ); ! 211: ! 212: /* Dump final statistics */ ! 213: ifstat ( sender ); ! 214: ifstat ( receiver ); ! 215: ! 216: return 0; ! 217: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.