[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.
This commit is contained in:
parent
50810955e9
commit
c3811d4a13
|
@ -94,12 +94,19 @@ FEATURE ( FEATURE_PROTOCOL, "SLAM", DHCP_EB_FEATURE_SLAM, 1 );
|
||||||
#define SLAM_MAX_HEADER_LEN ( 7 /* transaction id */ + 7 /* total_bytes */ + \
|
#define SLAM_MAX_HEADER_LEN ( 7 /* transaction id */ + 7 /* total_bytes */ + \
|
||||||
7 /* block_size */ )
|
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
|
/** 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 */ + \
|
#define SLAM_MAX_NACK_LEN ( 7 /* block */ + 7 /* #blocks */ + 1 /* NUL */ )
|
||||||
1 /* NUL */ )
|
|
||||||
|
|
||||||
/** SLAM slave timeout */
|
/** SLAM slave timeout */
|
||||||
#define SLAM_SLAVE_TIMEOUT ( 1 * TICKS_PER_SEC )
|
#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 ) {
|
static int slam_tx_nack ( struct slam_request *slam ) {
|
||||||
struct io_buffer *iobuf;
|
struct io_buffer *iobuf;
|
||||||
unsigned long block;
|
unsigned long first_block;
|
||||||
|
unsigned long num_blocks;
|
||||||
uint8_t *nul;
|
uint8_t *nul;
|
||||||
int rc;
|
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
|
* data out as fast as it can. On a gigabit network, without
|
||||||
* RX checksumming, this would inevitably cause packet drops.
|
* RX checksumming, this would inevitably cause packet drops.
|
||||||
*/
|
*/
|
||||||
block = bitmap_first_gap ( &slam->bitmap );
|
first_block = bitmap_first_gap ( &slam->bitmap );
|
||||||
if ( block ) {
|
for ( num_blocks = 1 ; ; num_blocks++ ) {
|
||||||
DBGCP ( slam, "SLAM %p transmitting NACK for block %ld\n",
|
if ( num_blocks >= SLAM_MAX_BLOCKS_PER_NACK )
|
||||||
slam, block );
|
break;
|
||||||
} else {
|
if ( ( first_block + num_blocks ) >= slam->num_blocks )
|
||||||
DBGC ( slam, "SLAM %p transmitting initial NACK\n", slam );
|
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;
|
return rc;
|
||||||
if ( ( rc = slam_put_value ( slam, iobuf, 1 ) ) != 0 )
|
if ( ( rc = slam_put_value ( slam, iobuf, num_blocks ) ) != 0 )
|
||||||
return rc;
|
return rc;
|
||||||
nul = iob_put ( iobuf, 1 );
|
nul = iob_put ( iobuf, 1 );
|
||||||
*nul = 0;
|
*nul = 0;
|
||||||
|
|
Reference in New Issue