iPXE
Macros | Functions | Variables
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. More...
 
#define PEERDISC_REPEAT_TIMEOUT   ( 1 * TICKS_PER_SEC )
 Time between repeated discovery attempts. More...
 
#define PEERDISC_DEFAULT_TIMEOUT_SECS   2
 Default discovery timeout (in seconds) More...
 

Functions

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

Variables

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

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 54 of file peerdisc.c.

◆ PEERDISC_REPEAT_TIMEOUT

#define PEERDISC_REPEAT_TIMEOUT   ( 1 * TICKS_PER_SEC )

Time between repeated discovery attempts.

Definition at line 57 of file peerdisc.c.

◆ PEERDISC_DEFAULT_TIMEOUT_SECS

#define PEERDISC_DEFAULT_TIMEOUT_SECS   2

Default discovery timeout (in seconds)

Definition at line 60 of file peerdisc.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ LIST_HEAD()

static LIST_HEAD ( peerdisc_segments  )
static

List of discovery segments.

◆ peerdisc_find()

static 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 365 of file peerdisc.c.

365  {
366  struct peerdisc_segment *segment;
367 
368  /* Look for a matching segment */
369  list_for_each_entry ( segment, &peerdisc_segments, list ) {
370  if ( strcmp ( id, segment->id ) == 0 )
371  return segment;
372  }
373 
374  return NULL;
375 }
uint16_t segment
Code segment.
Definition: librm.h:252
A PeerDist discovery segment.
Definition: peerdisc.h:42
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:431
struct list_head list
List of segments.
Definition: peerdisc.h:46
int strcmp(const char *first, const char *second)
Compare strings.
Definition: string.c:173
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

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

Referenced by peerdisc_open(), and peerdisc_socket_rx().

◆ peerdisc_discovered()

static 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 384 of file peerdisc.c.

385  {
386  struct peerdisc_peer *peer;
387  struct peerdisc_client *peerdisc;
388  struct peerdisc_client *tmp;
389  char *recent;
390 
391  /* Ignore duplicate peers */
392  list_for_each_entry ( peer, &segment->peers, list ) {
393  if ( strcmp ( peer->location, location ) == 0 ) {
394  DBGC2 ( segment, "PEERDISC %p duplicate %s\n",
395  segment, location );
396  return 0;
397  }
398  }
399  DBGC2 ( segment, "PEERDISC %p discovered %s\n", segment, location );
400 
401  /* Allocate and initialise structure */
402  peer = zalloc ( sizeof ( *peer ) + strlen ( location ) + 1 /* NUL */ );
403  if ( ! peer )
404  return -ENOMEM;
405  strcpy ( peer->location, location );
406 
407  /* Add to end of list of peers */
408  list_add_tail ( &peer->list, &segment->peers );
409 
410  /* Record as most recently discovered peer */
411  if ( location != peerdisc_recent ) {
412  recent = strdup ( location );
413  if ( recent ) {
414  free ( peerdisc_recent );
415  peerdisc_recent = recent;
416  }
417  }
418 
419  /* Notify all clients */
420  list_for_each_entry_safe ( peerdisc, tmp, &segment->clients, list )
421  peerdisc->op->discovered ( peerdisc );
422 
423  return 0;
424 }
uint16_t segment
Code segment.
Definition: librm.h:252
static char * peerdisc_recent
Most recently discovered peer (for any block)
Definition: peerdisc.c:77
struct list_head list
List of clients.
Definition: peerdisc.h:83
unsigned long tmp
Definition: linux_pci.h:53
#define ENOMEM
Not enough space.
Definition: errno.h:534
void(* discovered)(struct peerdisc_client *peerdisc)
New peers have been discovered.
Definition: peerdisc.h:94
A PeerDist discovery client.
Definition: peerdisc.h:79
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:431
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
char * strcpy(char *dest, const char *src)
Copy string.
Definition: string.c:326
#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:458
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
char * strdup(const char *src)
Duplicate string.
Definition: string.c:380
size_t strlen(const char *src)
Get length of string.
Definition: string.c:243
#define DBGC2(...)
Definition: compiler.h:522
int strcmp(const char *first, const char *second)
Compare strings.
Definition: string.c:173
struct peerdisc_client_operations * op
Operations.
Definition: peerdisc.h:85
struct mschapv2_challenge peer
Peer challenge.
Definition: mschapv2.h:12
A PeerDist discovery peer.
Definition: peerdisc.h:71

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 100 of file peerdisc.c.

