iPXE
Functions | Variables
lotest.c File Reference

Loopback testing. More...

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/iobuf.h>
#include <ipxe/netdevice.h>
#include <ipxe/if_ether.h>
#include <ipxe/keys.h>
#include <ipxe/console.h>
#include <usr/ifmgmt.h>
#include <usr/lotest.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
static LIST_HEAD (lotest_queue)
 Loopback testing received packets. More...
 
static int lotest_rx (struct io_buffer *iobuf, struct net_device *netdev, const void *ll_dest __unused, const void *ll_source __unused, unsigned int flags __unused)
 Process received packet. More...
 
static struct io_bufferlotest_dequeue (void)
 Dequeue received packet. More...
 
static const char * lotest_ntoa (const void *net_addr __unused)
 Transcribe network-layer address. More...
 
static void lotest_flush (void)
 Discard all received loopback test packets. More...
 
static int loopback_wait (void *data, size_t len)
 Wait for packet to be received. More...
 
int loopback_test (struct net_device *sender, struct net_device *receiver, size_t mtu, int broadcast)
 Perform loopback test between two network devices. More...
 

Variables

static struct net_devicelotest_receiver
 Current loopback test receiver. More...
 
static struct net_protocol lotest_protocol __net_protocol
 Loopback test network-layer protocol. More...
 

Detailed Description

Loopback testing.

Definition in file lotest.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ LIST_HEAD()

static LIST_HEAD ( lotest_queue  )
static

Loopback testing received packets.

◆ lotest_rx()

static int lotest_rx ( struct io_buffer iobuf,
struct net_device netdev,
const void *ll_dest  __unused,
const void *ll_source  __unused,
unsigned int flags  __unused 
)
static

Process received packet.

Parameters
iobufI/O buffer
netdevNetwork device
ll_destLink-layer destination address
ll_sourceLink-layer source address
flagsPacket flags
Return values
rcReturn status code

Definition at line 62 of file lotest.c.

66  {
67 
68  /* Add to received packet queue if currently performing a test */
69  if ( netdev == lotest_receiver ) {
70  list_add_tail ( &iobuf->list, &lotest_queue );
71  } else {
72  free_iob ( iobuf );
73  }
74 
75  return 0;
76 }
static struct net_device * lotest_receiver
Current loopback test receiver.
Definition: lotest.c:47
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
static struct net_device * netdev
Definition: gdbudp.c:52
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:39

References free_iob(), io_buffer::list, list_add_tail, lotest_receiver, and netdev.

◆ lotest_dequeue()

static struct io_buffer* lotest_dequeue ( void  )
static

Dequeue received packet.

Return values
iobufI/O buffer, or NULL

Definition at line 83 of file lotest.c.

83  {
84  struct io_buffer *iobuf;
85 
86  /* Remove first packet (if any) from received packet queue */
87  iobuf = list_first_entry ( &lotest_queue, struct io_buffer, list );
88  if ( ! iobuf )
89  return NULL;
90  list_del ( &iobuf->list );
91 
92  return iobuf;
93 }
#define list_first_entry(list, type, member)
Get the container of the first entry in a list.
Definition: list.h:333
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:39
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
A persistent I/O buffer.
Definition: iobuf.h:32

References io_buffer::list, list_del, list_first_entry, and NULL.

Referenced by loopback_wait(), and lotest_flush().

◆ lotest_ntoa()

static const char* lotest_ntoa ( const void *net_addr  __unused)
static

Transcribe network-layer address.

Parameters
net_addrNetwork-layer address
Return values
stringHuman-readable transcription of address

Definition at line 101 of file lotest.c.

101  {
102  return "<INVALID>";
103 }

◆ lotest_flush()

static void lotest_flush ( void  )
static

Discard all received loopback test packets.

Definition at line 124 of file lotest.c.

124  {
125  struct io_buffer *iobuf;
126 
127  while ( ( iobuf = lotest_dequeue() ) != NULL )
128  free_iob ( iobuf );
129 }
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
static struct io_buffer * lotest_dequeue(void)
Dequeue received packet.
Definition: lotest.c:83
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
A persistent I/O buffer.
Definition: iobuf.h:32

References free_iob(), lotest_dequeue(), and NULL.

Referenced by loopback_test().

◆ loopback_wait()

static int loopback_wait ( void *  data,
size_t  len 
)
static

Wait for packet to be received.

Parameters
dataExpected data
lenExpected data length
Return values
rcReturn status code

Definition at line 138 of file lotest.c.

