|
@@ -94,12 +94,19 @@ FEATURE ( FEATURE_PROTOCOL, "SLAM", DHCP_EB_FEATURE_SLAM, 1 );
|
94
|
94
|
#define SLAM_MAX_HEADER_LEN ( 7 /* transaction id */ + 7 /* total_bytes */ + \
|
95
|
95
|
7 /* block_size */ )
|
96
|
96
|
|
|
97
|
+/** Maximum number of blocks to request per NACK
|
|
98
|
+ *
|
|
99
|
+ * This is a policy decision equivalent to selecting a TCP window
|
|
100
|
+ * size.
|
|
101
|
+ */
|
|
102
|
+#define SLAM_MAX_BLOCKS_PER_NACK 4
|
|
103
|
+
|
97
|
104
|
/** Maximum SLAM NACK length
|
98
|
105
|
*
|
99
|
|
- * We only ever send a NACK for a single packet.
|
|
106
|
+ * We only ever send a NACK for a single range of up to @c
|
|
107
|
+ * SLAM_MAX_BLOCKS_PER_NACK blocks.
|
100
|
108
|
*/
|
101
|
|
-#define SLAM_MAX_NACK_LEN ( 7 /* block */ + 1 /* #blocks = 1 */ + \
|
102
|
|
- 1 /* NUL */ )
|
|
109
|
+#define SLAM_MAX_NACK_LEN ( 7 /* block */ + 7 /* #blocks */ + 1 /* NUL */ )
|
103
|
110
|
|
104
|
111
|
/** SLAM slave timeout */
|
105
|
112
|
#define SLAM_SLAVE_TIMEOUT ( 1 * TICKS_PER_SEC )
|
|
@@ -242,7 +249,8 @@ static int slam_put_value ( struct slam_request *slam,
|
242
|
249
|
*/
|
243
|
250
|
static int slam_tx_nack ( struct slam_request *slam ) {
|
244
|
251
|
struct io_buffer *iobuf;
|
245
|
|
- unsigned long block;
|
|
252
|
+ unsigned long first_block;
|
|
253
|
+ unsigned long num_blocks;
|
246
|
254
|
uint8_t *nul;
|
247
|
255
|
int rc;
|
248
|
256
|
|
|
@@ -263,16 +271,27 @@ static int slam_tx_nack ( struct slam_request *slam ) {
|
263
|
271
|
* data out as fast as it can. On a gigabit network, without
|
264
|
272
|
* RX checksumming, this would inevitably cause packet drops.
|
265
|
273
|
*/
|
266
|
|
- block = bitmap_first_gap ( &slam->bitmap );
|
267
|
|
- if ( block ) {
|
268
|
|
- DBGCP ( slam, "SLAM %p transmitting NACK for block %ld\n",
|
269
|
|
- slam, block );
|
|
274
|
+ first_block = bitmap_first_gap ( &slam->bitmap );
|
|
275
|
+ for ( num_blocks = 1 ; ; num_blocks++ ) {
|
|
276
|
+ if ( num_blocks >= SLAM_MAX_BLOCKS_PER_NACK )
|
|
277
|
+ break;
|
|
278
|
+ if ( ( first_block + num_blocks ) >= slam->num_blocks )
|
|
279
|
+ break;
|
|
280
|
+ if ( bitmap_test ( &slam->bitmap,
|
|
281
|
+ ( first_block + num_blocks ) ) )
|
|
282
|
+ break;
|
|
283
|
+ }
|
|
284
|
+ if ( first_block ) {
|
|
285
|
+ DBGCP ( slam, "SLAM %p transmitting NACK for blocks "
|
|
286
|
+ "%ld-%ld\n", slam, first_block,
|
|
287
|
+ ( first_block + num_blocks - 1 ) );
|
270
|
288
|
} else {
|
271
|
|
- DBGC ( slam, "SLAM %p transmitting initial NACK\n", slam );
|
|
289
|
+ DBGC ( slam, "SLAM %p transmitting initial NACK for blocks "
|
|
290
|
+ "0-%ld\n", slam, ( num_blocks - 1 ) );
|
272
|
291
|
}
|
273
|
|
- if ( ( rc = slam_put_value ( slam, iobuf, block ) ) != 0 )
|
|
292
|
+ if ( ( rc = slam_put_value ( slam, iobuf, first_block ) ) != 0 )
|
274
|
293
|
return rc;
|
275
|
|
- if ( ( rc = slam_put_value ( slam, iobuf, 1 ) ) != 0 )
|
|
294
|
+ if ( ( rc = slam_put_value ( slam, iobuf, num_blocks ) ) != 0 )
|
276
|
295
|
return rc;
|
277
|
296
|
nul = iob_put ( iobuf, 1 );
|
278
|
297
|
*nul = 0;
|