101  {
102  struct interface *dest;
103  peerdisc_stat_TYPE ( void * ) *op =
105  void *object = intf_object ( dest );
106 
107  if ( op ) {
108  op ( object, peer, peers );
109  } else {
110  /* Default is to do nothing */
111  }
112 
113  intf_put ( dest );
114 }
void * intf_object(struct interface *intf)
Get pointer to object containing object interface.
Definition: interface.c:159
struct interface * intf
Original interface.
Definition: interface.h:158
void peerdisc_stat(struct interface *intf, struct peerdisc_peer *peer, struct list_head *peers)
Report peer discovery statistics.
Definition: peerdisc.c:100
An object interface.
Definition: interface.h:124
static void * dest
Definition: strings.h:176
static uint16_t struct vmbus_xfer_pages_operations * op
Definition: netvsc.h:327
#define peerdisc_stat_TYPE(object_type)
Definition: peerdisc.h:114
void intf_put(struct interface *intf)
Decrement reference count on an object interface.
Definition: interface.c:149
struct mschapv2_challenge peer
Peer challenge.
Definition: mschapv2.h:12
#define intf_get_dest_op(intf, type, dest)
Get object interface destination and operation method.
Definition: interface.h:269

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()

static int peerdisc_socket_open ( void  )
static

Open all PeerDist discovery sockets.

Return values
rcReturn status code

Definition at line 128 of file peerdisc.c.

128  {
129  struct peerdisc_socket *socket;
130  int rc;
131 
132  /* Open each socket */
134  if ( ( rc = xfer_open_socket ( &socket->xfer, SOCK_DGRAM,
135  &socket->address.sa,
136  NULL ) ) != 0 ) {
137  DBGC ( socket, "PEERDISC %s could not open socket: "
138  "%s\n", socket->name, strerror ( rc ) );
139  goto err;
140  }
141  }
142 
143  return 0;
144 
145  err:
147  intf_restart ( &socket->xfer, rc );
148  return rc;
149 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition: interface.c:343
int xfer_open_socket(struct interface *intf, int semantics, struct sockaddr *peer, struct sockaddr *local)
Open socket.
Definition: open.c:142
A PeerDist discovery socket.
Definition: peerdisc.h:22
#define SOCK_DGRAM
Definition: socket.h:29
#define DBGC(...)
Definition: compiler.h:505
#define PEERDISC_SOCKETS
PeerDist discovery socket table.
Definition: peerdisc.h:36
struct interface xfer
Data transfer interface.
Definition: peerdisc.h:26
struct sockaddr sa
Definition: peerdisc.h:29
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:385
union peerdisc_socket::@589 address
Socket address.
const char * name
Name.
Definition: peerdisc.h:24
#define for_each_table_entry_continue_reverse(pointer, table)
Iterate through all remaining entries within a linker table in reverse order.
Definition: tables.h:469
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

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()

static 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 157 of file peerdisc.c.