138  {
139  struct io_buffer *iobuf;
140 
141  /* Poll until packet arrives */
142  while ( 1 ) {
143 
144  /* Check for cancellation */
145  if ( iskey() && ( getchar() == CTRL_C ) )
146  return -ECANCELED;
147 
148  /* Poll network devices */
149  net_poll();
150 
151  /* Dequeue packet, if available */
152  iobuf = lotest_dequeue();
153  if ( ! iobuf )
154  continue;
155 
156  /* Check packet length */
157  if ( iob_len ( iobuf ) != len ) {
158  printf ( "\nLength mismatch: sent %zd, received %zd",
159  len, iob_len ( iobuf ) );
160  DBG ( "\nSent:\n" );
161  DBG_HDA ( 0, data, len );
162  DBG ( "Received:\n" );
163  DBG_HDA ( 0, iobuf->data, iob_len ( iobuf ) );
164  free_iob ( iob_disown ( iobuf ) );
165  return -EINVAL;
166  }
167 
168  /* Check packet content */
169  if ( memcmp ( iobuf->data, data, len ) != 0 ) {
170  printf ( "\nContent mismatch" );
171  DBG ( "\nSent:\n" );
172  DBG_HDA ( 0, data, len );
173  DBG ( "Received:\n" );
174  DBG_HDA ( 0, iobuf->data, iob_len ( iobuf ) );
175  free_iob ( iob_disown ( iobuf ) );
176  return -EINVAL;
177  }
178 
179  /* Discard packet and return */
180  free_iob ( iob_disown ( iobuf ) );
181  return 0;
182  }
183 }
#define EINVAL
Invalid argument.
Definition: errno.h:428
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition: vsprintf.c:464
#define DBG_HDA(...)
Definition: compiler.h:499
void net_poll(void)
Poll the network stack.
Definition: netdevice.c:1052
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
#define ECANCELED
Operation canceled.
Definition: errno.h:343
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:208
#define CTRL_C
Definition: keys.h:20
static struct io_buffer * lotest_dequeue(void)
Dequeue received packet.
Definition: lotest.c:83
int getchar(void)
Read a single character from any console.
Definition: console.c:82
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
uint32_t len
Length.
Definition: ena.h:14
void * data
Start of data.
Definition: iobuf.h:44
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:98
int iskey(void)
Check for available input on any console.
Definition: console.c:127
A persistent I/O buffer.
Definition: iobuf.h:32

References CTRL_C, data, io_buffer::data, DBG, DBG_HDA, ECANCELED, EINVAL, free_iob(), getchar(), iob_disown, iob_len(), iskey(), len, lotest_dequeue(), memcmp(), net_poll(), and printf().

Referenced by loopback_test().

◆ loopback_test()

int loopback_test ( struct net_device sender,
struct net_device receiver,
size_t  mtu,
int  broadcast 
)

Perform loopback test between two network devices.

Parameters
senderSending network device
receiverReceived network device
mtuPacket size (excluding link-layer headers)
broadcastUse broadcast link-layer address
Return values
rcReturn status code

Definition at line 194 of file lotest.c.

