iPXE
peerdisc.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015 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 (at your option) 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 <stdlib.h>
28#include <string.h>
29#include <ctype.h>
30#include <errno.h>
31#include <assert.h>
32#include <ipxe/xfer.h>
33#include <ipxe/iobuf.h>
34#include <ipxe/open.h>
35#include <ipxe/tcpip.h>
36#include <ipxe/uuid.h>
37#include <ipxe/base16.h>
38#include <ipxe/netdevice.h>
39#include <ipxe/timer.h>
40#include <ipxe/fault.h>
41#include <ipxe/settings.h>
42#include <ipxe/pccrr.h>
43#include <ipxe/pccrd.h>
44#include <ipxe/peerdisc.h>
45
46/** @file
47 *
48 * Peer Content Caching and Retrieval (PeerDist) protocol peer discovery
49 *
50 */
51
52/** List of discovery segments */
53static LIST_HEAD ( peerdisc_segments );
54
55/** Number of repeated discovery attempts */
56#define PEERDISC_REPEAT_COUNT 2
57
58/** Time between repeated discovery attempts */
59#define PEERDISC_REPEAT_TIMEOUT ( 1 * TICKS_PER_SEC )
60
61/** Default discovery timeout (in seconds) */
62#define PEERDISC_DEFAULT_TIMEOUT_SECS 2
63
64/** Recommended discovery timeout (in seconds)
65 *
66 * We reduce the recommended discovery timeout whenever a segment
67 * fails to discover any peers, and restore the default value whenever
68 * a valid discovery reply is received. We continue to send discovery
69 * requests even if the recommended timeout is reduced to zero.
70 *
71 * This strategy is intended to minimise discovery delays when no
72 * peers are available on the network, while allowing downloads to
73 * quickly switch back to using PeerDist acceleration if new peers
74 * become available.
75 */
77
78/** Most recently discovered peer (for any block) */
79static char *peerdisc_recent;
80
81/** Hosted cache server */
82static char *peerhost;
83
84/** Local cache directory */
85static char *peerpath;
86
87static struct peerdisc_segment * peerdisc_find ( const char *id );
89 struct peerdist_retrieval *retrieval,
90 const char *location );
91
92/******************************************************************************
93 *
94 * Statistics reporting
95 *
96 ******************************************************************************
97 */
98
99/**
100 * Report peer discovery statistics
101 *
102 * @v intf Interface
103 * @v peer Selected peer (or NULL)
104 * @v peers List of available peers
105 */
106void peerdisc_stat ( struct interface *intf, struct peerdisc_peer *peer,
107 struct list_head *peers ) {
108 struct interface *dest;
109 peerdisc_stat_TYPE ( void * ) *op =
111 void *object = intf_object ( dest );
112
113 if ( op ) {
114 op ( object, peer, peers );
115 } else {
116 /* Default is to do nothing */
117 }
118
119 intf_put ( dest );
120}
121
122/******************************************************************************
123 *
124 * Discovery sockets
125 *
126 ******************************************************************************
127 */
128
129/**
130 * Open all PeerDist discovery sockets
131 *
132 * @ret rc Return status code
133 */
134static int peerdisc_socket_open ( void ) {
135 struct peerdisc_socket *socket;
136 int rc;
137
138 /* Open each socket */
140 if ( ( rc = xfer_open_socket ( &socket->xfer, SOCK_DGRAM,
141 &socket->address.sa,
142 NULL ) ) != 0 ) {
143 DBGC ( socket, "PEERDISC %s could not open socket: "
144 "%s\n", socket->name, strerror ( rc ) );
145 goto err;
146 }
147 }
148
149 return 0;
150
151 err:
153 intf_restart ( &socket->xfer, rc );
154 return rc;
155}
156
157/**
158 * Attempt to transmit PeerDist discovery requests on all sockets
159 *
160 * @v uuid Message UUID string
161 * @v id Segment identifier string
162 */
163static void peerdisc_socket_tx ( const char *uuid, const char *id ) {
164 struct peerdisc_socket *socket;
165 struct net_device *netdev;
166 struct xfer_metadata meta;
167 union {
168 struct sockaddr sa;
169 struct sockaddr_tcpip st;
170 } address;
171 char *request;
172 size_t len;
173 int rc;
174
175 /* Construct discovery request */
177 if ( ! request )
178 goto err_request;
179 len = strlen ( request );
180
181 /* Initialise data transfer metadata */
182 memset ( &meta, 0, sizeof ( meta ) );
183 meta.dest = &address.sa;
184
185 /* Send message on each socket */
187
188 /* Initialise socket address */
189 memcpy ( &address.sa, &socket->address.sa,
190 sizeof ( address.sa ) );
191
192 /* Send message on each open network device */
194
195 /* Skip unopened network devices */
196 if ( ! netdev_is_open ( netdev ) )
197 continue;
198 address.st.st_scope_id = netdev->scope_id;
199
200 /* Discard request (for test purposes) if applicable */
201 if ( inject_fault ( PEERDISC_DISCARD_RATE ) )
202 continue;
203
204 /* Transmit request */
205 if ( ( rc = xfer_deliver_raw_meta ( &socket->xfer,
206 request, len,
207 &meta ) ) != 0 ) {
208 DBGC ( socket, "PEERDISC %s could not transmit "
209 "via %s: %s\n", socket->name,
210 netdev->name, strerror ( rc ) );
211 /* Contine to try other net devices/sockets */
212 continue;
213 }
214 }
215 }
216
217 free ( request );
218 err_request:
219 return;
220}
221
222/**
223 * Handle received PeerDist discovery reply
224 *
225 * @v socket PeerDist discovery socket
226 * @v iobuf I/O buffer
227 * @v meta Data transfer metadata
228 * @ret rc Return status code
229 */
230static int peerdisc_socket_rx ( struct peerdisc_socket *socket,
231 struct io_buffer *iobuf,
232 struct xfer_metadata *meta __unused ) {
233 struct peerdist_discovery_reply reply;
235 char *id;
236 char *location;
237 int rc;
238
239 /* Discard reply (for test purposes) if applicable */
240 if ( ( rc = inject_fault ( PEERDISC_DISCARD_RATE ) ) != 0 )
241 goto err;
242
243 /* Parse reply */
244 if ( ( rc = peerdist_discovery_reply ( iobuf->data, iob_len ( iobuf ),
245 &reply ) ) != 0 ) {
246 DBGC ( socket, "PEERDISC %s could not parse reply: %s\n",
247 socket->name, strerror ( rc ) );
248 DBGC_HDA ( socket, 0, iobuf->data, iob_len ( iobuf ) );
249 goto err;
250 }
251
252 /* Any kind of discovery reply indicates that there are active
253 * peers on a local network, so restore the recommended
254 * discovery timeout to its default value for future requests.
255 */
257 DBGC ( socket, "PEERDISC %s restoring timeout to %d seconds\n",
259 }
261
262 /* Iterate over segment IDs */
263 for ( id = reply.ids ; *id ; id += ( strlen ( id ) + 1 /* NUL */ ) ) {
264
265 /* Find corresponding segment */
266 segment = peerdisc_find ( id );
267 if ( ! segment ) {
268 DBGC ( socket, "PEERDISC %s ignoring reply for %s\n",
269 socket->name, id );
270 continue;
271 }
272
273 /* Report all discovered peer locations */
274 for ( location = reply.locations ; *location ;
275 location += ( strlen ( location ) + 1 /* NUL */ ) ) {
276
277 /* Report discovered peer location */
278 if ( ( rc = peerdisc_discovered ( segment,
280 location ) ) != 0 ) {
281 goto err;
282 }
283 }
284 }
285
286 err:
287 free_iob ( iobuf );
288 return rc;
289}
290
291/**
292 * Close all PeerDist discovery sockets
293 *
294 * @v rc Reason for close
295 */
296static void peerdisc_socket_close ( int rc ) {
297 struct peerdisc_socket *socket;
298
299 /* Close all sockets */
301 intf_restart ( &socket->xfer, rc );
302}
303
304/** PeerDist discovery socket interface operations */
308
309/** PeerDist discovery socket interface descriptor */
312
313/** PeerDist discovery IPv4 socket */
314struct peerdisc_socket peerdisc_socket_ipv4 __peerdisc_socket = {
315 .name = "IPv4",
316 .address = {
317 .sin = {
318 .sin_family = AF_INET,
319 .sin_port = htons ( PEERDIST_DISCOVERY_PORT ),
320 .sin_addr.s_addr = PEERDIST_DISCOVERY_IPV4,
321 },
322 },
324};
325
326/** PeerDist discovery IPv6 socket */
327struct peerdisc_socket peerdisc_socket_ipv6 __peerdisc_socket = {
328 .name = "IPv6",
329 .address = {
330 .sin6 = {
331 .sin6_family = AF_INET6,
332 .sin6_port = htons ( PEERDIST_DISCOVERY_PORT ),
333 .sin6_addr.s6_addr = PEERDIST_DISCOVERY_IPV6,
334 },
335 },
337};
338
339/******************************************************************************
340 *
341 * Discovery segments
342 *
343 ******************************************************************************
344 */
345
346/**
347 * Free PeerDist discovery segment
348 *
349 * @v refcnt Reference count
350 */
351static void peerdisc_free ( struct refcnt *refcnt ) {
352 struct peerdisc_segment *segment =
354 struct peerdisc_peer *peer;
355 struct peerdisc_peer *tmp;
356
357 /* Free all discovered peers */
359 list_del ( &peer->list );
360 free ( peer );
361 }
362
363 /* Free segment */
364 free ( segment );
365}
366
367/**
368 * Find PeerDist discovery segment
369 *
370 * @v id Segment ID
371 * @ret segment PeerDist discovery segment, or NULL if not found
372 */
373static struct peerdisc_segment * peerdisc_find ( const char *id ) {
375
376 /* Look for a matching segment */
377 list_for_each_entry ( segment, &peerdisc_segments, list ) {
378 if ( strcmp ( id, segment->id ) == 0 )
379 return segment;
380 }
381
382 return NULL;
383}
384
385/**
386 * Add discovered PeerDist peer
387 *
388 * @v segment PeerDist discovery segment
389 * @v retrieval PeerDist retrieval protocol
390 * @v location Peer location
391 * @ret rc Return status code
392 */
394 struct peerdist_retrieval *retrieval,
395 const char *location ) {
396 struct peerdisc_peer *peer;
397 struct peerdisc_client *peerdisc;
398 struct peerdisc_client *tmp;
399 char *recent;
400
401 /* Ignore duplicate peers */
402 list_for_each_entry ( peer, &segment->peers, list ) {
403 if ( strcmp ( peer->location, location ) == 0 ) {
404 DBGC2 ( segment, "PEERDISC %p duplicate %s\n",
405 segment, location );
406 return 0;
407 }
408 }
409 DBGC2 ( segment, "PEERDISC %p discovered %s\n", segment, location );
410
411 /* Allocate and initialise structure */
412 peer = zalloc ( sizeof ( *peer ) + strlen ( location ) + 1 /* NUL */ );
413 if ( ! peer )
414 return -ENOMEM;
415 peer->retrieval = retrieval;
416 strcpy ( peer->location, location );
417
418 /* Add to end of list of peers */
419 list_add_tail ( &peer->list, &segment->peers );
420
421 /* Record as most recently discovered peer, if applicable */
422 if ( ( location != peerdisc_recent ) &&
423 ( location != peerhost ) &&
424 ( location != peerpath ) ) {
425 recent = strdup ( location );
426 if ( recent ) {
428 peerdisc_recent = recent;
429 }
430 }
431
432 /* Notify all clients */
433 list_for_each_entry_safe ( peerdisc, tmp, &segment->clients, list )
434 peerdisc->op->discovered ( peerdisc );
435
436 return 0;
437}
438
439/**
440 * Handle discovery timer expiry
441 *
442 * @v timer Discovery timer
443 * @v over Failure indicator
444 */
445static void peerdisc_expired ( struct retry_timer *timer, int over __unused ) {
446 struct peerdisc_segment *segment =
448
449 /* Attempt to transmit discovery requests */
450 peerdisc_socket_tx ( segment->uuid, segment->id );
451
452 /* Schedule next transmission, if applicable */
453 if ( timer->count < PEERDISC_REPEAT_COUNT )
455}
456
457/**
458 * Create PeerDist discovery segment
459 *
460 * @v id Segment ID
461 * @ret segment PeerDist discovery segment, or NULL on error
462 */
463static struct peerdisc_segment * peerdisc_create ( const char *id ) {
465 union {
466 union uuid uuid;
467 uint32_t dword[ sizeof ( union uuid ) / sizeof ( uint32_t ) ];
468 } random_uuid;
469 size_t uuid_len;
470 size_t id_len;
471 const char *uuid;
472 char *uuid_copy;
473 char *id_copy;
474 unsigned int i;
475 int rc;
476
477 /* Generate a random message UUID. This does not require high
478 * quality randomness.
479 */
480 for ( i = 0 ; i < ( sizeof ( random_uuid.dword ) /
481 sizeof ( random_uuid.dword[0] ) ) ; i++ )
482 random_uuid.dword[i] = random();
483 uuid = uuid_ntoa ( &random_uuid.uuid );
484
485 /* Calculate string lengths */
486 id_len = ( strlen ( id ) + 1 /* NUL */ );
487 uuid_len = ( strlen ( uuid ) + 1 /* NUL */ );
488
489 /* Allocate and initialise structure */
490 segment = zalloc ( sizeof ( *segment ) + id_len + uuid_len );
491 if ( ! segment )
492 goto err_alloc;
493 id_copy = ( ( ( void * ) segment ) + sizeof ( *segment ) );
494 memcpy ( id_copy, id, id_len );
495 uuid_copy = ( ( ( void * ) id_copy ) + id_len );
496 memcpy ( uuid_copy, uuid, uuid_len );
497 ref_init ( &segment->refcnt, peerdisc_free );
498 segment->id = id_copy;
499 segment->uuid = uuid_copy;
500 INIT_LIST_HEAD ( &segment->peers );
501 INIT_LIST_HEAD ( &segment->clients );
502 timer_init ( &segment->timer, peerdisc_expired, &segment->refcnt );
503
504 /* Add local cache directory, if any */
505 if ( peerpath )
507
508 /* Add hosted cache server or initiate discovery */
509 if ( peerhost ) {
510
511 /* Add hosted cache server to list of peers */
513 peerhost ) ) != 0 ) {
514 goto err_peerhost;
515 }
516
517 } else {
518
519 /* Add most recently discovered peer to list of peers
520 *
521 * This is a performance optimisation: we assume that
522 * the most recently discovered peer for any block has
523 * a high probability of also having a copy of the
524 * next block that we attempt to discover.
525 */
526 if ( peerdisc_recent ) {
529 }
530
531 /* Start discovery timer */
532 start_timer_nodelay ( &segment->timer );
533 DBGC2 ( segment, "PEERDISC %p discovering %s\n",
534 segment, segment->id );
535 }
536
537 /* Add to list of segments, transfer reference to list, and return */
538 list_add_tail ( &segment->list, &peerdisc_segments );
539 return segment;
540
541 err_peerhost:
542 ref_put ( &segment->refcnt );
543 err_alloc:
544 return NULL;
545}
546
547/**
548 * Destroy PeerDist discovery segment
549 *
550 * @v segment PeerDist discovery segment
551 */
553
554 /* Sanity check */
555 assert ( list_empty ( &segment->clients ) );
556
557 /* Stop timer */
558 stop_timer ( &segment->timer );
559
560 /* Remove from list of segments and drop list's reference */
561 list_del ( &segment->list );
562 ref_put ( &segment->refcnt );
563}
564
565/******************************************************************************
566 *
567 * Discovery clients
568 *
569 ******************************************************************************
570 */
571
572/**
573 * Open PeerDist discovery client
574 *
575 * @v peerdisc PeerDist discovery client
576 * @v id Segment ID
577 * @v len Length of segment ID
578 * @ret rc Return status code
579 */
580int peerdisc_open ( struct peerdisc_client *peerdisc, const void *id,
581 size_t len ) {
583 char id_string[ base16_encoded_len ( len ) + 1 /* NUL */ ];
584 char *id_chr;
585 int rc;
586
587 /* Construct ID string */
588 base16_encode ( id, len, id_string, sizeof ( id_string ) );
589 for ( id_chr = id_string ; *id_chr ; id_chr++ )
590 *id_chr = toupper ( *id_chr );
591
592 /* Sanity check */
593 assert ( peerdisc->segment == NULL );
594
595 /* Open socket if this is the first segment */
596 if ( list_empty ( &peerdisc_segments ) &&
597 ( ( rc = peerdisc_socket_open() ) != 0 ) )
598 return rc;
599
600 /* Find or create segment */
601 if ( ! ( ( segment = peerdisc_find ( id_string ) ) ||
602 ( segment = peerdisc_create ( id_string ) ) ) )
603 return -ENOMEM;
604
605 /* Add to list of clients */
606 ref_get ( &segment->refcnt );
607 peerdisc->segment = segment;
608 list_add_tail ( &peerdisc->list, &segment->clients );
609
610 return 0;
611}
612
613/**
614 * Close PeerDist discovery client
615 *
616 * @v peerdisc PeerDist discovery client
617 */
618void peerdisc_close ( struct peerdisc_client *peerdisc ) {
619 struct peerdisc_segment *segment = peerdisc->segment;
620
621 /* Ignore if discovery is already closed */
622 if ( ! segment )
623 return;
624
625 /* If no peers were discovered, reduce the recommended
626 * discovery timeout to minimise delays on future requests.
627 */
628 if ( list_empty ( &segment->peers ) && peerdisc_timeout_secs ) {
630 DBGC ( segment, "PEERDISC %p reducing timeout to %d "
631 "seconds\n", peerdisc, peerdisc_timeout_secs );
632 }
633
634 /* Remove from list of clients */
635 peerdisc->segment = NULL;
636 list_del ( &peerdisc->list );
637 ref_put ( &segment->refcnt );
638
639 /* If this was the last clients, destroy the segment */
640 if ( list_empty ( &segment->clients ) )
642
643 /* If there are no more segments, close the socket */
644 if ( list_empty ( &peerdisc_segments ) )
646}
647
648/******************************************************************************
649 *
650 * Settings
651 *
652 ******************************************************************************
653 */
654
655/** PeerDist hosted cache server setting */
656const struct setting peerhost_setting __setting ( SETTING_MISC, peerhost ) = {
657 .name = "peerhost",
658 .description = "PeerDist hosted cache",
659 .type = &setting_type_string,
660};
661
662/** PeerDist local cache directory setting */
663const struct setting peerpath_setting __setting ( SETTING_MISC, peerpath ) = {
664 .name = "peerpath",
665 .description = "PeerDist local cache",
666 .type = &setting_type_string,
667};
668
669/**
670 * Apply PeerDist discovery settings
671 *
672 * @ret rc Return status code
673 */
674static int apply_peerdisc_settings ( void ) {
675 char *host;
676 char *path;
677
678 /* Set hosted cache server, if any */
679 fetch_string_setting_copy ( NULL, &peerhost_setting, &host );
680 if ( host && ! ( peerhost && ( strcmp ( host, peerhost ) == 0 ) ) ) {
681 DBGC ( &peerdisc_segments, "PEERDISC using hosted cache %s\n",
682 host );
683 }
684 free ( peerhost );
685 peerhost = host;
686
687 /* Set local cache directory, if any */
688 fetch_string_setting_copy ( NULL, &peerpath_setting, &path );
689 if ( path && ! ( peerpath && ( strcmp ( path, peerpath ) == 0 ) ) ) {
690 DBGC ( &peerdisc_segments, "PEERDISC using local cache %s\n",
691 path );
692 }
693 free ( peerpath );
694 peerpath = path;
695
696 return 0;
697}
698
699/** PeerDist discovery settings applicator */
700struct settings_applicator peerdisc_applicator __settings_applicator = {
702};
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned int uint32_t
Definition stdint.h:12
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" retur dest)
Definition string.h:151
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
Base16 encoding.
static size_t base16_encoded_len(size_t raw_len)
Calculate length of base16-encoded data.
Definition base16.h:25
#define PEERDISC_DISCARD_RATE
Definition fault.h:22
Character types.
static int toupper(int character)
Convert character to upper case.
Definition ctype.h:121
ring len
Length.
Definition dwmac.h:226
uint8_t id_string[24]
ID string.
Definition eltorito.h:12
uint8_t id
Request identifier.
Definition ena.h:1
uint8_t meta
Metadata flags.
Definition ena.h:3
uint64_t address
Base address.
Definition ena.h:13
Error codes.
static struct net_device * netdev
Definition gdbudp.c:53
#define AF_INET
IPv4 Internet addresses.
Definition socket.h:64
#define AF_INET6
IPv6 Internet addresses.
Definition socket.h:65
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:598
#define SOCK_DGRAM
Definition socket.h:30
#define DBGC2(...)
Definition compiler.h:547
#define DBGC(...)
Definition compiler.h:530
#define DBGC_HDA(...)
Definition compiler.h:531
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define ENOMEM
Not enough space.
Definition errno.h:578
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:951
#define SETTING_MISC
Miscellaneous settings.
Definition settings.h:81
u8 request[0]
List of IEs requested.
Definition ieee80211.h:2
#define htons(value)
Definition byteswap.h:136
Fault injection.
Configuration settings.
#define __setting(setting_order, name)
Declare a configuration setting.
Definition settings.h:57
#define __settings_applicator
Declare a settings applicator.
Definition settings.h:265
Transport-network layer interface.
iPXE timers
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void * intf_object(struct interface *intf)
Get pointer to object containing object interface.
Definition interface.c:160
void intf_put(struct interface *intf)
Decrement reference count on an object interface.
Definition interface.c:150
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition interface.c:344
#define intf_get_dest_op(intf, type, dest)
Get object interface destination and operation method.
Definition interface.h:270
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81
#define INTF_INIT(descriptor)
Initialise a static object interface.
Definition interface.h:218
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
I/O buffers.
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:220
uint16_t segment
Code segment.
Definition librm.h:3
unsigned long tmp
Definition linux_pci.h:65
#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_HEAD(list)
Declare a static list head.
Definition list.h:38
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:718
struct mschapv2_challenge peer
Peer challenge.
Definition mschapv2.h:1
Network device management.
#define for_each_netdev(netdev)
Iterate over all network devices.
Definition netdevice.h:550
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition netdevice.h:665
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
int xfer_open_socket(struct interface *intf, int semantics, struct sockaddr *peer, struct sockaddr *local)
Open socket.
Definition open.c:152
Data transfer interface opening.
char * peerdist_discovery_request(const char *uuid, const char *id)
Construct discovery request.
Definition pccrd.c:107
Peer Content Caching and Retrieval: Discovery Protocol [MS-PCCRD].
#define PEERDIST_DISCOVERY_IPV6
PeerDist discovery IPv6 address (ff02::c).
Definition pccrd.h:22
#define PEERDIST_DISCOVERY_PORT
PeerDist discovery port.
Definition pccrd.h:16
#define PEERDIST_DISCOVERY_IPV4
PeerDist discovery IPv4 address (239.255.255.250).
Definition pccrd.h:19
struct peerdist_retrieval peerdist_get
PeerDist retrieval protocol using HTTP GET or local file.
Definition pccrr.c:190
struct peerdist_retrieval peerdist_post
PeerDist retrieval protocol using HTTP POST.
Definition pccrr.c:143
Peer Content Caching and Retrieval: Retrieval Protocol [MS-PCCRR].
static char * peerhost
Hosted cache server.
Definition peerdisc.c:82
static struct peerdisc_segment * peerdisc_find(const char *id)
Find PeerDist discovery segment.
Definition peerdisc.c:373
static struct peerdisc_segment * peerdisc_create(const char *id)
Create PeerDist discovery segment.
Definition peerdisc.c:463
static int peerdisc_socket_rx(struct peerdisc_socket *socket, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Handle received PeerDist discovery reply.
Definition peerdisc.c:230
void peerdisc_stat(struct interface *intf, struct peerdisc_peer *peer, struct list_head *peers)
Report peer discovery statistics.
Definition peerdisc.c:106
int peerdisc_open(struct peerdisc_client *peerdisc, const void *id, size_t len)
Open PeerDist discovery client.
Definition peerdisc.c:580
void peerdisc_close(struct peerdisc_client *peerdisc)
Close PeerDist discovery client.
Definition peerdisc.c:618
static char * peerpath
Local cache directory.
Definition peerdisc.c:85
static struct interface_operation peerdisc_socket_operations[]
PeerDist discovery socket interface operations.
Definition peerdisc.c:305
unsigned int peerdisc_timeout_secs
Recommended discovery timeout (in seconds).
Definition peerdisc.c:76
static int apply_peerdisc_settings(void)
Apply PeerDist discovery settings.
Definition peerdisc.c:674
static void peerdisc_destroy(struct peerdisc_segment *segment)
Destroy PeerDist discovery segment.
Definition peerdisc.c:552
static void peerdisc_socket_tx(const char *uuid, const char *id)
Attempt to transmit PeerDist discovery requests on all sockets.
Definition peerdisc.c:163
static int peerdisc_socket_open(void)
Open all PeerDist discovery sockets.
Definition peerdisc.c:134
static int peerdisc_discovered(struct peerdisc_segment *segment, struct peerdist_retrieval *retrieval, const char *location)
Add discovered PeerDist peer.
Definition peerdisc.c:393
static void peerdisc_expired(struct retry_timer *timer, int over __unused)
Handle discovery timer expiry.
Definition peerdisc.c:445
#define PEERDISC_REPEAT_COUNT
Number of repeated discovery attempts.
Definition peerdisc.c:56
static void peerdisc_socket_close(int rc)
Close all PeerDist discovery sockets.
Definition peerdisc.c:296
static char * peerdisc_recent
Most recently discovered peer (for any block).
Definition peerdisc.c:79
static void peerdisc_free(struct refcnt *refcnt)
Free PeerDist discovery segment.
Definition peerdisc.c:351
static struct interface_descriptor peerdisc_socket_desc
PeerDist discovery socket interface descriptor.
Definition peerdisc.c:310
#define PEERDISC_REPEAT_TIMEOUT
Time between repeated discovery attempts.
Definition peerdisc.c:59
#define PEERDISC_DEFAULT_TIMEOUT_SECS
Default discovery timeout (in seconds).
Definition peerdisc.c:62
Peer Content Caching and Retrieval (PeerDist) protocol peer discovery.
#define PEERDISC_SOCKETS
PeerDist discovery socket table.
Definition peerdisc.h:37
#define __peerdisc_socket
Declare a PeerDist discovery socket.
Definition peerdisc.h:40
#define peerdisc_stat_TYPE(object_type)
Definition peerdisc.h:117
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition random.c:32
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_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
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition retry.h:100
int fetch_string_setting_copy(struct settings *settings, const struct setting *setting, char **data)
Fetch value of string setting.
Definition settings.c:874
unsigned long int dword
Definition smc9000.h:40
#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 strcmp(const char *first, const char *second)
Compare strings.
Definition string.c:174
char * strdup(const char *src)
Duplicate string.
Definition string.c:425
char * strcpy(char *dest, const char *src)
Copy string.
Definition string.c:378
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
An object interface descriptor.
Definition interface.h:56
An object interface operation.
Definition interface.h:18
An object interface.
Definition interface.h:125
struct interface * intf
Original interface.
Definition interface.h:159
A persistent I/O buffer.
Definition iobuf.h:98
void * data
Start of data.
Definition iobuf.h:113
A doubly-linked list entry (or list head).
Definition list.h:19
A network device.
Definition netdevice.h:353
void(* discovered)(struct peerdisc_client *peerdisc)
New peers have been discovered.
Definition peerdisc.h:97
A PeerDist discovery client.
Definition peerdisc.h:82
struct list_head list
List of clients.
Definition peerdisc.h:86
struct peerdisc_segment * segment
Discovery segment.
Definition peerdisc.h:84
struct peerdisc_client_operations * op
Operations.
Definition peerdisc.h:88
A PeerDist discovery peer.
Definition peerdisc.h:72
struct list_head list
List of peers.
Definition peerdisc.h:74
A PeerDist discovery segment.
Definition peerdisc.h:43
struct list_head list
List of segments.
Definition peerdisc.h:47
struct list_head peers
List of discovered peers.
Definition peerdisc.h:64
A PeerDist discovery socket.
Definition peerdisc.h:23
struct sockaddr sa
Definition peerdisc.h:30
const char * name
Name.
Definition peerdisc.h:25
struct interface xfer
Data transfer interface.
Definition peerdisc.h:27
union peerdisc_socket::@135052057250103003165261220231164357172243045304 address
Socket address.
A PeerDist discovery reply.
Definition pccrd.h:32
char * ids
List of segment ID strings.
Definition pccrd.h:37
char * locations
List of peer locations.
Definition pccrd.h:42
A retrieval protocol mechanism.
Definition pccrr.h:356
A reference counter.
Definition refcnt.h:27
A retry timer.
Definition retry.h:22
A setting.
Definition settings.h:24
A settings applicator.
Definition settings.h:252
TCP/IP socket address.
Definition tcpip.h:76
Generalized socket address structure.
Definition socket.h:97
A timer.
Definition timer.h:29
Data transfer metadata.
Definition xfer.h:23
struct sockaddr_tcpip st
Definition syslog.c:58
struct sockaddr sa
Definition syslog.c:57
#define for_each_table_entry_continue_reverse(pointer, table)
Iterate through all remaining entries within a linker table in reverse order.
Definition tables.h:470
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386
A universally unique ID.
Definition uuid.h:16
const char * uuid_ntoa(const union uuid *uuid)
Convert UUID to printable string.
Definition uuid.c:46
Universally unique IDs.
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195
int xfer_deliver_raw_meta(struct interface *intf, const void *data, size_t len, struct xfer_metadata *meta)
Deliver datagram as raw data.
Definition xfer.c:269
Data transfer interfaces.