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)
 
 FILE_SECBOOT (PERMITTED)
 
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 55 of file peerdisc.c.

◆ PEERDISC_REPEAT_TIMEOUT

#define PEERDISC_REPEAT_TIMEOUT   ( 1 * TICKS_PER_SEC )

Time between repeated discovery attempts.

Definition at line 58 of file peerdisc.c.

◆ PEERDISC_DEFAULT_TIMEOUT_SECS

#define PEERDISC_DEFAULT_TIMEOUT_SECS   2

Default discovery timeout (in seconds)

Definition at line 61 of file peerdisc.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED  )

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

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

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 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 ) {
415  free ( peerdisc_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 }
uint16_t segment
Code segment.
Definition: librm.h:138
static char * peerdisc_recent
Most recently discovered peer (for any block)
Definition: peerdisc.c:78
struct list_head list
List of clients.
Definition: peerdisc.h:84
unsigned long tmp
Definition: linux_pci.h:65
#define ENOMEM
Not enough space.
Definition: errno.h:535
void(* discovered)(struct peerdisc_client *peerdisc)
New peers have been discovered.
Definition: peerdisc.h:95
A PeerDist discovery client.
Definition: peerdisc.h:80
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:432
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:94
char * strcpy(char *dest, const char *src)
Copy string.
Definition: string.c:347
#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
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:662
char * strdup(const char *src)
Duplicate string.
Definition: string.c:394
size_t strlen(const char *src)
Get length of string.
Definition: string.c:244
#define DBGC2(...)
Definition: compiler.h:522
int strcmp(const char *first, const char *second)
Compare strings.
Definition: string.c:174
struct peerdisc_client_operations * op
Operations.
Definition: peerdisc.h:86
struct mschapv2_challenge peer
Peer challenge.
Definition: mschapv2.h:12
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 }
void * intf_object(struct interface *intf)
Get pointer to object containing object interface.
Definition: interface.c:160
struct interface * intf
Original interface.
Definition: interface.h:159
void peerdisc_stat(struct interface *intf, struct peerdisc_peer *peer, struct list_head *peers)
Report peer discovery statistics.
Definition: peerdisc.c:101
An object interface.
Definition: interface.h:125
static uint16_t struct vmbus_xfer_pages_operations * op
Definition: netvsc.h:327
#define peerdisc_stat_TYPE(object_type)
Definition: peerdisc.h:115
void intf_put(struct interface *intf)
Decrement reference count on an object interface.
Definition: interface.c:150
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" return dest
Definition: string.h:151
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:270

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 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:14
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
A PeerDist discovery socket.
Definition: peerdisc.h:23
#define SOCK_DGRAM
Definition: socket.h:30
#define DBGC(...)
Definition: compiler.h:505
#define PEERDISC_SOCKETS
PeerDist discovery socket table.
Definition: peerdisc.h:37
struct interface xfer
Data transfer interface.
Definition: peerdisc.h:27
struct sockaddr sa
Definition: peerdisc.h:30
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:386
const char * name
Name.
Definition: peerdisc.h:25
#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 NULL
NULL pointer (VOID *)
Definition: Base.h:322
union peerdisc_socket::@655 address
Socket address.

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 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 */
188  for_each_netdev ( netdev ) {
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 }
TCP/IP socket address.
Definition: tcpip.h:76
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
Data transfer metadata.
Definition: xfer.h:23
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
A universally unique ID.
Definition: uuid.h:16
A PeerDist discovery socket.
Definition: peerdisc.h:23
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:37
#define PEERDISC_DISCARD_RATE
Definition: fault.h:22
unsigned int scope_id
Scope ID.
Definition: netdevice.h:361
struct sockaddr_tcpip st
Definition: syslog.c:58
struct interface xfer
Data transfer interface.
Definition: peerdisc.h:27
char * peerdist_discovery_request(const char *uuid, const char *id)
Construct discovery request.
Definition: pccrd.c:107
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:662
struct sockaddr sa
Definition: peerdisc.h:30
ring len
Length.
Definition: dwmac.h:231
static struct net_device * netdev
Definition: gdbudp.c:52
struct sockaddr sa
Definition: syslog.c:57
Generalized socket address structure.
Definition: socket.h:97
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
#define for_each_netdev(netdev)
Iterate over all network devices.
Definition: netdevice.h:547
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:386
A network device.
Definition: netdevice.h:353
size_t strlen(const char *src)
Get length of string.
Definition: string.c:244
char name[NETDEV_NAME_LEN]
Name of this network device.
Definition: netdevice.h:363
u8 request[0]
List of IEs requested.
Definition: ieee80211.h:16
const char * name
Name.
Definition: peerdisc.h:25
uint8_t meta
Metadata flags.
Definition: ena.h:14
union peerdisc_socket::@655 address
Socket address.
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 225 of file peerdisc.c.