195  {
196  uint8_t *buf;
197  uint32_t *seq;
198  struct io_buffer *iobuf;
199  const void *ll_dest;
200  unsigned int i;
201  unsigned int successes;
202  int rc;
203 
204  /* Open network devices */
205  if ( ( rc = ifopen ( sender ) ) != 0 )
206  return rc;
207  if ( ( rc = ifopen ( receiver ) ) != 0 )
208  return rc;
209 
210  /* Wait for link-up */
211  if ( ( rc = iflinkwait ( sender, 0 ) ) != 0 )
212  return rc;
213  if ( ( rc = iflinkwait ( receiver, 0 ) ) != 0 )
214  return rc;
215 
216  /* Allocate data buffer */
217  if ( mtu < sizeof ( *seq ) )
218  mtu = sizeof ( *seq );
219  buf = malloc ( mtu );
220  if ( ! buf )
221  return -ENOMEM;
222  seq = ( ( void * ) buf );
223 
224  /* Determine destination address */
225  ll_dest = ( broadcast ? sender->ll_broadcast : receiver->ll_addr );
226 
227  /* Print initial statistics */
228  printf ( "Performing %sloopback test from %s to %s with %zd byte MTU\n",
229  ( broadcast ? "broadcast " : "" ), sender->name,
230  receiver->name, mtu );
231  ifstat ( sender );
232  ifstat ( receiver );
233 
234  /* Start loopback test */
235  lotest_flush();
236  lotest_receiver = receiver;
237 
238  /* Perform loopback test */
239  for ( successes = 0 ; ; successes++ ) {
240 
241  /* Print running total */
242  printf ( "\r%d", successes );
243 
244  /* Generate random packet */
245  *seq = htonl ( successes );
246  for ( i = sizeof ( *seq ) ; i < mtu ; i++ )
247  buf[i] = random();
248  iobuf = alloc_iob ( MAX_LL_HEADER_LEN + mtu );
249  if ( ! iobuf ) {
250  printf ( "\nFailed to allocate I/O buffer" );
251  rc = -ENOMEM;
252  break;
253  }
254  iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
255  memcpy ( iob_put ( iobuf, mtu ), buf, mtu );
256 
257  /* Transmit packet */
258  if ( ( rc = net_tx ( iob_disown ( iobuf ), sender,
259  &lotest_protocol, ll_dest,
260  sender->ll_addr ) ) != 0 ) {
261  printf ( "\nFailed to transmit packet: %s",
262  strerror ( rc ) );
263  break;
264  }
265 
266  /* Wait for received packet */
267  if ( ( rc = loopback_wait ( buf, mtu ) ) != 0 )
268  break;
269  }
270 
271  printf ( "\n");
272 
273  /* Stop loopback testing */
275  lotest_flush();
276 
277  /* Dump final statistics */
278  ifstat ( sender );
279  ifstat ( receiver );
280 
281  /* Free buffer */
282  free ( buf );
283 
284  return 0;
285 }
static struct net_device * lotest_receiver
Current loopback test receiver.
Definition: lotest.c:47
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define iob_put(iobuf, len)
Definition: iobuf.h:116
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition: vsprintf.c:464
static void lotest_flush(void)
Discard all received loopback test packets.
Definition: lotest.c:124
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:128
#define htonl(value)
Definition: byteswap.h:133
u16 seq
802.11 Sequence Control field
Definition: ieee80211.h:19
#define ENOMEM
Not enough space.
Definition: errno.h:534
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:208
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static int loopback_wait(void *data, size_t len)
Wait for packet to be received.
Definition: lotest.c:138
#define MAX_LL_HEADER_LEN
Maximum length of a link-layer header.
Definition: netdevice.h:45
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition: random.c:30
unsigned char uint8_t
Definition: stdint.h:10
unsigned int uint32_t
Definition: stdint.h:12
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:583
struct stp_switch sender
Sender switch.
Definition: stp.h:30
int ifopen(struct net_device *netdev)
Open network device.
Definition: ifmgmt.c:65
#define iob_reserve(iobuf, len)
Definition: iobuf.h:63
char name[NETDEV_NAME_LEN]
Name of this network device.
Definition: netdevice.h:358
int net_tx(struct io_buffer *iobuf, struct net_device *netdev, struct net_protocol *net_protocol, const void *ll_dest, const void *ll_source)
Transmit network-layer packet.
Definition: netdevice.c:999
int iflinkwait(struct net_device *netdev, unsigned long timeout)
Wait for link-up, with status indication.
Definition: ifmgmt.c:216
uint32_t mtu
Maximum MTU.
Definition: ena.h:28
void ifstat(struct net_device *netdev)
Print status of network device.
Definition: ifmgmt.c:110
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition: netdevice.h:381
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
A persistent I/O buffer.
Definition: iobuf.h:32

References alloc_iob(), ENOMEM, free, htonl, iflinkwait(), ifopen(), ifstat(), iob_disown, iob_put, iob_reserve, net_device::ll_addr, loopback_wait(), lotest_flush(), lotest_receiver, malloc(), MAX_LL_HEADER_LEN, memcpy(), mtu, net_device::name, net_tx(), NULL, printf(), random(), rc, sender, seq, and strerror().

Referenced by lotest_exec().

Variable Documentation

◆ lotest_receiver

struct net_device* lotest_receiver
static

Current loopback test receiver.

Definition at line 47 of file lotest.c.

Referenced by loopback_test(), and lotest_rx().

◆ __net_protocol

struct net_protocol lotest_protocol __net_protocol
static
Initial value:
= {
.name = "LOTEST",
.rx = lotest_rx,
.ntoa = lotest_ntoa,
.net_proto = htons ( 0x6950 ),
.net_addr_len = 0,
}
static int lotest_rx(struct io_buffer *iobuf, struct net_device *netdev, const void *ll_dest __unused, const void *ll_source __unused, unsigned int flags __unused)
Process received packet.
Definition: lotest.c:62
static const char * lotest_ntoa(const void *net_addr __unused)
Transcribe network-layer address.
Definition: lotest.c:101
#define htons(value)
Definition: byteswap.h:135

Loopback test network-layer protocol.

Using a dedicated network-layer protocol avoids problems caused by cards supporting features such as IPv4 checksum offload trying to interpret the (randomly generated) network-layer content.

Definition at line 112 of file lotest.c.