From c3811d4a1339c29254db1ce04810259448840bcc Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 11 Jun 2008 13:16:02 +0100 Subject: [PATCH] [slam] Add support for SLAM window lengths of greater than one packet Add the definition of SLAM_MAX_BLOCKS_PER_NACK, which is roughly equivalent to a TCP window size; it represents the maximum number of packets that will be requested in a single NACK. Note that, to keep the code size down, we still limit ourselves to requesting only a single range per NACK; if the missing-block list is discontiguous then we may request fewer than SLAM_MAX_BLOCKS_PER_NACK blocks. --- src/net/udp/slam.c | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/net/udp/slam.c b/src/net/udp/slam.c index 510b9b21..cb0dfa5c 100644 --- a/src/net/udp/slam.c +++ b/src/net/udp/slam.c @@ -94,12 +94,19 @@ FEATURE ( FEATURE_PROTOCOL, "SLAM", DHCP_EB_FEATURE_SLAM, 1 ); #define SLAM_MAX_HEADER_LEN ( 7 /* transaction id */ + 7 /* total_bytes */ + \ 7 /* block_size */ ) +/** Maximum number of blocks to request per NACK + * + * This is a policy decision equivalent to selecting a TCP window + * size. + */ +#define SLAM_MAX_BLOCKS_PER_NACK 4 + /** Maximum SLAM NACK length * - * We only ever send a NACK for a single packet. + * We only ever send a NACK for a single range of up to @c + * SLAM_MAX_BLOCKS_PER_NACK blocks. */ -#define SLAM_MAX_NACK_LEN ( 7 /* block */ + 1 /* #blocks = 1 */ + \ - 1 /* NUL */ ) +#define SLAM_MAX_NACK_LEN ( 7 /* block */ + 7 /* #blocks */ + 1 /* NUL */ ) /** SLAM slave timeout */ #define SLAM_SLAVE_TIMEOUT ( 1 * TICKS_PER_SEC ) @@ -242,7 +249,8 @@ static int slam_put_value ( struct slam_request *slam, */ static int slam_tx_nack ( struct slam_request *slam ) { struct io_buffer *iobuf; - unsigned long block; + unsigned long first_block; + unsigned long num_blocks; uint8_t *nul; int rc; @@ -263,16 +271,27 @@ static int slam_tx_nack ( struct slam_request *slam ) { * data out as fast as it can. On a gigabit network, without * RX checksumming, this would inevitably cause packet drops. */ - block = bitmap_first_gap ( &slam->bitmap ); - if ( block ) { - DBGCP ( slam, "SLAM %p transmitting NACK for block %ld\n", - slam, block ); - } else { - DBGC ( slam, "SLAM %p transmitting initial NACK\n", slam ); + first_block = bitmap_first_gap ( &slam->bitmap ); + for ( num_blocks = 1 ; ; num_blocks++ ) { + if ( num_blocks >= SLAM_MAX_BLOCKS_PER_NACK ) + break; + if ( ( first_block + num_blocks ) >= slam->num_blocks ) + break; + if ( bitmap_test ( &slam->bitmap, + ( first_block + num_blocks ) ) ) + break; } - if ( ( rc = slam_put_value ( slam, iobuf, block ) ) != 0 ) + if ( first_block ) { + DBGCP ( slam, "SLAM %p transmitting NACK for blocks " + "%ld-%ld\n", slam, first_block, + ( first_block + num_blocks - 1 ) ); + } else { + DBGC ( slam, "SLAM %p transmitting initial NACK for blocks " + "0-%ld\n", slam, ( num_blocks - 1 ) ); + } + if ( ( rc = slam_put_value ( slam, iobuf, first_block ) ) != 0 ) return rc; - if ( ( rc = slam_put_value ( slam, iobuf, 1 ) ) != 0 ) + if ( ( rc = slam_put_value ( slam, iobuf, num_blocks ) ) != 0 ) return rc; nul = iob_put ( iobuf, 1 ); *nul = 0;