227  {
228  struct peerdist_discovery_reply reply;
229  struct peerdisc_segment *segment;
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 }
uint16_t segment
Code segment.
Definition: librm.h:138
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:153
A PeerDist discovery segment.
Definition: peerdisc.h:43
#define DBGC(...)
Definition: compiler.h:505
#define PEERDISC_DISCARD_RATE
Definition: fault.h:22
static struct peerdisc_segment * peerdisc_find(const char *id)
Find PeerDist discovery segment.
Definition: peerdisc.c:366
#define DBGC_HDA(...)
Definition: compiler.h:506
A PeerDist discovery reply.
Definition: pccrd.h:31
uint8_t id
Request identifier.
Definition: ena.h:12
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:160
size_t strlen(const char *src)
Get length of string.
Definition: string.c:244
void * data
Start of data.
Definition: iobuf.h:53
static int peerdisc_discovered(struct peerdisc_segment *segment, const char *location)
Add discovered PeerDist peer.
Definition: peerdisc.c:385
const char * name
Name.
Definition: peerdisc.h:25
#define PEERDISC_DEFAULT_TIMEOUT_SECS
Default discovery timeout (in seconds)
Definition: peerdisc.c:61
unsigned int peerdisc_timeout_secs
Recommended discovery timeout (in seconds)
Definition: peerdisc.c:75

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

289  {
290  struct peerdisc_socket *socket;
291 
292  /* Close all sockets */
294  intf_restart ( &socket->xfer, rc );
295 }
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:344
A PeerDist discovery socket.
Definition: peerdisc.h:23
#define PEERDISC_SOCKETS
PeerDist discovery socket table.
Definition: peerdisc.h:37
struct interface xfer
Data transfer interface.
Definition: peerdisc.h:27
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:386

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 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 */
351  list_for_each_entry_safe ( peer, tmp, &segment->peers, list ) {
352  list_del ( &peer->list );
353  free ( peer );
354  }
355 
356  /* Free segment */
357  free ( segment );
358 }
uint16_t segment
Code segment.
Definition: librm.h:138
A PeerDist discovery segment.
Definition: peerdisc.h:43
A reference counter.
Definition: refcnt.h:27
unsigned long tmp
Definition: linux_pci.h:65
#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
#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
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
struct mschapv2_challenge peer
Peer challenge.
Definition: mschapv2.h:12
struct list_head list
List of peers.
Definition: peerdisc.h:74
A PeerDist discovery peer.
Definition: peerdisc.h:72

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 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 }
uint16_t segment
Code segment.
Definition: librm.h:138
static void peerdisc_socket_tx(const char *uuid, const char *id)
Attempt to transmit PeerDist discovery requests on all sockets.
Definition: peerdisc.c:158
A PeerDist discovery segment.
Definition: peerdisc.h:43
A timer.
Definition: timer.h:29
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:36
#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
#define PEERDISC_REPEAT_COUNT
Number of repeated discovery attempts.
Definition: peerdisc.c:55

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