157  {
158  struct peerdisc_socket *socket;
159  struct net_device *netdev;
160  struct xfer_metadata meta;
161  union {
162  struct sockaddr sa;
163  struct sockaddr_tcpip st;
164  } address;
165  char *request;
166  size_t len;
167  int rc;
168 
169  /* Construct discovery request */
171  if ( ! request )
172  goto err_request;
173  len = strlen ( request );
174 
175  /* Initialise data transfer metadata */
176  memset ( &meta, 0, sizeof ( meta ) );
177  meta.dest = &address.sa;
178 
179  /* Send message on each socket */
181 
182  /* Initialise socket address */
183  memcpy ( &address.sa, &socket->address.sa,
184  sizeof ( address.sa ) );
185 
186  /* Send message on each open network device */
187  for_each_netdev ( netdev ) {
188 
189  /* Skip unopened network devices */
190  if ( ! netdev_is_open ( netdev ) )
191  continue;
192  address.st.st_scope_id = netdev->scope_id;
193 
194  /* Discard request (for test purposes) if applicable */
195  if ( inject_fault ( PEERDISC_DISCARD_RATE ) )
196  continue;
197 
198  /* Transmit request */
199  if ( ( rc = xfer_deliver_raw_meta ( &socket->xfer,
200  request, len,
201  &meta ) ) != 0 ) {
202  DBGC ( socket, "PEERDISC %s could not transmit "
203  "via %s: %s\n", socket->name,
204  netdev->name, strerror ( rc ) );
205  /* Contine to try other net devices/sockets */
206  continue;
207  }
208  }
209  }
210 
211  free ( request );
212  err_request:
213  return;
214 }
TCP/IP socket address.
Definition: tcpip.h:75
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
Data transfer metadata.
Definition: xfer.h:22
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:268
A universally unique ID.
Definition: uuid.h:15
A PeerDist discovery socket.
Definition: peerdisc.h:22
uint64_t address
Base address.
Definition: ena.h:24
#define DBGC(...)
Definition: compiler.h:505
#define PEERDISC_SOCKETS
PeerDist discovery socket table.
Definition: peerdisc.h:36
#define PEERDISC_DISCARD_RATE
Definition: fault.h:18
unsigned int scope_id
Scope ID.
Definition: netdevice.h:360
struct sockaddr_tcpip st
Definition: syslog.c:56
struct interface xfer
Data transfer interface.
Definition: peerdisc.h:26
char * peerdist_discovery_request(const char *uuid, const char *id)
Construct discovery request.
Definition: pccrd.c:106
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition: netdevice.h:658
struct sockaddr sa
Definition: peerdisc.h:29
static struct net_device * netdev
Definition: gdbudp.c:52
struct sockaddr sa
Definition: syslog.c:55
int meta(WINDOW *, bool)
Generalized socket address structure.
Definition: socket.h:96
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
#define for_each_netdev(netdev)
Iterate over all network devices.
Definition: netdevice.h:543
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:385
A network device.
Definition: netdevice.h:352
size_t strlen(const char *src)
Get length of string.
Definition: string.c:243
char name[NETDEV_NAME_LEN]
Name of this network device.
Definition: netdevice.h:362
union peerdisc_socket::@589 address
Socket address.
uint32_t len
Length.
Definition: ena.h:14
u8 request[0]
List of IEs requested.
Definition: ieee80211.h:16
const char * name
Name.
Definition: peerdisc.h:24
void * memset(void *dest, int character, size_t len) __nonnull

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

Referenced by peerdisc_expired().

◆ peerdisc_socket_rx()

static 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 224 of file peerdisc.c.

