iPXE
neighbour.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <stdint.h>
28#include <stdlib.h>
29#include <string.h>
30#include <errno.h>
31#include <ipxe/iobuf.h>
32#include <ipxe/retry.h>
33#include <ipxe/timer.h>
34#include <ipxe/malloc.h>
35#include <ipxe/pending.h>
36#include <ipxe/neighbour.h>
37#include <config/fault.h>
38
39/** @file
40 *
41 * Neighbour discovery
42 *
43 * This file implements the abstract functions of neighbour discovery,
44 * independent of the underlying network protocol (e.g. ARP or NDP).
45 *
46 */
47
48/** Neighbour discovery minimum timeout */
49#define NEIGHBOUR_MIN_TIMEOUT ( TICKS_PER_SEC / 8 )
50
51/** Neighbour discovery maximum timeout */
52#define NEIGHBOUR_MAX_TIMEOUT ( TICKS_PER_SEC * 3 )
53
54/** Neighbour discovery maximum burst count for delayed transmissions
55 *
56 * When using delay injection, timer quantisation can cause a large
57 * number of delayed packets to be scheduled at the same time. This
58 * can quickly exhaust available transmit descriptors, leading to
59 * packets that are dropped completely (not just delayed).
60 *
61 * Limit the number of delayed packets that we will attempt to
62 * transmit at once, to allow time for transmit completions to occur.
63 */
64#define NEIGHBOUR_DELAY_MAX_BURST 2
65
66/** The neighbour cache */
68
69/** Pending operation for delayed transmissions */
71
72static void neighbour_expired ( struct retry_timer *timer, int over );
73
74/**
75 * Free neighbour cache entry
76 *
77 * @v refcnt Reference count
78 */
79static void neighbour_free ( struct refcnt *refcnt ) {
80 struct neighbour *neighbour =
82
83 /* Sanity check */
85
86 /* Drop reference to network device */
88
89 /* Free neighbour */
90 free ( neighbour );
91}
92
93/**
94 * Create neighbour cache entry
95 *
96 * @v netdev Network device
97 * @v net_protocol Network-layer protocol
98 * @v net_dest Destination network-layer address
99 * @ret neighbour Neighbour cache entry, or NULL if allocation failed
100 */
101static struct neighbour * neighbour_create ( struct net_device *netdev,
103 const void *net_dest ) {
104 struct neighbour *neighbour;
105
106 /* Allocate and initialise entry */
107 neighbour = zalloc ( sizeof ( *neighbour ) );
108 if ( ! neighbour )
109 return NULL;
115 timer_init ( &neighbour->timer, neighbour_expired, &neighbour->refcnt );
116 set_timer_limits ( &neighbour->timer, NEIGHBOUR_MIN_TIMEOUT,
119
120 /* Transfer ownership to cache */
122
123 DBGC ( neighbour, "NEIGHBOUR %s %s %s created\n", netdev->name,
125 return neighbour;
126}
127
128/**
129 * Find neighbour cache entry
130 *
131 * @v netdev Network device
132 * @v net_protocol Network-layer protocol
133 * @v net_dest Destination network-layer address
134 * @ret neighbour Neighbour cache entry, or NULL if not found
135 */
136static struct neighbour * neighbour_find ( struct net_device *netdev,
138 const void *net_dest ) {
139 struct neighbour *neighbour;
140
142 if ( ( neighbour->netdev == netdev ) &&
145 net_protocol->net_addr_len ) == 0 ) ) {
146
147 /* Move to start of cache */
148 list_del ( &neighbour->list );
150
151 return neighbour;
152 }
153 }
154 return NULL;
155}
156
157/**
158 * Start neighbour discovery
159 *
160 * @v neighbour Neighbour cache entry
161 * @v discovery Neighbour discovery protocol
162 * @v net_source Source network-layer address
163 */
166 const void *net_source ) {
169
170 /* Record discovery protocol and source network-layer address */
171 neighbour->discovery = discovery;
172 memcpy ( neighbour->net_source, net_source,
174
175 /* Start timer to trigger neighbour discovery */
177
178 DBGC ( neighbour, "NEIGHBOUR %s %s %s discovering via %s\n",
179 netdev->name, net_protocol->name,
182}
183
184/**
185 * Transmit deferred packets
186 *
187 * @v neighbour Neighbour cache entry
188 */
189static void neighbour_tx_queue ( struct neighbour *neighbour ) {
192 const void *ll_dest = neighbour->ll_dest;
193 struct neighbour_delay *delay;
194 struct io_buffer *iobuf;
195 unsigned long elapsed;
196 unsigned long threshold;
197 unsigned int count = 0;
198 int rc;
199
200 /* Stop retransmission timer */
202
203 /* Transmit any packets in queue. Take out a temporary
204 * reference on the entry to prevent it from going out of
205 * scope during the call to net_tx().
206 */
208 while ( ( iobuf = list_first_entry ( &neighbour->tx_queue,
209 struct io_buffer, list )) != NULL){
210
211 /* Handle delay injection */
212 if ( NEIGHBOUR_DELAY_MS ) {
213
214 /* Determine elapsed time since transmission attempt */
215 delay = iobuf->data;
216 elapsed = ( currticks() - delay->start );
217 threshold = ( NEIGHBOUR_DELAY_MS * TICKS_PER_MS );
218
219 /* Defer transmission if not yet scheduled */
220 if ( elapsed < threshold ) {
222 ( threshold - elapsed ) );
223 break;
224 }
225
226 /* Defer transmission if maximum burst count reached */
227 if ( ++count >= NEIGHBOUR_DELAY_MAX_BURST ) {
229 break;
230 }
231
232 /* Strip pseudo-header */
233 iob_pull ( iobuf, sizeof ( *delay ) );
234
235 /* Remove pending operation */
237 }
238
239 /* Transmit deferred packet */
240 DBGC2 ( neighbour, "NEIGHBOUR %s %s %s transmitting deferred "
241 "packet\n", netdev->name, net_protocol->name,
243 list_del ( &iobuf->list );
244 if ( ( rc = net_tx ( iobuf, netdev, net_protocol, ll_dest,
245 netdev->ll_addr ) ) != 0 ) {
246 DBGC ( neighbour, "NEIGHBOUR %s %s %s could not "
247 "transmit deferred packet: %s\n",
248 netdev->name, net_protocol->name,
250 strerror ( rc ) );
251 /* Ignore error and continue */
252 }
253 }
255}
256
257/**
258 * Complete neighbour discovery
259 *
260 * @v neighbour Neighbour cache entry
261 * @v ll_dest Destination link-layer address
262 */
264 const void *ll_dest ) {
266 struct ll_protocol *ll_protocol = netdev->ll_protocol;
268
269 /* Fill in link-layer address */
271 DBGC ( neighbour, "NEIGHBOUR %s %s %s is %s %s\n", netdev->name,
274
275 /* Mark discovery as complete */
277
278 /* Transmit any deferred packets */
280}
281
282/**
283 * Destroy neighbour cache entry
284 *
285 * @v neighbour Neighbour cache entry
286 * @v rc Reason for destruction
287 */
288static void neighbour_destroy ( struct neighbour *neighbour, int rc ) {
291 struct io_buffer *iobuf;
292
293 /* Take ownership from cache */
294 list_del ( &neighbour->list );
295
296 /* Stop timer */
298
299 /* Discard any outstanding I/O buffers */
300 while ( ( iobuf = list_first_entry ( &neighbour->tx_queue,
301 struct io_buffer, list )) != NULL){
302 DBGC2 ( neighbour, "NEIGHBOUR %s %s %s discarding deferred "
303 "packet: %s\n", netdev->name, net_protocol->name,
305 strerror ( rc ) );
306 list_del ( &iobuf->list );
307 if ( NEIGHBOUR_DELAY_MS )
309 netdev_tx_err ( neighbour->netdev, iobuf, rc );
310 }
311
312 DBGC ( neighbour, "NEIGHBOUR %s %s %s destroyed: %s\n", netdev->name,
314 strerror ( rc ) );
315
316 /* Drop remaining reference */
318}
319
320/**
321 * Handle neighbour timer expiry
322 *
323 * @v timer Retry timer
324 * @v fail Failure indicator
325 */
326static void neighbour_expired ( struct retry_timer *timer, int fail ) {
327 struct neighbour *neighbour =
328 container_of ( timer, struct neighbour, timer );
331 struct neighbour_discovery *discovery =
333 const void *net_dest = neighbour->net_dest;
334 const void *net_source = neighbour->net_source;
335 int rc;
336
337 /* If the timer is being (ab)used for delay injection, then
338 * transmit the deferred packet queue.
339 */
340 if ( NEIGHBOUR_DELAY_MS && ( ! neighbour->discovery ) ) {
342 return;
343 }
344
345 /* If we have failed, destroy the cache entry */
346 if ( fail ) {
348 return;
349 }
350
351 /* Restart the timer */
353
354 /* Transmit neighbour request */
355 if ( ( rc = discovery->tx_request ( netdev, net_protocol, net_dest,
356 net_source ) ) != 0 ) {
357 DBGC ( neighbour, "NEIGHBOUR %s %s %s could not transmit %s "
358 "request: %s\n", netdev->name, net_protocol->name,
361 /* Retransmit when timer expires */
362 return;
363 }
364}
365
366/**
367 * Transmit packet, determining link-layer address via neighbour discovery
368 *
369 * @v iobuf I/O buffer
370 * @v netdev Network device
371 * @v discovery Neighbour discovery protocol
372 * @v net_protocol Network-layer protocol
373 * @v net_dest Destination network-layer address
374 * @v net_source Source network-layer address
375 * @ret rc Return status code
376 */
377int neighbour_tx ( struct io_buffer *iobuf, struct net_device *netdev,
378 struct net_protocol *net_protocol, const void *net_dest,
379 struct neighbour_discovery *discovery,
380 const void *net_source ) {
381 struct neighbour *neighbour;
382 struct neighbour_delay *delay;
383 int rc;
384
385 /* Find or create neighbour cache entry */
387 if ( ! neighbour ) {
389 if ( ! neighbour )
390 return -ENOMEM;
391 neighbour_discover ( neighbour, discovery, net_source );
392 }
393
394 /* If discovery is still in progress or if delay injection is
395 * in use, then queue for later transmission.
396 */
398
399 /* Add to deferred packet queue */
400 DBGC2 ( neighbour, "NEIGHBOUR %s %s %s deferring packet\n",
401 netdev->name, net_protocol->name,
402 net_protocol->ntoa ( net_dest ) );
403 list_add_tail ( &iobuf->list, &neighbour->tx_queue );
404
405 /* Handle delay injection, if applicable */
406 if ( NEIGHBOUR_DELAY_MS ) {
407
408 /* Record original transmission time */
409 delay = iob_push ( iobuf, sizeof ( *delay ) );
410 delay->start = currticks();
411
412 /* Add pending operation */
414
415 /* Process deferred packet queue, if possible */
416 if ( ! neighbour->discovery )
418 }
419
420 return 0;
421 }
422
423 /* Otherwise, transmit immediately */
424 if ( ( rc = net_tx ( iobuf, netdev, net_protocol, neighbour->ll_dest,
425 netdev->ll_addr ) ) != 0 ) {
426 return rc;
427 }
428
429 return 0;
430}
431
432/**
433 * Update existing neighbour cache entry
434 *
435 * @v netdev Network device
436 * @v net_protocol Network-layer protocol
437 * @v net_dest Destination network-layer address
438 * @v ll_dest Destination link-layer address
439 * @ret rc Return status code
440 */
443 const void *net_dest, const void *ll_dest ) {
444 struct neighbour *neighbour;
445
446 /* Find neighbour cache entry */
448 if ( ! neighbour )
449 return -ENOENT;
450
451 /* Set destination address */
453
454 return 0;
455}
456
457/**
458 * Define neighbour cache entry
459 *
460 * @v netdev Network device
461 * @v net_protocol Network-layer protocol
462 * @v net_dest Destination network-layer address
463 * @v ll_dest Destination link-layer address, if known
464 * @ret rc Return status code
465 */
468 const void *net_dest, const void *ll_dest ) {
469 struct neighbour *neighbour;
470
471 /* Find or create neighbour cache entry */
473 if ( ! neighbour ) {
475 if ( ! neighbour )
476 return -ENOMEM;
477 }
478
479 /* Set destination address */
481
482 return 0;
483}
484
485/**
486 * Update neighbour cache on network device state change or removal
487 *
488 * @v netdev Network device
489 * @v priv Private data
490 */
491static void neighbour_flush ( struct net_device *netdev, void *priv __unused ) {
492 struct neighbour *neighbour;
493 struct neighbour *tmp;
494
495 /* Remove all neighbour cache entries when a network device is closed */
496 if ( ! netdev_is_open ( netdev ) ) {
499 }
500}
501
502/** Neighbour driver (for net device notifications) */
503struct net_driver neighbour_net_driver __net_driver = {
504 .name = "Neighbour",
505 .notify = neighbour_flush,
506 .remove = neighbour_flush,
507};
508
509/**
510 * Discard some cached neighbour entries
511 *
512 * @ret discarded Number of cached items discarded
513 */
514static unsigned int neighbour_discard ( void ) {
515 struct neighbour *neighbour;
516
517 /* Drop oldest cache entry, if any */
519 if ( neighbour ) {
521 return 1;
522 } else {
523 return 0;
524 }
525}
526
527/**
528 * Neighbour cache discarder
529 *
530 * Neighbour cache entries are deemed to have a high replacement cost,
531 * since flushing an active neighbour cache entry midway through a TCP
532 * transfer will cause substantial disruption.
533 */
535 .discard = neighbour_discard,
536};
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
Fault injection.
#define NEIGHBOUR_DELAY_MS
Definition fault.h:19
#define delay(nanosec)
Definition epic100.c:49
Error codes.
static struct net_device * netdev
Definition gdbudp.c:53
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define CACHE_EXPENSIVE
Items with a high replacement cost.
Definition malloc.h:115
#define DBGC2(...)
Definition compiler.h:522
#define DBGC(...)
Definition compiler.h:505
static unsigned int count
Number of entries.
Definition dwmac.h:220
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOENT
No such file or directory.
Definition errno.h:515
#define ETIMEDOUT
Connection timed out.
Definition errno.h:670
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ENOBUFS
No buffer space available.
Definition errno.h:499
#define ENODEV
No such device.
Definition errno.h:510
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
iPXE timers
#define TICKS_PER_MS
Number of ticks per millisecond.
Definition timer.h:26
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
I/O buffers.
#define iob_push(iobuf, len)
Definition iobuf.h:89
#define iob_pull(iobuf, len)
Definition iobuf.h:107
unsigned long tmp
Definition linux_pci.h:65
#define list_first_entry(list, type, member)
Get the container of the first entry in a list.
Definition list.h:334
#define list_last_entry(list, type, member)
Get the container of the last entry in a list.
Definition list.h:347
#define LIST_HEAD_INIT(list)
Initialise a static list head.
Definition list.h:31
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
#define list_empty(list)
Test whether a list is empty.
Definition list.h:137
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
Dynamic memory allocation.
#define __cache_discarder(cost)
Declare a cache discarder.
Definition malloc.h:106
int neighbour_tx(struct io_buffer *iobuf, struct net_device *netdev, struct net_protocol *net_protocol, const void *net_dest, struct neighbour_discovery *discovery, const void *net_source)
Transmit packet, determining link-layer address via neighbour discovery.
Definition neighbour.c:377
static void neighbour_expired(struct retry_timer *timer, int over)
Handle neighbour timer expiry.
Definition neighbour.c:326
static struct neighbour * neighbour_create(struct net_device *netdev, struct net_protocol *net_protocol, const void *net_dest)
Create neighbour cache entry.
Definition neighbour.c:101
static struct neighbour * neighbour_find(struct net_device *netdev, struct net_protocol *net_protocol, const void *net_dest)
Find neighbour cache entry.
Definition neighbour.c:136
#define NEIGHBOUR_MAX_TIMEOUT
Neighbour discovery maximum timeout.
Definition neighbour.c:52
struct list_head neighbours
The neighbour cache.
Definition neighbour.c:67
static void neighbour_destroy(struct neighbour *neighbour, int rc)
Destroy neighbour cache entry.
Definition neighbour.c:288
static void neighbour_discovered(struct neighbour *neighbour, const void *ll_dest)
Complete neighbour discovery.
Definition neighbour.c:263
int neighbour_update(struct net_device *netdev, struct net_protocol *net_protocol, const void *net_dest, const void *ll_dest)
Update existing neighbour cache entry.
Definition neighbour.c:441
static struct pending_operation neighbour_delayed
Pending operation for delayed transmissions.
Definition neighbour.c:70
#define NEIGHBOUR_MIN_TIMEOUT
Neighbour discovery minimum timeout.
Definition neighbour.c:49
static void neighbour_flush(struct net_device *netdev, void *priv __unused)
Update neighbour cache on network device state change or removal.
Definition neighbour.c:491
static void neighbour_tx_queue(struct neighbour *neighbour)
Transmit deferred packets.
Definition neighbour.c:189
#define NEIGHBOUR_DELAY_MAX_BURST
Neighbour discovery maximum burst count for delayed transmissions.
Definition neighbour.c:64
int neighbour_define(struct net_device *netdev, struct net_protocol *net_protocol, const void *net_dest, const void *ll_dest)
Define neighbour cache entry.
Definition neighbour.c:466
static void neighbour_free(struct refcnt *refcnt)
Free neighbour cache entry.
Definition neighbour.c:79
static void neighbour_discover(struct neighbour *neighbour, struct neighbour_discovery *discovery, const void *net_source)
Start neighbour discovery.
Definition neighbour.c:164
static unsigned int neighbour_discard(void)
Discard some cached neighbour entries.
Definition neighbour.c:514
Neighbour discovery.
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:1074
void netdev_tx_err(struct net_device *netdev, struct io_buffer *iobuf, int rc)
Discard transmitted packet.
Definition netdevice.c:441
static struct net_device * netdev_get(struct net_device *netdev)
Get reference to network device.
Definition netdevice.h:565
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition netdevice.h:662
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition netdevice.h:576
#define __net_driver
Declare a network driver.
Definition netdevice.h:507
void pending_put(struct pending_operation *pending)
Mark an operation as no longer pending.
Definition pending.c:59
void pending_get(struct pending_operation *pending)
Mark an operation as pending.
Definition pending.c:46
Pending operations.
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define ref_get(refcnt)
Get additional reference to object.
Definition refcnt.h:93
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
void start_timer(struct retry_timer *timer)
Start timer.
Definition retry.c:94
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition retry.c:65
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition retry.c:118
Retry timers.
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition retry.h:100
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
A cache discarder.
Definition malloc.h:93
A persistent I/O buffer.
Definition iobuf.h:38
void * data
Start of data.
Definition iobuf.h:53
struct list_head list
List of which this buffer is a member.
Definition iobuf.h:45
A doubly-linked list entry (or list head)
Definition list.h:19
A link-layer protocol.
Definition netdevice.h:115
const char * name
Protocol name.
Definition netdevice.h:117
const char *(* ntoa)(const void *ll_addr)
Transcribe link-layer address.
Definition netdevice.h:164
uint8_t ll_addr_len
Link-layer address length.
Definition netdevice.h:199
A neighbour transmission delay pseudo-header.
Definition neighbour.h:65
A neighbour discovery protocol.
Definition neighbour.h:20
int(* tx_request)(struct net_device *netdev, struct net_protocol *net_protocol, const void *net_dest, const void *net_source)
Transmit neighbour discovery request.
Definition neighbour.h:32
const char * name
Name.
Definition neighbour.h:22
A neighbour cache entry.
Definition neighbour.h:38
struct neighbour_discovery * discovery
Neighbour discovery protocol (if discovery is ongoing)
Definition neighbour.h:54
uint8_t net_source[MAX_NET_ADDR_LEN]
Network-layer source address (for discovery requests)
Definition neighbour.h:56
struct retry_timer timer
Retransmission timer.
Definition neighbour.h:58
struct list_head tx_queue
Pending I/O buffers.
Definition neighbour.h:61
struct refcnt refcnt
Reference count.
Definition neighbour.h:40
struct net_protocol * net_protocol
Network-layer protocol.
Definition neighbour.h:47
struct net_device * netdev
Network device.
Definition neighbour.h:45
uint8_t ll_dest[MAX_LL_ADDR_LEN]
Link-layer destination address.
Definition neighbour.h:51
uint8_t net_dest[MAX_NET_ADDR_LEN]
Network-layer destination address.
Definition neighbour.h:49
struct list_head list
List of neighbour cache entries.
Definition neighbour.h:42
A network device.
Definition netdevice.h:353
A network upper-layer driver.
Definition netdevice.h:477
A network-layer protocol.
Definition netdevice.h:65
const char * name
Protocol name.
Definition netdevice.h:67
uint8_t net_addr_len
Network-layer address length.
Definition netdevice.h:102
const char *(* ntoa)(const void *net_addr)
Transcribe network-layer address.
Definition netdevice.h:95
A pending operation.
Definition pending.h:14
A reference counter.
Definition refcnt.h:27
A retry timer.
Definition retry.h:22
A timer.
Definition timer.h:29
unsigned long currticks(void)
Get current system time in ticks.
Definition timer.c:43
static struct tlan_private * priv
Definition tlan.c:225