Browse Source

[peerdist] Gather and report peer statistics during download

Record and report the number of peers (calculated as the maximum
number of peers discovered for a block's segment at the time that the
block download is complete), and the percentage of blocks retrieved
from peers rather than from the origin server.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 years ago
parent
commit
7e673a6b67
5 changed files with 114 additions and 0 deletions
  1. 6
    0
      src/include/ipxe/peerdisc.h
  2. 13
    0
      src/include/ipxe/peermux.h
  3. 8
    0
      src/net/peerblk.c
  4. 30
    0
      src/net/peerdisc.c
  5. 57
    0
      src/net/peermux.c

+ 6
- 0
src/include/ipxe/peerdisc.h View File

@@ -109,6 +109,12 @@ peerdisc_init ( struct peerdisc_client *peerdisc,
109 109
 
110 110
 extern unsigned int peerdisc_timeout_secs;
111 111
 
112
+extern void peerdisc_stat ( struct interface *intf, struct peerdisc_peer *peer,
113
+			    struct list_head *peers );
114
+#define peerdisc_stat_TYPE( object_type )				\
115
+	typeof ( void ( object_type, struct peerdisc_peer *peer,	\
116
+			struct list_head *peers ) )
117
+
112 118
 extern int peerdisc_open ( struct peerdisc_client *peerdisc, const void *id,
113 119
 			   size_t len );
114 120
 extern void peerdisc_close ( struct peerdisc_client *peerdisc );

+ 13
- 0
src/include/ipxe/peermux.h View File

@@ -41,6 +41,16 @@ struct peerdist_multiplexed_block {
41 41
 	struct interface xfer;
42 42
 };
43 43
 
44
+/** PeerDist statistics */
45
+struct peerdist_statistics {
46
+	/** Maximum observed number of peers */
47
+	unsigned int peers;
48
+	/** Number of blocks downloaded in total */
49
+	unsigned int total;
50
+	/** Number of blocks downloaded from peers */
51
+	unsigned int local;
52
+};
53
+
44 54
 /** A PeerDist download multiplexer */
45 55
 struct peerdist_multiplexer {
46 56
 	/** Reference count */
@@ -65,6 +75,9 @@ struct peerdist_multiplexer {
65 75
 	struct list_head idle;
66 76
 	/** Block downloads */
67 77
 	struct peerdist_multiplexed_block block[PEERMUX_MAX_BLOCKS];
78
+
79
+	/** Statistics */
80
+	struct peerdist_statistics stats;
68 81
 };
69 82
 
70 83
 extern int peermux_filter ( struct interface *xfer, struct interface *info,

+ 8
- 0
src/net/peerblk.c View File

@@ -270,6 +270,9 @@ static int peerblk_deliver ( struct peerdist_block *peerblk,
270 270
  */
271 271
 static void peerblk_done ( struct peerdist_block *peerblk, int rc ) {
272 272
 	struct digest_algorithm *digest = peerblk->digest;
273
+	struct peerdisc_segment *segment = peerblk->discovery.segment;
274
+	struct peerdisc_peer *head;
275
+	struct peerdisc_peer *peer;
273 276
 	uint8_t hash[digest->digestsize];
274 277
 	unsigned long now = peerblk_timestamp();
275 278
 
@@ -296,6 +299,11 @@ static void peerblk_done ( struct peerdist_block *peerblk, int rc ) {
296 299
 	profile_custom ( &peerblk_attempt_success_profiler,
297 300
 			 ( now - peerblk->attempted ) );
298 301
 
302
+	/* Report peer statistics */
303
+	head = list_entry ( &segment->peers, struct peerdisc_peer, list );
304
+	peer = ( ( peerblk->peer == head ) ? NULL : peerblk->peer );
305
+	peerdisc_stat ( &peerblk->xfer, peer, &segment->peers );
306
+
299 307
 	/* Close download */
300 308
 	peerblk_close ( peerblk, 0 );
301 309
 	return;

+ 30
- 0
src/net/peerdisc.c View File

@@ -76,6 +76,36 @@ static struct peerdisc_segment * peerdisc_find ( const char *id );
76 76
 static int peerdisc_discovered ( struct peerdisc_segment *segment,
77 77
 				 const char *location );
78 78
 
79
+/******************************************************************************
80
+ *
81
+ * Statistics reporting
82
+ *
83
+ ******************************************************************************
84
+ */
85
+
86
+/**
87
+ * Report peer discovery statistics
88
+ *
89
+ * @v intf		Interface
90
+ * @v peer		Selected peer (or NULL)
91
+ * @v peers		List of available peers
92
+ */
93
+void peerdisc_stat ( struct interface *intf, struct peerdisc_peer *peer,
94
+		     struct list_head *peers ) {
95
+	struct interface *dest;
96
+	peerdisc_stat_TYPE ( void * ) *op =
97
+		intf_get_dest_op ( intf, peerdisc_stat, &dest );
98
+	void *object = intf_object ( dest );
99
+
100
+	if ( op ) {
101
+		op ( object, peer, peers );
102
+	} else {
103
+		/* Default is to do nothing */
104
+	}
105
+
106
+	intf_put ( dest );
107
+}
108
+
79 109
 /******************************************************************************
80 110
  *
81 111
  * Discovery sockets

+ 57
- 0
src/net/peermux.c View File

@@ -24,9 +24,11 @@
24 24
 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 25
 
26 26
 #include <stdlib.h>
27
+#include <stdio.h>
27 28
 #include <errno.h>
28 29
 #include <ipxe/uri.h>
29 30
 #include <ipxe/xferbuf.h>
31
+#include <ipxe/job.h>
30 32
 #include <ipxe/peerblk.h>
31 33
 #include <ipxe/peermux.h>
32 34
 
@@ -74,6 +76,28 @@ static void peermux_close ( struct peerdist_multiplexer *peermux, int rc ) {
74 76
 	intf_shutdown ( &peermux->info, rc );
75 77
 }
76 78
 
79
+/**
80
+ * Report progress of PeerDist download
81
+ *
82
+ * @v peermux		PeerDist download multiplexer
83
+ * @v progress		Progress report to fill in
84
+ * @ret ongoing_rc	Ongoing job status code (if known)
85
+ */
86
+static int peermux_progress ( struct peerdist_multiplexer *peermux,
87
+			      struct job_progress *progress ) {
88
+	struct peerdist_statistics *stats = &peermux->stats;
89
+	unsigned int percentage;
90
+
91
+	/* Construct PeerDist status message */
92
+	if ( stats->total ) {
93
+		percentage = ( ( 100 * stats->local ) / stats->total );
94
+		snprintf ( progress->message, sizeof ( progress->message ),
95
+			   "%3d%% from %d peers", percentage, stats->peers );
96
+	}
97
+
98
+	return 0;
99
+}
100
+
77 101
 /**
78 102
  * Receive content information
79 103
  *
@@ -274,6 +298,35 @@ peermux_block_buffer ( struct peerdist_multiplexed_block *peermblk ) {
274 298
 	return xfer_buffer ( &peermux->xfer );
275 299
 }
276 300
 
301
+/**
302
+ * Record peer discovery statistics
303
+ *
304
+ * @v peermblk		PeerDist multiplexed block download
305
+ * @v peer		Selected peer (or NULL)
306
+ * @v peers		List of available peers
307
+ */
308
+static void peermux_block_stat ( struct peerdist_multiplexed_block *peermblk,
309
+				 struct peerdisc_peer *peer,
310
+				 struct list_head *peers ) {
311
+	struct peerdist_multiplexer *peermux = peermblk->peermux;
312
+	struct peerdist_statistics *stats = &peermux->stats;
313
+	struct peerdisc_peer *tmp;
314
+	unsigned int count = 0;
315
+
316
+	/* Record maximum number of available peers */
317
+	list_for_each_entry ( tmp, peers, list )
318
+		count++;
319
+	if ( count > stats->peers )
320
+		stats->peers = count;
321
+
322
+	/* Update block counts */
323
+	if ( peer )
324
+		stats->local++;
325
+	stats->total++;
326
+	DBGC2 ( peermux, "PEERMUX %p downloaded %d/%d from %d peers\n",
327
+		peermux, stats->local, stats->total, stats->peers );
328
+}
329
+
277 330
 /**
278 331
  * Close multiplexed block download
279 332
  *
@@ -303,6 +356,8 @@ static void peermux_block_close ( struct peerdist_multiplexed_block *peermblk,
303 356
 
304 357
 /** Data transfer interface operations */
305 358
 static struct interface_operation peermux_xfer_operations[] = {
359
+	INTF_OP ( job_progress, struct peerdist_multiplexer *,
360
+		  peermux_progress ),
306 361
 	INTF_OP ( intf_close, struct peerdist_multiplexer *, peermux_close ),
307 362
 };
308 363
 
@@ -330,6 +385,8 @@ static struct interface_operation peermux_block_operations[] = {
330 385
 		  peermux_block_deliver ),
331 386
 	INTF_OP ( xfer_buffer, struct peerdist_multiplexed_block *,
332 387
 		  peermux_block_buffer ),
388
+	INTF_OP ( peerdisc_stat, struct peerdist_multiplexed_block *,
389
+		  peermux_block_stat ),
333 390
 	INTF_OP ( intf_close, struct peerdist_multiplexed_block *,
334 391
 		  peermux_block_close ),
335 392
 };

Loading…
Cancel
Save