226  {
227  struct peerdist_discovery_reply reply;
228  struct peerdisc_segment *segment;
229  char *id;
230  char *location;
231  int rc;
232 
233  /* Discard reply (for test purposes) if applicable */
234  if ( ( rc = inject_fault ( PEERDISC_DISCARD_RATE ) ) != 0 )
235  goto err;
236 
237  /* Parse reply */
238  if ( ( rc = peerdist_discovery_reply ( iobuf->data, iob_len ( iobuf ),
239  &reply ) ) != 0 ) {
240  DBGC ( socket, "PEERDISC %s could not parse reply: %s\n",
241  socket->name, strerror ( rc ) );
242  DBGC_HDA ( socket, 0, iobuf->data, iob_len ( iobuf ) );
243  goto err;
244  }
245 
246  /* Any kind of discovery reply indicates that there are active
247  * peers on a local network, so restore the recommended
248  * discovery timeout to its default value for future requests.
249  */
251  DBGC ( socket, "PEERDISC %s restoring timeout to %d seconds\n",
253  }
255 
256  /* Iterate over segment IDs */
257  for ( id = reply.ids ; *id ; id += ( strlen ( id ) + 1 /* NUL */ ) ) {
258 
259  /* Find corresponding segment */
260  segment = peerdisc_find ( id );
261  if ( ! segment ) {
262  DBGC ( socket, "PEERDISC %s ignoring reply for %s\n",
263  socket->name, id );
264  continue;
265  }
266 
267  /* Report all discovered peer locations */
268  for ( location = reply.locations ; *location ;
269  location += ( strlen ( location ) + 1 /* NUL */ ) ) {
270 
271  /* Report discovered peer location */
272  if ( ( rc = peerdisc_discovered ( segment,
273  location ) ) != 0 )
274  goto err;
275  }
276  }
277 
278  err:
279  free_iob ( iobuf );
280  return rc;
281 }
uint16_t segment
Code segment.
Definition: librm.h:252
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
A PeerDist discovery segment.
Definition: peerdisc.h:42
#define DBGC(...)
Definition: compiler.h:505
#define PEERDISC_DISCARD_RATE
Definition: fault.h:18
static struct peerdisc_segment * peerdisc_find(const char *id)
Find PeerDist discovery segment.
Definition: peerdisc.c:365
#define DBGC_HDA(...)
Definition: compiler.h:506
A PeerDist discovery reply.
Definition: pccrd.h:30
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
uint8_t id
Request identifier.
Definition: ena.h:12
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:155
size_t strlen(const char *src)
Get length of string.
Definition: string.c:243
void * data
Start of data.
Definition: iobuf.h:48
static int peerdisc_discovered(struct peerdisc_segment *segment, const char *location)
Add discovered PeerDist peer.
Definition: peerdisc.c:384
const char * name
Name.
Definition: peerdisc.h:24
#define PEERDISC_DEFAULT_TIMEOUT_SECS
Default discovery timeout (in seconds)
Definition: peerdisc.c:60
unsigned int peerdisc_timeout_secs
Recommended discovery timeout (in seconds)
Definition: peerdisc.c:74

References io_buffer::data, DBGC, DBGC_HDA, free_iob(), id, peerdist_discovery_reply::ids, iob_len(), peerdist_discovery_reply::locations, 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()

static void peerdisc_socket_close ( int  rc)
static

Close all PeerDist discovery sockets.

Parameters
rcReason for close

Definition at line 288 of file peerdisc.c.

