summaryrefslogtreecommitdiffstats
path: root/src/net
diff options
context:
space:
mode:
authorMichael Brown2008-06-10 13:30:43 +0200
committerMichael Brown2008-06-10 13:36:39 +0200
commit2456b9b4baf452a83d3814a2f7babed440037e9f (patch)
tree58fddb4c4dbc6034c7137d4db3d8bff6f3b51f10 /src/net
parent[slam] Speed up NACK transmission by restricting the block-list length (diff)
downloadipxe-2456b9b4baf452a83d3814a2f7babed440037e9f.tar.gz
ipxe-2456b9b4baf452a83d3814a2f7babed440037e9f.tar.xz
ipxe-2456b9b4baf452a83d3814a2f7babed440037e9f.zip
[slam] Request all remaining blocks if we run out of space for the blocklist
In a SLAM NACK packet, if we run out of space to represent the missing-block list, then indicate all remaining blocks as missing. This avoids the need to wait for the one-second timeout before receiving the blocks that otherwise wouldn't have been requested due to running out of space.
Diffstat (limited to 'src/net')
-rw-r--r--src/net/udp/slam.c63
1 files changed, 41 insertions, 22 deletions
diff --git a/src/net/udp/slam.c b/src/net/udp/slam.c
index e51c068f..f7ce546e 100644
--- a/src/net/udp/slam.c
+++ b/src/net/udp/slam.c
@@ -191,14 +191,14 @@ static void slam_finished ( struct slam_request *slam, int rc ) {
* @v slam SLAM request
* @v iobuf I/O buffer
* @v value Value to add
- * @ret rc Return status code
+ * @v reserved Length of reserved space at end of buffer
+ * @ret len Length of value, or negative error.
*
- * Adds a variable-length value to the end of an I/O buffer. Will
- * refuse to use the last byte of the I/O buffer; this is to allow
- * space for the terminating NUL.
+ * Adds a variable-length value to the end of an I/O buffer.
*/
static int slam_put_value ( struct slam_request *slam,
- struct io_buffer *iobuf, unsigned long value ) {
+ struct io_buffer *iobuf, unsigned long value,
+ size_t reserved ) {
uint8_t *data;
size_t len;
unsigned int i;
@@ -207,7 +207,7 @@ static int slam_put_value ( struct slam_request *slam,
* leave at least one byte in the I/O buffer.
*/
len = ( ( flsl ( value ) + 10 ) / 8 );
- if ( len >= iob_tailroom ( iobuf ) ) {
+ if ( ( len + reserved ) > iob_tailroom ( iobuf ) ) {
DBGC2 ( slam, "SLAM %p cannot add %d-byte value\n",
slam, len );
return -ENOBUFS;
@@ -227,7 +227,7 @@ static int slam_put_value ( struct slam_request *slam,
*data |= ( len << 5 );
assert ( value == 0 );
- return 0;
+ return len;
}
/**
@@ -239,13 +239,16 @@ static int slam_put_value ( struct slam_request *slam,
*/
static int slam_build_block_list ( struct slam_request *slam,
struct io_buffer *iobuf ) {
- unsigned int block;
- unsigned int block_count;
+ unsigned long block;
+ unsigned long block_count;
int block_present;
int last_block_present;
+ int len;
+ size_t last_len = 0;
+ unsigned long last_block_count = 0;
int rc;
- DBGC ( slam, "SLAM %p asking for ", slam );
+ DBGC ( slam, "SLAM %p asking for", slam );
/* Walk bitmap to construct list */
block_count = 0;
@@ -253,27 +256,43 @@ static int slam_build_block_list ( struct slam_request *slam,
for ( block = 0 ; block < slam->num_blocks ; block++ ) {
block_present = ( !! bitmap_test ( &slam->bitmap, block ) );
if ( block_present != last_block_present ) {
- if ( ( rc = slam_put_value ( slam, iobuf,
- block_count ) ) != 0 ) {
- DBGC ( slam, "...\n" );
- return rc;
- }
- DBGC ( slam, "%c%d",
+ if ( ( len = slam_put_value ( slam, iobuf, block_count,
+ ( sizeof ( block ) + 1 ) ) ) < 0 )
+ goto truncated;
+ DBGC ( slam, "%c%ld",
( last_block_present ? ' ' : '-' ),
( last_block_present ? block : block - 1 ) );
- block_count = 0;
+ last_len = len;
+ last_block_count = block_count;
last_block_present = block_present;
+ block_count = 0;
}
block_count++;
}
- if ( ( rc = slam_put_value ( slam, iobuf, block_count ) ) != 0 ) {
- DBGC ( slam, "...\n" );
- return rc;
- }
- DBGC ( slam, "%c%d\n", ( last_block_present ? ' ' : '-' ),
+ if ( ( len = slam_put_value ( slam, iobuf, block_count,
+ ( sizeof ( block ) + 1 ) ) ) < 0 )
+ goto truncated;
+ DBGC ( slam, "%c%ld\n", ( last_block_present ? ' ' : '-' ),
( last_block_present ? block : block - 1 ) );
return 0;
+
+ truncated:
+ rc = len;
+ block -= block_count;
+ assert ( last_len != 0 ); /* Cannot truncate on first entry */
+ if ( last_block_present ) {
+ /* Replace last missing-blocks number */
+ DBGC ( slam, "#" );
+ iob_unput ( iobuf, last_len );
+ block -= last_block_count;
+ }
+ /* Report all remaining blocks as missing */
+ block_count = ( slam->num_blocks - block );
+ DBGC ( slam, "-%ld\n", ( slam->num_blocks - 1 ) );
+ len = slam_put_value ( slam, iobuf, block_count, 1 );
+ assert ( len > 0 );
+ return rc;
}
/**