iPXE
peerdisc.c File Reference

Peer Content Caching and Retrieval (PeerDist) protocol peer discovery. More...

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <assert.h>
#include <ipxe/xfer.h>
#include <ipxe/iobuf.h>
#include <ipxe/open.h>
#include <ipxe/tcpip.h>
#include <ipxe/uuid.h>
#include <ipxe/base16.h>
#include <ipxe/netdevice.h>
#include <ipxe/timer.h>
#include <ipxe/fault.h>
#include <ipxe/settings.h>
#include <ipxe/pccrd.h>
#include <ipxe/peerdisc.h>

Go to the source code of this file.

Macros

#define PEERDISC_REPEAT_COUNT   2
 Number of repeated discovery attempts.
#define PEERDISC_REPEAT_TIMEOUT   ( 1 * TICKS_PER_SEC )
 Time between repeated discovery attempts.
#define PEERDISC_DEFAULT_TIMEOUT_SECS   2
 Default discovery timeout (in seconds)

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static LIST_HEAD (peerdisc_segments)
 List of discovery segments.
static struct peerdisc_segmentpeerdisc_find (const char *id)
 Find PeerDist discovery segment.
static int peerdisc_discovered (struct peerdisc_segment *segment, const char *location)
 Add discovered PeerDist peer.
void peerdisc_stat (struct interface *intf, struct peerdisc_peer *peer, struct list_head *peers)
 Report peer discovery statistics.
static int peerdisc_socket_open (void)
 Open all PeerDist discovery sockets.
static void peerdisc_socket_tx (const char *uuid, const char *id)
 Attempt to transmit PeerDist discovery requests on all sockets.
