Browse Source

[slam] Speed up NACK transmission by restricting the block-list length

Shorter NACK packets take less time to construct and spew out less
debug output, and there's a limit to how useful it is to send a
complete missing-block list anyway; if the loss rate is high then
we're going to have to retransmit an updated missing-block list
anyway.

Also add pretty debugging output to show the list of requested blocks.
tags/v0.9.4
Michael Brown 16 years ago
parent
commit
1e5c2d48cb
1 changed files with 62 additions and 20 deletions
  1. 62
    20
      src/net/udp/slam.c

+ 62
- 20
src/net/udp/slam.c View File

@@ -93,6 +93,16 @@ FEATURE ( FEATURE_PROTOCOL, "SLAM", DHCP_EB_FEATURE_SLAM, 1 );
93 93
 #define SLAM_MAX_HEADER_LEN ( 8 /* transaction id */ + 8 /* total_bytes */ + \
94 94
 			      8 /* block_size */ )
95 95
 
96
+/** Maximum SLAM NACK length
97
+ *
98
+ * This is a policy decision.  Shorter packets take less time to
99
+ * construct and spew out less debug output, and there's a limit to
100
+ * how useful it is to send a complete missing-block list anyway; if
101
+ * the loss rate is high then we're going to have to retransmit an
102
+ * updated missing-block list anyway.
103
+ */
104
+#define SLAM_MAX_NACK_LEN 16
105
+
96 106
 /** A SLAM request */
97 107
 struct slam_request {
98 108
 	/** Reference counter */
@@ -198,8 +208,8 @@ static int slam_put_value ( struct slam_request *slam,
198 208
 	 */
199 209
 	len = ( ( flsl ( value ) + 10 ) / 8 );
200 210
 	if ( len >= iob_tailroom ( iobuf ) ) {
201
-		DBGC ( slam, "SLAM %p cannot add %d-byte value\n",
202
-		       slam, len );
211
+		DBGC2 ( slam, "SLAM %p cannot add %d-byte value\n",
212
+			slam, len );
203 213
 		return -ENOBUFS;
204 214
 	}
205 215
 	/* There is no valid way within the protocol that we can end
@@ -221,17 +231,59 @@ static int slam_put_value ( struct slam_request *slam,
221 231
 }
222 232
 
223 233
 /**
224
- * Send SLAM NACK packet
234
+ * Build SLAM compressed missing-block list
225 235
  *
226 236
  * @v slam		SLAM request
237
+ * @v iobuf		I/O buffer
227 238
  * @ret rc		Return status code
228 239
  */
229
-static int slam_tx_nack ( struct slam_request *slam ) {
230
-	struct io_buffer *iobuf;
240
+static int slam_build_block_list ( struct slam_request *slam,
241
+				   struct io_buffer *iobuf ) {
231 242
 	unsigned int block;
232 243
 	unsigned int block_count;
233 244
 	int block_present;
234 245
 	int last_block_present;
246
+	int rc;
247
+
248
+	DBGC ( slam, "SLAM %p asking for ", slam );
249
+
250
+	/* Walk bitmap to construct list */
251
+	block_count = 0;
252
+	last_block_present = ( ! 0 );
253
+	for ( block = 0 ; block < slam->num_blocks ; block++ ) {
254
+		block_present = ( !! bitmap_test ( &slam->bitmap, block ) );
255
+		if ( block_present != last_block_present ) {
256
+			if ( ( rc = slam_put_value ( slam, iobuf,
257
+						     block_count ) ) != 0 ) {
258
+				DBGC ( slam, "...\n" );
259
+				return rc;
260
+			}
261
+			DBGC ( slam, "%c%d",
262
+			       ( last_block_present ? ' ' : '-' ),
263
+			       ( last_block_present ? block : block - 1 ) );
264
+			block_count = 0;
265
+			last_block_present = block_present;
266
+		}
267
+		block_count++;
268
+	}
269
+	if ( ( rc = slam_put_value ( slam, iobuf, block_count ) ) != 0 ) {
270
+		DBGC ( slam, "...\n" );
271
+		return rc;
272
+	}
273
+	DBGC ( slam, "%c%d\n", ( last_block_present ? ' ' : '-' ),
274
+	       ( last_block_present ? block : block - 1 ) );
275
+
276
+	return 0;
277
+}
278
+
279
+/**
280
+ * Send SLAM NACK packet
281
+ *
282
+ * @v slam		SLAM request
283
+ * @ret rc		Return status code
284
+ */
285
+static int slam_tx_nack ( struct slam_request *slam ) {
286
+	struct io_buffer *iobuf;
235 287
 	uint8_t *nul;
236 288
 
237 289
 	DBGC ( slam, "SLAM %p transmitting NACK\n", slam );
@@ -243,26 +295,17 @@ static int slam_tx_nack ( struct slam_request *slam ) {
243 295
 	 * data we can fit in a packet.  If we overrun, it seems to be
244 296
 	 * acceptable to drop information anyway.
245 297
 	 */
246
-	iobuf = xfer_alloc_iob ( &slam->socket,	slam->block_size );
298
+	iobuf = xfer_alloc_iob ( &slam->socket,	SLAM_MAX_NACK_LEN );
247 299
 	if ( ! iobuf ) {
248 300
 		DBGC ( slam, "SLAM %p could not allocate I/O buffer\n",
249 301
 		       slam );
250 302
 		return -ENOMEM;
251 303
 	}
252 304
 
253
-	/* Walk bitmap to construct list */
254
-	block_count = 0;
255
-	last_block_present = ( ! 0 );
256
-	for ( block = 0 ; block < slam->num_blocks ; block++ ) {
257
-		block_present = ( !! bitmap_test ( &slam->bitmap, block ) );
258
-		if ( block_present != last_block_present ) {
259
-			slam_put_value ( slam, iobuf, block_count );
260
-			block_count = 0;
261
-			last_block_present = block_present;
262
-		}
263
-		block_count++;
264
-	}
265
-	slam_put_value ( slam, iobuf, block_count );
305
+	/* Build block list.  (Errors are non-fatal; it just means we
306
+	 * couldn't fit the compressed list within the packet.)
307
+	 */
308
+	slam_build_block_list ( slam, iobuf );
266 309
 
267 310
 	/* Add NUL terminator */
268 311
 	nul = iob_put ( iobuf, 1 );
@@ -697,7 +740,6 @@ static int slam_open ( struct xfer_interface *xfer, struct uri *uri ) {
697 740
 	/* Fake an invalid cached header of { 0x00, ... } */
698 741
 	slam->header_len = 1;
699 742
 	/* Fake parameters for initial NACK */
700
-	slam->block_size = 512;
701 743
 	slam->num_blocks = 1;
702 744
 	if ( ( rc = bitmap_resize ( &slam->bitmap, 1 ) ) != 0 ) {
703 745
 		DBGC ( slam, "SLAM %p could not allocate initial bitmap: "

Loading…
Cancel
Save