451  {
452  struct peerdisc_segment *segment;
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 }
uint16_t segment
Code segment.
Definition: librm.h:138
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:100
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:65
A universally unique ID.
Definition: uuid.h:16
A PeerDist discovery segment.
Definition: peerdisc.h:43
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
void * memcpy(void *dest, const void *src, size_t len) __nonnull
uint8_t uuid[16]
UUID.
Definition: smbios.h:23
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:94
static char * peerhost
Hosted cache server.
Definition: peerdisc.c:81
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:662
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition: random.c:32
size_t strlen(const char *src)
Get length of string.
Definition: string.c:244
static void peerdisc_expired(struct retry_timer *timer, int over __unused)
Handle discovery timer expiry.
Definition: peerdisc.c:433
unsigned int uint32_t
Definition: stdint.h:12
const char * uuid_ntoa(const union uuid *uuid)
Convert UUID to printable string.
Definition: uuid.c:46
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:46
#define DBGC2(...)
Definition: compiler.h:522
static int peerdisc_discovered(struct peerdisc_segment *segment, const char *location)
Add discovered PeerDist peer.
Definition: peerdisc.c:385
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
unsigned long int dword
Definition: smc9000.h:40
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:107

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 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 }
uint16_t segment
Code segment.
Definition: librm.h:138
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:137
#define list_del(list)
Delete an entry from a list.
Definition: list.h:120
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition: retry.c:118
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:107

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  {
562  struct peerdisc_segment *segment;
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 }
uint16_t segment
Code segment.
Definition: librm.h:138
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
A PeerDist discovery segment.
Definition: peerdisc.h:43
struct list_head list
List of clients.
Definition: peerdisc.h:84
static struct peerdisc_segment * peerdisc_find(const char *id)
Find PeerDist discovery segment.
Definition: peerdisc.c:366
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:137
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
#define ENOMEM
Not enough space.
Definition: errno.h:535
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:94
ring len
Length.
Definition: dwmac.h:231
uint8_t id_string[24]
ID string.
Definition: eltorito.h:24
#define ref_get(refcnt)
Get additional reference to object.
Definition: refcnt.h:93
struct peerdisc_segment * segment
Discovery segment.
Definition: peerdisc.h:82
static struct peerdisc_segment * peerdisc_create(const char *id)
Create PeerDist discovery segment.
Definition: peerdisc.c:451
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
static int peerdisc_socket_open(void)
Open all PeerDist discovery sockets.
Definition: peerdisc.c:129

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 ) )
625  peerdisc_socket_close ( 0 );
626 }
uint16_t segment
Code segment.
Definition: librm.h:138
static void peerdisc_socket_close(int rc)
Close all PeerDist discovery sockets.
Definition: peerdisc.c:289
A PeerDist discovery segment.
Definition: peerdisc.h:43
#define DBGC(...)
Definition: compiler.h:505
struct list_head list
List of clients.
Definition: peerdisc.h:84
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:137
#define list_del(list)
Delete an entry from a list.
Definition: list.h:120
struct peerdisc_segment * segment
Discovery segment.
Definition: peerdisc.h:82
static void peerdisc_destroy(struct peerdisc_segment *segment)
Destroy PeerDist discovery segment.
Definition: peerdisc.c:532
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:107
unsigned int peerdisc_timeout_secs
Recommended discovery timeout (in seconds)
Definition: peerdisc.c:75

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 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 }
#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:874
static char * peerhost
Hosted cache server.
Definition: peerdisc.c:81
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322

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 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:23
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
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:33
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.

◆ peerdisc_socket_desc

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

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 INTF_INIT(descriptor)
Initialise a static object interface.
Definition: interface.h:218
#define PEERDIST_DISCOVERY_IPV4
PeerDist discovery IPv4 address (239.255.255.250)
Definition: pccrd.h:17
#define htonl(value)
Definition: byteswap.h:134
static struct interface_descriptor peerdisc_socket_desc
PeerDist discovery socket interface descriptor.
Definition: peerdisc.c:303
#define PEERDIST_DISCOVERY_PORT
PeerDist discovery port.
Definition: pccrd.h:14
#define htons(value)
Definition: byteswap.h:136
#define AF_INET
IPv4 Internet addresses.
Definition: socket.h:64

PeerDist discovery IPv4 socket.

PeerDist discovery IPv6 socket.

Definition at line 307 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:647

PeerDist discovery settings applicator.

Definition at line 664 of file peerdisc.c.