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