static int peerdisc_socket_rx (struct peerdisc_socket *socket, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
 Handle received PeerDist discovery reply.
static void peerdisc_socket_close (int rc)
 Close all PeerDist discovery sockets.
static void peerdisc_free (struct refcnt *refcnt)
 Free PeerDist discovery segment.
static void peerdisc_expired (struct retry_timer *timer, int over __unused)
 Handle discovery timer expiry.
static struct peerdisc_segmentpeerdisc_create (const char *id)
 Create PeerDist discovery segment.
static void peerdisc_destroy (struct peerdisc_segment *segment)
 Destroy PeerDist discovery segment.
int peerdisc_open (struct peerdisc_client *peerdisc, const void *id, size_t len)
 Open PeerDist discovery client.
void peerdisc_close (struct peerdisc_client *peerdisc)
 Close PeerDist discovery client.
const struct setting peerhost_setting __setting (SETTING_MISC, peerhost)
 PeerDist hosted cache server setting.
static int apply_peerdisc_settings (void)
 Apply PeerDist discovery settings.

Variables

unsigned int peerdisc_timeout_secs = PEERDISC_DEFAULT_TIMEOUT_SECS
 Recommended discovery timeout (in seconds)
static char * peerdisc_recent
 Most recently discovered peer (for any block)
static char * peerhost
 Hosted cache server.
static struct interface_operation peerdisc_socket_operations []
 PeerDist discovery socket interface operations.
static struct interface_descriptor peerdisc_socket_desc
 PeerDist discovery socket interface descriptor.
struct peerdisc_socket peerdisc_socket_ipv4 __peerdisc_socket
 PeerDist discovery IPv4 socket.
struct settings_applicator peerdisc_applicator __settings_applicator
 PeerDist discovery settings applicator.

Detailed Description

Peer Content Caching and Retrieval (PeerDist) protocol peer discovery.

Definition in file peerdisc.c.

Macro Definition Documentation

◆ PEERDISC_REPEAT_COUNT

#define PEERDISC_REPEAT_COUNT   2

Number of repeated discovery attempts.

Definition at line 55 of file peerdisc.c.

Referenced by peerdisc_expired().

◆ PEERDISC_REPEAT_TIMEOUT

#define PEERDISC_REPEAT_TIMEOUT   ( 1 * TICKS_PER_SEC )

Time between repeated discovery attempts.

Definition at line 58 of file peerdisc.c.

Referenced by peerdisc_expired().

◆ PEERDISC_DEFAULT_TIMEOUT_SECS

#define PEERDISC_DEFAULT_TIMEOUT_SECS   2

Default discovery timeout (in seconds)

Definition at line 61 of file peerdisc.c.

Referenced by peerdisc_socket_rx().

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ LIST_HEAD()

LIST_HEAD ( peerdisc_segments )
static

List of discovery segments.

◆ peerdisc_find()

struct peerdisc_segment * peerdisc_find ( const char * id)
static

Find PeerDist discovery segment.

Parameters
idSegment ID
Return values
segmentPeerDist discovery segment, or NULL if not found

Definition at line 366 of file peerdisc.c.

366 {
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}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
uint16_t segment
Code segment.
Definition librm.h:3
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
int strcmp(const char *first, const char *second)
Compare strings.
Definition string.c:174
A PeerDist discovery segment.
Definition peerdisc.h:43
struct list_head list
List of segments.
Definition peerdisc.h:47

References peerdisc_segment::list, list_for_each_entry, NULL, segment, and strcmp().

Referenced by peerdisc_open(), and peerdisc_socket_rx().

◆ peerdisc_discovered()

int peerdisc_discovered ( struct peerdisc_segment * segment,
const char * location )
static

Add discovered PeerDist peer.

Parameters
segmentPeerDist discovery segment
locationPeer location
Return values
rcReturn status code

Definition at line 385 of file peerdisc.c.

386 {
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}
#define DBGC2(...)
Definition compiler.h:522
#define ENOMEM
Not enough space.
Definition errno.h:535
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
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
struct mschapv2_challenge peer
Peer challenge.
Definition mschapv2.h:1
static char * peerdisc_recent
Most recently discovered peer (for any block)
Definition peerdisc.c:78
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
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
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_client_operations * op
Operations.
Definition peerdisc.h:86
A PeerDist discovery peer.
Definition peerdisc.h:72

References DBGC2, peerdisc_client_operations::discovered, ENOMEM, free, peerdisc_client::list, list_add_tail, list_for_each_entry, list_for_each_entry_safe, peerdisc_client::op, peer, peerdisc_recent, segment, strcmp(), strcpy(), strdup(), strlen(), tmp, and zalloc().

Referenced by peerdisc_create(), and peerdisc_socket_rx().

◆ peerdisc_stat()

void peerdisc_stat ( struct interface * intf,
struct peerdisc_peer * peer,
struct list_head * peers )

Report peer discovery statistics.

Parameters
intfInterface
peerSelected peer (or NULL)
peersList of available peers

Definition at line 101 of file peerdisc.c.

102 {
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}
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
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
#define intf_get_dest_op(intf, type, dest)
Get object interface destination and operation method.
Definition interface.h:270
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
void peerdisc_stat(struct interface *intf, struct peerdisc_peer *peer, struct list_head *peers)
Report peer discovery statistics.
Definition peerdisc.c:101
#define peerdisc_stat_TYPE(object_type)
Definition peerdisc.h:115
An object interface.
Definition interface.h:125
struct interface * intf
Original interface.
Definition interface.h:159

References dest, interface::intf, intf_get_dest_op, intf_object(), intf_put(), op, peer, peerdisc_stat(), and peerdisc_stat_TYPE.

Referenced by peerblk_done(), and peerdisc_stat().

◆ peerdisc_socket_open()

int peerdisc_socket_open ( void )
static

Open all PeerDist discovery sockets.

Return values
rcReturn status code

Definition at line 129 of file peerdisc.c.

129 {
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}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define SOCK_DGRAM
Definition socket.h:30
#define DBGC(...)
Definition compiler.h:505
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition interface.c:344
int xfer_open_socket(struct interface *intf, int semantics, struct sockaddr *peer, struct sockaddr *local)
Open socket.
Definition open.c:143
#define PEERDISC_SOCKETS
PeerDist discovery socket table.
Definition peerdisc.h:37
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
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.
#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

References peerdisc_socket::address, DBGC, for_each_table_entry, for_each_table_entry_continue_reverse, intf_restart(), peerdisc_socket::name, NULL, PEERDISC_SOCKETS, rc, peerdisc_socket::sa, SOCK_DGRAM, strerror(), peerdisc_socket::xfer, and xfer_open_socket().

Referenced by peerdisc_open().

◆ peerdisc_socket_tx()

void peerdisc_socket_tx ( const char * uuid,
const char * id )
static

Attempt to transmit PeerDist discovery requests on all sockets.

Parameters
uuidMessage UUID string
idSegment identifier string

Definition at line 158 of file peerdisc.c.

158 {
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}
#define PEERDISC_DISCARD_RATE
Definition fault.h:22
ring len
Length.
Definition dwmac.h:226
uint8_t meta
Metadata flags.
Definition ena.h:3
uint64_t address
Base address.
Definition ena.h:13
static struct net_device * netdev
Definition gdbudp.c:53
u8 request[0]
List of IEs requested.
Definition ieee80211.h:2
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
#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
char * peerdist_discovery_request(const char *uuid, const char *id)
Construct discovery request.
Definition pccrd.c:107
A network device.
Definition netdevice.h:353
Data transfer metadata.
Definition xfer.h:23
struct sockaddr_tcpip st
Definition syslog.c:58
struct sockaddr sa
Definition syslog.c:57
A universally unique ID.
Definition uuid.h:16
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

References address, peerdisc_socket::address, DBGC, for_each_netdev, for_each_table_entry, free, len, memcpy(), memset(), meta, peerdisc_socket::name, netdev, netdev_is_open(), PEERDISC_DISCARD_RATE, PEERDISC_SOCKETS, peerdist_discovery_request(), rc, request, peerdisc_socket::sa, sa, st, strerror(), strlen(), peerdisc_socket::xfer, and xfer_deliver_raw_meta().

Referenced by peerdisc_expired().

◆ peerdisc_socket_rx()

int peerdisc_socket_rx ( struct peerdisc_socket * socket,
struct io_buffer * iobuf,
struct xfer_metadata *meta __unused )
static

Handle received PeerDist discovery reply.

Parameters
socketPeerDist discovery socket
iobufI/O buffer
metaData transfer metadata
Return values
rcReturn status code

Definition at line 225 of file peerdisc.c.

227 {
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}
uint8_t id
Request identifier.
Definition ena.h:1
#define DBGC_HDA(...)
Definition compiler.h:506
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
static struct peerdisc_segment * peerdisc_find(const char *id)
Find PeerDist discovery segment.
Definition peerdisc.c:366
unsigned int peerdisc_timeout_secs
Recommended discovery timeout (in seconds)
Definition peerdisc.c:75
static int peerdisc_discovered(struct peerdisc_segment *segment, const char *location)
Add discovered PeerDist peer.
Definition peerdisc.c:385
#define PEERDISC_DEFAULT_TIMEOUT_SECS
Default discovery timeout (in seconds)
Definition peerdisc.c:61
void * data
Start of data.
Definition iobuf.h:53
A PeerDist discovery reply.
Definition pccrd.h:31

References __unused, io_buffer::data, DBGC, DBGC_HDA, free_iob(), id, peerdist_discovery_reply::ids, iob_len(), peerdist_discovery_reply::locations, meta, peerdisc_socket::name, PEERDISC_DEFAULT_TIMEOUT_SECS, PEERDISC_DISCARD_RATE, peerdisc_discovered(), peerdisc_find(), peerdisc_timeout_secs, rc, segment, strerror(), and strlen().

◆ peerdisc_socket_close()

void peerdisc_socket_close ( int rc)
static

Close all PeerDist discovery sockets.

Parameters
rcReason for close

Definition at line 289 of file peerdisc.c.

289 {
290 struct peerdisc_socket *socket;
291
292 /* Close all sockets */
294 intf_restart ( &socket->xfer, rc );
295}

References for_each_table_entry, intf_restart(), PEERDISC_SOCKETS, rc, and peerdisc_socket::xfer.

Referenced by peerdisc_close().

◆ peerdisc_free()

void peerdisc_free ( struct refcnt * refcnt)
static

Free PeerDist discovery segment.

Parameters
refcntReference count

Definition at line 344 of file peerdisc.c.

344 {
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}
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
struct list_head list
List of peers.
Definition peerdisc.h:74
A reference counter.
Definition refcnt.h:27

References container_of, free, peerdisc_peer::list, list_del, list_for_each_entry_safe, peer, segment, and tmp.

Referenced by peerdisc_create().

◆ peerdisc_expired()

void peerdisc_expired ( struct retry_timer * timer,
int over __unused )
static

Handle discovery timer expiry.

Parameters
timerDiscovery timer
overFailure indicator

Definition at line 433 of file peerdisc.c.

433 {
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}
static void peerdisc_socket_tx(const char *uuid, const char *id)
Attempt to transmit PeerDist discovery requests on all sockets.
Definition peerdisc.c:158
#define PEERDISC_REPEAT_COUNT
Number of repeated discovery attempts.
Definition peerdisc.c:55
#define PEERDISC_REPEAT_TIMEOUT
Time between repeated discovery attempts.
Definition peerdisc.c:58
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition retry.c:65
A timer.
Definition timer.h:29

References __unused, container_of, PEERDISC_REPEAT_COUNT, PEERDISC_REPEAT_TIMEOUT, peerdisc_socket_tx(), segment, and start_timer_fixed().

Referenced by peerdisc_create().

◆ peerdisc_create()

struct peerdisc_segment * peerdisc_create ( const char * id)
static

Create PeerDist discovery segment.

Parameters
idSegment ID
Return values
segmentPeerDist discovery segment, or NULL on error

Definition at line 451 of file peerdisc.c.

451 {
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}
unsigned int uint32_t
Definition stdint.h:12
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
static char * peerhost
Hosted cache server.
Definition peerdisc.c:81
static void peerdisc_expired(struct retry_timer *timer, int over __unused)
Handle discovery timer expiry.
Definition peerdisc.c:433
static void peerdisc_free(struct refcnt *refcnt)
Free PeerDist discovery segment.
Definition peerdisc.c:344
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition random.c:32
#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
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition retry.h:100
unsigned long int dword
Definition smc9000.h:40
const char * uuid
Message UUID string.
Definition peerdisc.h:55
const char * uuid_ntoa(const union uuid *uuid)
Convert UUID to printable string.
Definition uuid.c:46

References DBGC2, INIT_LIST_HEAD, list_add_tail, memcpy(), NULL, peerdisc_discovered(), peerdisc_expired(), peerdisc_free(), peerdisc_recent, peerhost, random(), rc, ref_init, ref_put, segment, start_timer_nodelay(), strlen(), uuid_ntoa(), and zalloc().

Referenced by peerdisc_open().

◆ peerdisc_destroy()

void peerdisc_destroy ( struct peerdisc_segment * segment)
static

Destroy PeerDist discovery segment.

Parameters
segmentPeerDist discovery segment

Definition at line 532 of file peerdisc.c.

532 {
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}
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
#define list_empty(list)
Test whether a list is empty.
Definition list.h:137
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition retry.c:118

References assert, list_del, list_empty, ref_put, segment, and stop_timer().

Referenced by peerdisc_close().

◆ peerdisc_open()

int peerdisc_open ( struct peerdisc_client * peerdisc,
const void * id,
size_t len )

Open PeerDist discovery client.

Parameters
peerdiscPeerDist discovery client
idSegment ID
lenLength of segment ID
Return values
rcReturn status code

Definition at line 560 of file peerdisc.c.

561 {
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}
static size_t base16_encoded_len(size_t raw_len)
Calculate length of base16-encoded data.
Definition base16.h:25
static int toupper(int character)
Convert character to upper case.
Definition ctype.h:121
uint8_t id_string[24]
ID string.
Definition eltorito.h:12
static struct peerdisc_segment * peerdisc_create(const char *id)
Create PeerDist discovery segment.
Definition peerdisc.c:451
static int peerdisc_socket_open(void)
Open all PeerDist discovery sockets.
Definition peerdisc.c:129
#define ref_get(refcnt)
Get additional reference to object.
Definition refcnt.h:93
struct peerdisc_segment * segment
Discovery segment.
Definition peerdisc.h:82

References assert, base16_encoded_len(), ENOMEM, id_string, len, peerdisc_client::list, list_add_tail, list_empty, NULL, peerdisc_create(), peerdisc_find(), peerdisc_socket_open(), rc, ref_get, peerdisc_client::segment, segment, and toupper().

Referenced by peerblk_open().

◆ peerdisc_close()

void peerdisc_close ( struct peerdisc_client * peerdisc)

Close PeerDist discovery client.

Parameters
peerdiscPeerDist discovery client

Definition at line 598 of file peerdisc.c.

598 {
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}
static void peerdisc_destroy(struct peerdisc_segment *segment)
Destroy PeerDist discovery segment.
Definition peerdisc.c:532
static void peerdisc_socket_close(int rc)
Close all PeerDist discovery sockets.
Definition peerdisc.c:289

References DBGC, peerdisc_client::list, list_del, list_empty, NULL, peerdisc_destroy(), peerdisc_socket_close(), peerdisc_timeout_secs, ref_put, peerdisc_client::segment, and segment.

Referenced by peerblk_close().

◆ __setting()

const struct setting peerhost_setting __setting ( SETTING_MISC ,
peerhost  )

PeerDist hosted cache server setting.

References __setting, peerhost, and SETTING_MISC.

◆ apply_peerdisc_settings()

int apply_peerdisc_settings ( void )
static

Apply PeerDist discovery settings.

Return values
rcReturn status code

Definition at line 647 of file peerdisc.c.

647 {
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}
int fetch_string_setting_copy(struct settings *settings, const struct setting *setting, char **data)
Fetch value of string setting.
Definition settings.c:874

References DBGC, fetch_string_setting_copy(), free, NULL, and peerhost.

Variable Documentation

◆ peerdisc_timeout_secs

unsigned int peerdisc_timeout_secs = PEERDISC_DEFAULT_TIMEOUT_SECS

Recommended discovery timeout (in seconds)

We reduce the recommended discovery timeout whenever a segment fails to discover any peers, and restore the default value whenever a valid discovery reply is received. We continue to send discovery requests even if the recommended timeout is reduced to zero.

This strategy is intended to minimise discovery delays when no peers are available on the network, while allowing downloads to quickly switch back to using PeerDist acceleration if new peers become available.

Definition at line 75 of file peerdisc.c.

Referenced by peerblk_open(), peerdisc_close(), and peerdisc_socket_rx().

◆ peerdisc_recent

char* peerdisc_recent
static

Most recently discovered peer (for any block)

Definition at line 78 of file peerdisc.c.

Referenced by peerdisc_create(), and peerdisc_discovered().

◆ peerhost

char* peerhost
static

Hosted cache server.

Definition at line 81 of file peerdisc.c.

Referenced by __setting(), apply_peerdisc_settings(), and peerdisc_create().

◆ peerdisc_socket_operations

struct interface_operation peerdisc_socket_operations[]
static
Initial value:
= {
}
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
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
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195

PeerDist discovery socket interface operations.

Definition at line 298 of file peerdisc.c.

298 {
300};

◆ peerdisc_socket_desc

struct interface_descriptor peerdisc_socket_desc
static
Initial value:
=
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81
static struct interface_operation peerdisc_socket_operations[]
PeerDist discovery socket interface operations.
Definition peerdisc.c:298

PeerDist discovery socket interface descriptor.

Definition at line 303 of file peerdisc.c.

◆ __peerdisc_socket

struct peerdisc_socket peerdisc_socket_ipv6 __peerdisc_socket
Initial value:
= {
.name = "IPv4",
.address = {
.sin = {
.sin_family = AF_INET,
.sin_port = htons ( PEERDIST_DISCOVERY_PORT ),
.sin_addr.s_addr = htonl ( PEERDIST_DISCOVERY_IPV4 ),
},
},
}
#define AF_INET
IPv4 Internet addresses.
Definition socket.h:64
#define htonl(value)
Definition byteswap.h:134
#define htons(value)
Definition byteswap.h:136
#define INTF_INIT(descriptor)
Initialise a static object interface.
Definition interface.h:218
#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 struct interface_descriptor peerdisc_socket_desc
PeerDist discovery socket interface descriptor.
Definition peerdisc.c:303

PeerDist discovery IPv4 socket.

PeerDist discovery IPv6 socket.

Definition at line 307 of file peerdisc.c.

307 {
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};

◆ __settings_applicator

struct settings_applicator peerdisc_applicator __settings_applicator
Initial value:
= {
}
static int apply_peerdisc_settings(void)
Apply PeerDist discovery settings.
Definition peerdisc.c:647

PeerDist discovery settings applicator.

Definition at line 664 of file peerdisc.c.

664 {
666};