288  {
289  struct peerdisc_socket *socket;
290 
291  /* Close all sockets */
293  intf_restart ( &socket->xfer, rc );
294 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition: interface.c:343
A PeerDist discovery socket.
Definition: peerdisc.h:22
#define PEERDISC_SOCKETS
PeerDist discovery socket table.
Definition: peerdisc.h:36
struct interface xfer
Data transfer interface.
Definition: peerdisc.h:26
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:385

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

Referenced by peerdisc_close().

◆ peerdisc_free()

static void peerdisc_free ( struct refcnt refcnt)
static

Free PeerDist discovery segment.

Parameters
refcntReference count

Definition at line 343 of file peerdisc.c.

343  {
344  struct peerdisc_segment *segment =
346  struct peerdisc_peer *peer;
347  struct peerdisc_peer *tmp;
348 
349  /* Free all discovered peers */
350  list_for_each_entry_safe ( peer, tmp, &segment->peers, list ) {
351  list_del ( &peer->list );
352  free ( peer );
353  }
354 
355  /* Free segment */
356  free ( segment );
357 }
uint16_t segment
Code segment.
Definition: librm.h:252
A PeerDist discovery segment.
Definition: peerdisc.h:42
A reference counter.
Definition: refcnt.h:26
unsigned long tmp
Definition: linux_pci.h:53
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
#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:458
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
struct mschapv2_challenge peer
Peer challenge.
Definition: mschapv2.h:12
struct list_head list
List of peers.
Definition: peerdisc.h:73
A PeerDist discovery peer.
Definition: peerdisc.h:71

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

Referenced by peerdisc_create().

◆ peerdisc_expired()

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

Handle discovery timer expiry.

Parameters
timerDiscovery timer
overFailure indicator

Definition at line 432 of file peerdisc.c.

432  {
433  struct peerdisc_segment *segment =
435 
436  /* Attempt to transmit discovery requests */
437  peerdisc_socket_tx ( segment->uuid, segment->id );
438 
439  /* Schedule next transmission, if applicable */
440  if ( timer->count < PEERDISC_REPEAT_COUNT )
442 }
uint16_t segment
Code segment.
Definition: librm.h:252
static void peerdisc_socket_tx(const char *uuid, const char *id)
Attempt to transmit PeerDist discovery requests on all sockets.
Definition: peerdisc.c:157
A PeerDist discovery segment.
Definition: peerdisc.h:42
A timer.
Definition: timer.h:28
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
#define PEERDISC_REPEAT_TIMEOUT
Time between repeated discovery attempts.
Definition: peerdisc.c:57
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition: retry.c:64
#define PEERDISC_REPEAT_COUNT
Number of repeated discovery attempts.
Definition: peerdisc.c:54

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

Referenced by peerdisc_create().

◆ peerdisc_create()

static 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 450 of file peerdisc.c.

450  {
451  struct peerdisc_segment *segment;
452  union {
453  union uuid uuid;
454  uint32_t dword[ sizeof ( union uuid ) / sizeof ( uint32_t ) ];
455  } random_uuid;
456  size_t uuid_len;
457  size_t id_len;
458  const char *uuid;
459  char *uuid_copy;
460  char *id_copy;
461  unsigned int i;
462  int rc;
463 
464  /* Generate a random message UUID. This does not require high
465  * quality randomness.
466  */
467  for ( i = 0 ; i < ( sizeof ( random_uuid.dword ) /
468  sizeof ( random_uuid.dword[0] ) ) ; i++ )
469  random_uuid.dword[i] = random();
470  uuid = uuid_ntoa ( &random_uuid.uuid );
471 
472  /* Calculate string lengths */
473  id_len = ( strlen ( id ) + 1 /* NUL */ );
474  uuid_len = ( strlen ( uuid ) + 1 /* NUL */ );
475 
476  /* Allocate and initialise structure */
477  segment = zalloc ( sizeof ( *segment ) + id_len + uuid_len );
478  if ( ! segment )
479  goto err_alloc;
480  id_copy = ( ( ( void * ) segment ) + sizeof ( *segment ) );
481  memcpy ( id_copy, id, id_len );
482  uuid_copy = ( ( ( void * ) id_copy ) + id_len );
483  memcpy ( uuid_copy, uuid, uuid_len );
484  ref_init ( &segment->refcnt, peerdisc_free );
485  segment->id = id_copy;
486  segment->uuid = uuid_copy;
487  INIT_LIST_HEAD ( &segment->peers );
488  INIT_LIST_HEAD ( &segment->clients );
489  timer_init ( &segment->timer, peerdisc_expired, &segment->refcnt );
490 
491  /* Add hosted cache server or initiate discovery */
492  if ( peerhost ) {
493 
494  /* Add hosted cache server to list of peers */
495  if ( ( rc = peerdisc_discovered ( segment, peerhost ) ) != 0 )
496  goto err_peerhost;
497 
498  } else {
499 
500  /* Add most recently discovered peer to list of peers
501  *
502  * This is a performance optimisation: we assume that
503  * the most recently discovered peer for any block has
504  * a high probability of also having a copy of the
505  * next block that we attempt to discover.
506  */
507  if ( peerdisc_recent )
509 
510  /* Start discovery timer */
511  start_timer_nodelay ( &segment->timer );
512  DBGC2 ( segment, "PEERDISC %p discovering %s\n",
513  segment, segment->id );
514  }
515 
516  /* Add to list of segments, transfer reference to list, and return */
517  list_add_tail ( &segment->list, &peerdisc_segments );
518  return segment;
519 
520  err_peerhost:
521  ref_put ( &segment->refcnt );
522  err_alloc:
523  return NULL;
524 }
uint16_t segment
Code segment.
Definition: librm.h:252
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition: retry.h:99
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:64
A universally unique ID.
Definition: uuid.h:15
A PeerDist discovery segment.
Definition: peerdisc.h:42
static char * peerdisc_recent
Most recently discovered peer (for any block)
Definition: peerdisc.c:77
static void peerdisc_free(struct refcnt *refcnt)
Free PeerDist discovery segment.
Definition: peerdisc.c:343
void * memcpy(void *dest, const void *src, size_t len) __nonnull
uint8_t uuid[16]
UUID.
Definition: smbios.h:22
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
static char * peerhost
Hosted cache server.
Definition: peerdisc.c:80
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition: random.c:31
size_t strlen(const char *src)
Get length of string.
Definition: string.c:243
static void peerdisc_expired(struct retry_timer *timer, int over __unused)
Handle discovery timer expiry.
Definition: peerdisc.c:432
unsigned int uint32_t
Definition: stdint.h:12
const char * uuid_ntoa(const union uuid *uuid)
Convert UUID to printable string.
Definition: uuid.c:45
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:45
#define DBGC2(...)
Definition: compiler.h:522
static int peerdisc_discovered(struct peerdisc_segment *segment, const char *location)
Add discovered PeerDist peer.
Definition: peerdisc.c:384
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
unsigned long int dword
Definition: smc9000.h:40
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106

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, uuid_ntoa(), and zalloc().

Referenced by peerdisc_open().

◆ peerdisc_destroy()

static void peerdisc_destroy ( struct peerdisc_segment segment)
static

Destroy PeerDist discovery segment.

Parameters
segmentPeerDist discovery segment

Definition at line 531 of file peerdisc.c.

531  {
532 
533  /* Sanity check */
534  assert ( list_empty ( &segment->clients ) );
535 
536  /* Stop timer */
537  stop_timer ( &segment->timer );
538 
539  /* Remove from list of segments and drop list's reference */
540  list_del ( &segment->list );
541  ref_put ( &segment->refcnt );
542 }
uint16_t segment
Code segment.
Definition: librm.h:252
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:136
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition: retry.c:117
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106

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 559 of file peerdisc.c.

560  {
561  struct peerdisc_segment *segment;
562  char id_string[ base16_encoded_len ( len ) + 1 /* NUL */ ];
563  char *id_chr;
564  int rc;
565 
566  /* Construct ID string */
567  base16_encode ( id, len, id_string, sizeof ( id_string ) );
568  for ( id_chr = id_string ; *id_chr ; id_chr++ )
569  *id_chr = toupper ( *id_chr );
570 
571  /* Sanity check */
572  assert ( peerdisc->segment == NULL );
573 
574  /* Open socket if this is the first segment */
575  if ( list_empty ( &peerdisc_segments ) &&
576  ( ( rc = peerdisc_socket_open() ) != 0 ) )
577  return rc;
578 
579  /* Find or create segment */
580  if ( ! ( ( segment = peerdisc_find ( id_string ) ) ||
581  ( segment = peerdisc_create ( id_string ) ) ) )
582  return -ENOMEM;
583 
584  /* Add to list of clients */
585  ref_get ( &segment->refcnt );
586  peerdisc->segment = segment;
587  list_add_tail ( &peerdisc->list, &segment->clients );
588 
589  return 0;
590 }
uint16_t segment
Code segment.
Definition: librm.h:252
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
A PeerDist discovery segment.
Definition: peerdisc.h:42
struct list_head list
List of clients.
Definition: peerdisc.h:83
static struct peerdisc_segment * peerdisc_find(const char *id)
Find PeerDist discovery segment.
Definition: peerdisc.c:365
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:136
static size_t base16_encoded_len(size_t raw_len)
Calculate length of base16-encoded data.
Definition: base16.h:24
static int toupper(int character)
Convert character to upper case.
Definition: ctype.h:120
#define ENOMEM
Not enough space.
Definition: errno.h:534
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
uint8_t id_string[24]
ID string.
Definition: eltorito.h:24
#define ref_get(refcnt)
Get additional reference to object.
Definition: refcnt.h:92
struct peerdisc_segment * segment
Discovery segment.
Definition: peerdisc.h:81
static struct peerdisc_segment * peerdisc_create(const char *id)
Create PeerDist discovery segment.
Definition: peerdisc.c:450
uint32_t len
Length.
Definition: ena.h:14
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
static int peerdisc_socket_open(void)
Open all PeerDist discovery sockets.
Definition: peerdisc.c:128

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 597 of file peerdisc.c.

597  {
598  struct peerdisc_segment *segment = peerdisc->segment;
599 
600  /* Ignore if discovery is already closed */
601  if ( ! segment )
602  return;
603 
604  /* If no peers were discovered, reduce the recommended
605  * discovery timeout to minimise delays on future requests.
606  */
607  if ( list_empty ( &segment->peers ) && peerdisc_timeout_secs ) {
609  DBGC ( segment, "PEERDISC %p reducing timeout to %d "
610  "seconds\n", peerdisc, peerdisc_timeout_secs );
611  }
612 
613  /* Remove from list of clients */
614  peerdisc->segment = NULL;
615  list_del ( &peerdisc->list );
616  ref_put ( &segment->refcnt );
617 
618  /* If this was the last clients, destroy the segment */
619  if ( list_empty ( &segment->clients ) )
621 
622  /* If there are no more segments, close the socket */
623  if ( list_empty ( &peerdisc_segments ) )
624  peerdisc_socket_close ( 0 );
625 }
uint16_t segment
Code segment.
Definition: librm.h:252
static void peerdisc_socket_close(int rc)
Close all PeerDist discovery sockets.
Definition: peerdisc.c:288
A PeerDist discovery segment.
Definition: peerdisc.h:42
#define DBGC(...)
Definition: compiler.h:505
struct list_head list
List of clients.
Definition: peerdisc.h:83
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:136
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
struct peerdisc_segment * segment
Discovery segment.
Definition: peerdisc.h:81
static void peerdisc_destroy(struct peerdisc_segment *segment)
Destroy PeerDist discovery segment.
Definition: peerdisc.c:531
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106
unsigned int peerdisc_timeout_secs
Recommended discovery timeout (in seconds)
Definition: peerdisc.c:74

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.

◆ apply_peerdisc_settings()

static int apply_peerdisc_settings ( void  )
static

Apply PeerDist discovery settings.

Return values
rcReturn status code

Definition at line 646 of file peerdisc.c.

646  {
647 
648  /* Free any existing hosted cache server */
649  free ( peerhost );
650  peerhost = NULL;
651 
652  /* Fetch hosted cache server */
653  fetch_string_setting_copy ( NULL, &peerhost_setting, &peerhost );
654  if ( peerhost ) {
655  DBGC ( &peerhost, "PEERDISC using hosted cache %s\n",
656  peerhost );
657  }
658 
659  return 0;
660 }
#define DBGC(...)
Definition: compiler.h:505
int fetch_string_setting_copy(struct settings *settings, const struct setting *setting, char **data)
Fetch value of string setting.
Definition: settings.c:873
static char * peerhost
Hosted cache server.
Definition: peerdisc.c:80
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

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 74 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 77 of file peerdisc.c.

Referenced by peerdisc_create(), and peerdisc_discovered().

◆ peerhost

char* peerhost
static

Hosted cache server.

Definition at line 80 of file peerdisc.c.

Referenced by apply_peerdisc_settings(), and peerdisc_create().

◆ peerdisc_socket_operations

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

PeerDist discovery socket interface operations.

Definition at line 297 of file peerdisc.c.

◆ peerdisc_socket_desc

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

PeerDist discovery socket interface descriptor.

Definition at line 302 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 INTF_INIT(descriptor)
Initialise a static object interface.
Definition: interface.h:217
#define PEERDIST_DISCOVERY_IPV4
PeerDist discovery IPv4 address (239.255.255.250)
Definition: pccrd.h:16
#define htonl(value)
Definition: byteswap.h:133
static struct interface_descriptor peerdisc_socket_desc
PeerDist discovery socket interface descriptor.
Definition: peerdisc.c:302
#define PEERDIST_DISCOVERY_PORT
PeerDist discovery port.
Definition: pccrd.h:13
#define htons(value)
Definition: byteswap.h:135
#define AF_INET
IPv4 Internet addresses.
Definition: socket.h:63

PeerDist discovery IPv4 socket.

PeerDist discovery IPv6 socket.

Definition at line 306 of file peerdisc.c.

◆ __settings_applicator

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

PeerDist discovery settings applicator.

Definition at line 663 of file peerdisc.c.