|
|
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.