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/pccrd.h>
43#include <ipxe/peerdisc.h>
44
45/** @file
46 *
47 * Peer Content Caching and Retrieval (PeerDist) protocol peer discovery
48 *
49 */
50
51/** List of discovery segments */
52static LIST_HEAD ( peerdisc_segments );
53
54/** Number of repeated discovery attempts */
55#define PEERDISC_REPEAT_COUNT 2
56
57/** Time between repeated discovery attempts */
58#define PEERDISC_REPEAT_TIMEOUT ( 1 * TICKS_PER_SEC )
59
60/** Default discovery timeout (in seconds) */
61#define PEERDISC_DEFAULT_TIMEOUT_SECS 2
62
63/** Recommended discovery timeout (in seconds)
64 *
65 * We reduce the recommended discovery timeout whenever a segment
66 * fails to discover any peers, and restore the default value whenever
67 * a valid discovery reply is received. We continue to send discovery
68 * requests even if the recommended timeout is reduced to zero.
69 *
70 * This strategy is intended to minimise discovery delays when no
71 * peers are available on the network, while allowing downloads to
72 * quickly switch back to using PeerDist acceleration if new peers
73 * become available.
74 */
76
77/** Most recently discovered peer (for any block) */
78static char *peerdisc_recent;
79
80/** Hosted cache server */
81static char *peerhost;
82
83static struct peerdisc_segment * peerdisc_find ( const char *id );
85 const char *location );
86
87/******************************************************************************
88 *
89 * Statistics reporting
90 *
91 ******************************************************************************
92 */
93
94/**
95 * Report peer discovery statistics
96 *
97 * @v intf Interface
98 * @v peer Selected peer (or NULL)
99 * @v peers List of available peers
100 */
101void peerdisc_stat ( struct interface *intf, struct peerdisc_peer *peer,
102 struct list_head *peers ) {
103 struct interface *dest;
104 peerdisc_stat_TYPE ( void * ) *op =
106 void *object = intf_object ( dest );
107
108 if ( op ) {
109 op ( object, peer, peers );
110 } else {
111 /* Default is to do nothing */
112 }
113
114 intf_put ( dest );
115}
116
117/******************************************************************************
118 *
119 * Discovery sockets
120 *
121 ******************************************************************************
122 */
123
124/**
125 * Open all PeerDist discovery sockets
126 *
127 * @ret rc Return status code
128 */
129static int peerdisc_socket_open ( void ) {
130 struct peerdisc_socket *socket;
131 int rc;
132
133 /* Open each socket */
135 if ( ( rc = xfer_open_socket ( &socket->xfer, SOCK_DGRAM,
136 &socket->address.sa,
137 NULL ) ) != 0 ) {
138 DBGC ( socket, "PEERDISC %s could not open socket: "
139 "%s\n", socket->name, strerror ( rc ) );
140 goto err;
141 }
142 }
143
144 return 0;
145
146 err:
148 intf_restart ( &socket->xfer, rc );
149 return rc;
150}
151
152/**
153 * Attempt to transmit PeerDist discovery requests on all sockets
154 *
155 * @v uuid Message UUID string
156 * @v id Segment identifier string
157 */
158static void peerdisc_socket_tx ( const char *uuid, const char *id ) {
159 struct peerdisc_socket *socket;
160 struct net_device *netdev;
161 struct xfer_metadata meta;
162 union {
163 struct sockaddr sa;
164 struct sockaddr_tcpip st;
165 } address;
166 char *request;
167 size_t len;
168 int rc;
169
170 /* Construct discovery request */
172 if ( ! request )
173 goto err_request;
174 len = strlen ( request );
175
176 /* Initialise data transfer metadata */
177 memset ( &meta, 0, sizeof ( meta ) );
178 meta.dest = &address.sa;
179
180 /* Send message on each socket */
182
183 /* Initialise socket address */
184 memcpy ( &address.sa, &socket->address.sa,
185 sizeof ( address.sa ) );
186
187 /* Send message on each open network device */
189
190 /* Skip unopened network devices */
191 if ( ! netdev_is_open ( netdev ) )
192 continue;
193 address.st.st_scope_id = netdev->scope_id;
194
195 /* Discard request (for test purposes) if applicable */
196 if ( inject_fault ( PEERDISC_DISCARD_RATE ) )
197 continue;
198
199 /* Transmit request */
200 if ( ( rc = xfer_deliver_raw_meta ( &socket->xfer,
201 request, len,
202 &meta ) ) != 0 ) {
203 DBGC ( socket, "PEERDISC %s could not transmit "
204 "via %s: %s\n", socket->name,
205 netdev->name, strerror ( rc ) );
206 /* Contine to try other net devices/sockets */
207 continue;
208 }
209 }
210 }
211
212 free ( request );
213 err_request:
214 return;
215}
216
217/**
218 * Handle received PeerDist discovery reply
219 *
220 * @v socket PeerDist discovery socket
221 * @v iobuf I/O buffer
222 * @v meta Data transfer metadata
223 * @ret rc Return status code
224 */
225static int peerdisc_socket_rx ( struct peerdisc_socket *socket,
226 struct io_buffer *iobuf,
227 struct xfer_metadata *meta __unused ) {
228 struct peerdist_discovery_reply reply;
230 char *id;
231 char *location;
232 int rc;
233
234 /* Discard reply (for test purposes) if applicable */
235 if ( ( rc = inject_fault ( PEERDISC_DISCARD_RATE ) ) != 0 )
236 goto err;
237
238 /* Parse reply */
239 if ( ( rc = peerdist_discovery_reply ( iobuf->data, iob_len ( iobuf ),
240 &reply ) ) != 0 ) {
241 DBGC ( socket, "PEERDISC %s could not parse reply: %s\n",
242 socket->name, strerror ( rc ) );
243 DBGC_HDA ( socket, 0, iobuf->data, iob_len ( iobuf ) );
244 goto err;
245 }
246
247 /* Any kind of discovery reply indicates that there are active
248 * peers on a local network, so restore the recommended
249 * discovery timeout to its default value for future requests.
250 */
252 DBGC ( socket, "PEERDISC %s restoring timeout to %d seconds\n",
254 }
256
257 /* Iterate over segment IDs */
258 for ( id = reply.ids ; *id ; id += ( strlen ( id ) + 1 /* NUL */ ) ) {
259
260 /* Find corresponding segment */
261 segment = peerdisc_find ( id );
262 if ( ! segment ) {
263 DBGC ( socket, "PEERDISC %s ignoring reply for %s\n",
264 socket->name, id );
265 continue;
266 }
267
268 /* Report all discovered peer locations */
269 for ( location = reply.locations ; *location ;
270 location += ( strlen ( location ) + 1 /* NUL */ ) ) {
271
272 /* Report discovered peer location */
273 if ( ( rc = peerdisc_discovered ( segment,
274 location ) ) != 0 )
275 goto err;
276 }
277 }
278
279 err:
280 free_iob ( iobuf );
281 return rc;
282}
283
284/**
285 * Close all PeerDist discovery sockets
286 *
287 * @v rc Reason for close
288 */
289static void peerdisc_socket_close ( int rc ) {
290 struct peerdisc_socket *socket;
291
292 /* Close all sockets */
294 intf_restart ( &socket->xfer, rc );
295}
296
297/** PeerDist discovery socket interface operations */
301
302/** PeerDist discovery socket interface descriptor */
305
306/** PeerDist discovery IPv4 socket */
307struct peerdisc_socket peerdisc_socket_ipv4 __peerdisc_socket = {
308 .name = "IPv4",
309 .address = {
310 .sin = {
311 .sin_family = AF_INET,
312 .sin_port = htons ( PEERDIST_DISCOVERY_PORT ),
313 .sin_addr.s_addr = htonl ( PEERDIST_DISCOVERY_IPV4 ),
314 },
315 },
317};
318
319/** PeerDist discovery IPv6 socket */
320struct peerdisc_socket peerdisc_socket_ipv6 __peerdisc_socket = {
321 .name = "IPv6",
322 .address = {
323 .sin6 = {
324 .sin6_family = AF_INET6,
325 .sin6_port = htons ( PEERDIST_DISCOVERY_PORT ),
326 .sin6_addr.s6_addr = PEERDIST_DISCOVERY_IPV6,
327 },
328 },
330};
331
332/******************************************************************************
333 *
334 * Discovery segments
335 *
336 ******************************************************************************
337 */
338
339/**
340 * Free PeerDist discovery segment
341 *
342 * @v refcnt Reference count
343 */
344static void peerdisc_free ( struct refcnt *refcnt ) {
345 struct peerdisc_segment *segment =
347 struct peerdisc_peer *peer;
348 struct peerdisc_peer *tmp;
349
350 /* Free all discovered peers */
352 list_del ( &peer->list );
353 free ( peer );
354 }
355
356 /* Free segment */
357 free ( segment );
358}
359
360/**
361 * Find PeerDist discovery segment
362 *
363 * @v id Segment ID
364 * @ret segment PeerDist discovery segment, or NULL if not found
365 */
366static struct peerdisc_segment * peerdisc_find ( const char *id ) {
368
369 /* Look for a matching segment */
370 list_for_each_entry ( segment, &peerdisc_segments, list ) {
371 if ( strcmp ( id, segment->id ) == 0 )
372 return segment;
373 }
374
375 return NULL;
376}
377
378/**
379 * Add discovered PeerDist peer
380 *
381 * @v segment PeerDist discovery segment
382 * @v location Peer location
383 * @ret rc Return status code
384 */
386 const char *location ) {
387 struct peerdisc_peer *peer;
388 struct peerdisc_client *peerdisc;
389 struct peerdisc_client *tmp;
390 char *recent;
391
392 /* Ignore duplicate peers */
393 list_for_each_entry ( peer, &segment->peers, list ) {
394 if ( strcmp ( peer->location, location ) == 0 ) {
395 DBGC2 ( segment, "PEERDISC %p duplicate %s\n",
396 segment, location );
397 return 0;
398 }
399 }
400 DBGC2 ( segment, "PEERDISC %p discovered %s\n", segment, location );
401
402 /* Allocate and initialise structure */
403 peer = zalloc ( sizeof ( *peer ) + strlen ( location ) + 1 /* NUL */ );
404 if ( ! peer )
405 return -ENOMEM;
406 strcpy ( peer->location, location );
407
408 /* Add to end of list of peers */
409 list_add_tail ( &peer->list, &segment->peers );
410
411 /* Record as most recently discovered peer */
412 if ( location != peerdisc_recent ) {
413 recent = strdup ( location );
414 if ( recent ) {
416 peerdisc_recent = recent;
417 }
418 }
419
420 /* Notify all clients */
421 list_for_each_entry_safe ( peerdisc, tmp, &segment->clients, list )
422 peerdisc->op->discovered ( peerdisc );
423
424 return 0;
425}
426
427/**
428 * Handle discovery timer expiry
429 *
430 * @v timer Discovery timer
431 * @v over Failure indicator
432 */
433static void peerdisc_expired ( struct retry_timer *timer, int over __unused ) {
434 struct peerdisc_segment *segment =
436
437 /* Attempt to transmit discovery requests */
438 peerdisc_socket_tx ( segment->uuid, segment->id );
439
440 /* Schedule next transmission, if applicable */
441 if ( timer->count < PEERDISC_REPEAT_COUNT )
443}
444
445/**
446 * Create PeerDist discovery segment
447 *
448 * @v id Segment ID
449 * @ret segment PeerDist discovery segment, or NULL on error
450 */
451static struct peerdisc_segment * peerdisc_create ( const char *id ) {
453 union {
454 union uuid uuid;
455 uint32_t dword[ sizeof ( union uuid ) / sizeof ( uint32_t ) ];
456 } random_uuid;
457 size_t uuid_len;
458 size_t id_len;
459 const char *uuid;
460 char *uuid_copy;
461 char *id_copy;
462 unsigned int i;
463 int rc;
464
465 /* Generate a random message UUID. This does not require high
466 * quality randomness.
467 */
468 for ( i = 0 ; i < ( sizeof ( random_uuid.dword ) /
469 sizeof ( random_uuid.dword[0] ) ) ; i++ )
470 random_uuid.dword[i] = random();
471 uuid = uuid_ntoa ( &random_uuid.uuid );
472
473 /* Calculate string lengths */
474 id_len = ( strlen ( id ) + 1 /* NUL */ );
475 uuid_len = ( strlen ( uuid ) + 1 /* NUL */ );
476
477 /* Allocate and initialise structure */
478 segment = zalloc ( sizeof ( *segment ) + id_len + uuid_len );
479 if ( ! segment )
480 goto err_alloc;
481 id_copy = ( ( ( void * ) segment ) + sizeof ( *segment ) );
482 memcpy ( id_copy, id, id_len );
483 uuid_copy = ( ( ( void * ) id_copy ) + id_len );
484 memcpy ( uuid_copy, uuid, uuid_len );
485 ref_init ( &segment->refcnt, peerdisc_free );
486 segment->id = id_copy;
487 segment->uuid = uuid_copy;
488 INIT_LIST_HEAD ( &segment->peers );
489 INIT_LIST_HEAD ( &segment->clients );
490 timer_init ( &segment->timer, peerdisc_expired, &segment->refcnt );
491
492 /* Add hosted cache server or initiate discovery */
493 if ( peerhost ) {
494
495 /* Add hosted cache server to list of peers */
496 if ( ( rc = peerdisc_discovered ( segment, peerhost ) ) != 0 )
497 goto err_peerhost;
498
499 } else {
500
501 /* Add most recently discovered peer to list of peers
502 *
503 * This is a performance optimisation: we assume that
504 * the most recently discovered peer for any block has
505 * a high probability of also having a copy of the
506 * next block that we attempt to discover.
507 */
508 if ( peerdisc_recent )
510
511 /* Start discovery timer */
512 start_timer_nodelay ( &segment->timer );
513 DBGC2 ( segment, "PEERDISC %p discovering %s\n",
514 segment, segment->id );
515 }
516
517 /* Add to list of segments, transfer reference to list, and return */
518 list_add_tail ( &segment->list, &peerdisc_segments );
519 return segment;
520
521 err_peerhost:
522 ref_put ( &segment->refcnt );
523 err_alloc:
524 return NULL;
525}
526
527/**
528 * Destroy PeerDist discovery segment
529 *
530 * @v segment PeerDist discovery segment
531 */
533
534 /* Sanity check */
535 assert ( list_empty ( &segment->clients ) );
536
537 /* Stop timer */
538 stop_timer ( &segment->timer );
539
540 /* Remove from list of segments and drop list's reference */
541 list_del ( &segment->list );
542 ref_put ( &segment->refcnt );
543}
544
545/******************************************************************************
546 *
547 * Discovery clients
548 *
549 ******************************************************************************
550 */
551
552/**
553 * Open PeerDist discovery client
554 *
555 * @v peerdisc PeerDist discovery client
556 * @v id Segment ID
557 * @v len Length of segment ID
558 * @ret rc Return status code
559 */
560int peerdisc_open ( struct peerdisc_client *peerdisc, const void *id,
561 size_t len ) {
563 char id_string[ base16_encoded_len ( len ) + 1 /* NUL */ ];
564 char *id_chr;
565 int rc;
566
567 /* Construct ID string */
568 base16_encode ( id, len, id_string, sizeof ( id_string ) );
569 for ( id_chr = id_string ; *id_chr ; id_chr++ )
570 *id_chr = toupper ( *id_chr );
571
572 /* Sanity check */
573 assert ( peerdisc->segment == NULL );
574
575 /* Open socket if this is the first segment */
576 if ( list_empty ( &peerdisc_segments ) &&
577 ( ( rc = peerdisc_socket_open() ) != 0 ) )
578 return rc;
579
580 /* Find or create segment */
581 if ( ! ( ( segment = peerdisc_find ( id_string ) ) ||
582 ( segment = peerdisc_create ( id_string ) ) ) )
583 return -ENOMEM;
584
585 /* Add to list of clients */
586 ref_get ( &segment->refcnt );
587 peerdisc->segment = segment;
588 list_add_tail ( &peerdisc->list, &segment->clients );
589
590 return 0;
591}
592
593/**
594 * Close PeerDist discovery client
595 *
596 * @v peerdisc PeerDist discovery client
597 */
598void peerdisc_close ( struct peerdisc_client *peerdisc ) {
599 struct peerdisc_segment *segment = peerdisc->segment;
600
601 /* Ignore if discovery is already closed */
602 if ( ! segment )
603 return;
604
605 /* If no peers were discovered, reduce the recommended
606 * discovery timeout to minimise delays on future requests.
607 */
608 if ( list_empty ( &segment->peers ) && peerdisc_timeout_secs ) {
610 DBGC ( segment, "PEERDISC %p reducing timeout to %d "
611 "seconds\n", peerdisc, peerdisc_timeout_secs );
612 }
613
614 /* Remove from list of clients */
615 peerdisc->segment = NULL;
616 list_del ( &peerdisc->list );
617 ref_put ( &segment->refcnt );
618
619 /* If this was the last clients, destroy the segment */
620 if ( list_empty ( &segment->clients ) )
622
623 /* If there are no more segments, close the socket */
624 if ( list_empty ( &peerdisc_segments ) )
626}
627
628/******************************************************************************
629 *
630 * Settings
631 *
632 ******************************************************************************
633 */
634
635/** PeerDist hosted cache server setting */
636const struct setting peerhost_setting __setting ( SETTING_MISC, peerhost ) = {
637 .name = "peerhost",
638 .description = "PeerDist hosted cache",
639 .type = &setting_type_string,
640};
641
642/**
643 * Apply PeerDist discovery settings
644 *
645 * @ret rc Return status code
646 */
647static int apply_peerdisc_settings ( void ) {
648
649 /* Free any existing hosted cache server */
650 free ( peerhost );
651 peerhost = NULL;
652
653 /* Fetch hosted cache server */
654 fetch_string_setting_copy ( NULL, &peerhost_setting, &peerhost );
655 if ( peerhost ) {
656 DBGC ( &peerhost, "PEERDISC using hosted cache %s\n",
657 peerhost );
658 }
659
660 return 0;
661}
662
663/** PeerDist discovery settings applicator */
664struct settings_applicator peerdisc_applicator __settings_applicator = {
666};
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
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:50
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:573
#define SOCK_DGRAM
Definition socket.h:30
#define DBGC2(...)
Definition compiler.h:522
#define DBGC(...)
Definition compiler.h:505
#define DBGC_HDA(...)
Definition compiler.h:506
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOMEM
Not enough space.
Definition errno.h:535
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define SETTING_MISC
Miscellaneous settings.
Definition settings.h:81
u8 request[0]
List of IEs requested.
Definition ieee80211.h:2
#define htonl(value)
Definition byteswap.h:134
#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:160
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:662
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:547
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition netdevice.h:662
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:143
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:21
#define PEERDIST_DISCOVERY_PORT
PeerDist discovery port.
Definition pccrd.h:14
#define PEERDIST_DISCOVERY_IPV4
PeerDist discovery IPv4 address (239.255.255.250)
Definition pccrd.h:17
static char * peerhost
Hosted cache server.
Definition peerdisc.c:81
static struct peerdisc_segment * peerdisc_find(const char *id)
Find PeerDist discovery segment.
Definition peerdisc.c:366
static struct peerdisc_segment * peerdisc_create(const char *id)
Create PeerDist discovery segment.
Definition peerdisc.c:451
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:225
void peerdisc_stat(struct interface *intf, struct peerdisc_peer *peer, struct list_head *peers)
Report peer discovery statistics.
Definition peerdisc.c:101
int peerdisc_open(struct peerdisc_client *peerdisc, const void *id, size_t len)
Open PeerDist discovery client.
Definition peerdisc.c:560
void peerdisc_close(struct peerdisc_client *peerdisc)
Close PeerDist discovery client.
Definition peerdisc.c:598
static struct interface_operation peerdisc_socket_operations[]
PeerDist discovery socket interface operations.
Definition peerdisc.c:298
unsigned int peerdisc_timeout_secs
Recommended discovery timeout (in seconds)
Definition peerdisc.c:75
static int apply_peerdisc_settings(void)
Apply PeerDist discovery settings.
Definition peerdisc.c:647
static void peerdisc_destroy(struct peerdisc_segment *segment)
Destroy PeerDist discovery segment.
Definition peerdisc.c:532
static void peerdisc_socket_tx(const char *uuid, const char *id)
Attempt to transmit PeerDist discovery requests on all sockets.
Definition peerdisc.c:158
static int peerdisc_socket_open(void)
Open all PeerDist discovery sockets.
Definition peerdisc.c:129
static void peerdisc_expired(struct retry_timer *timer, int over __unused)
Handle discovery timer expiry.
Definition peerdisc.c:433
#define PEERDISC_REPEAT_COUNT
Number of repeated discovery attempts.
Definition peerdisc.c:55
static void peerdisc_socket_close(int rc)
Close all PeerDist discovery sockets.
Definition peerdisc.c:289
static char * peerdisc_recent
Most recently discovered peer (for any block)
Definition peerdisc.c:78
static void peerdisc_free(struct refcnt *refcnt)
Free PeerDist discovery segment.
Definition peerdisc.c:344
static struct interface_descriptor peerdisc_socket_desc
PeerDist discovery socket interface descriptor.
Definition peerdisc.c:303
static int peerdisc_discovered(struct peerdisc_segment *segment, const char *location)
Add discovered PeerDist peer.
Definition peerdisc.c:385
#define PEERDISC_REPEAT_TIMEOUT
Time between repeated discovery attempts.
Definition peerdisc.c:58
#define PEERDISC_DEFAULT_TIMEOUT_SECS
Default discovery timeout (in seconds)
Definition peerdisc.c:61
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:115
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:394
char * strcpy(char *dest, const char *src)
Copy string.
Definition string.c:347
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:38
void * data
Start of data.
Definition iobuf.h:53
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:95
A PeerDist discovery client.
Definition peerdisc.h:80
struct list_head list
List of clients.
Definition peerdisc.h:84
struct peerdisc_segment * segment
Discovery segment.
Definition peerdisc.h:82
struct peerdisc_client_operations * op
Operations.
Definition peerdisc.h:86
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:31
char * ids
List of segment ID strings.
Definition pccrd.h:36
char * locations
List of peer locations.
Definition pccrd.h:41
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.