Skip to content

Commit

Permalink
Make CoAP block size configurable at build- and run-time
Browse files Browse the repository at this point in the history
This patch makes the CoAP block size, used in block transfers,
configurable in two ways.
 1. Build-time configurable default value via a cmake variable.
 2. Run-time configurable via new -S command line argument.

Add two new functions to the interface:
 - lwm2m_validate_block_size()
 - lwm2m_set_block_size()

The new default value for the block size will now be 1024
with no further configuration. This avoids block transfers
in common use-cases.

Signed-off-by: Marc Lasch <marc.lasch@husqvarnagroup.com>
  • Loading branch information
mlasch committed Apr 27, 2021
1 parent 4a8aa2b commit b65fb0f
Show file tree
Hide file tree
Showing 13 changed files with 180 additions and 50 deletions.
55 changes: 39 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Several compilation switches are used:
-DLWM2M_VERSION="1.0" to cmake.
- LWM2M_RAW_BLOCK1_REQUESTS For low memory client devices where it is not possible to keep a large post or put request in memory to be parsed (typically a firmware write).
This option enable each unprocessed block 1 payload to be passed to the application, typically to be stored to a flash memory.
- COAP_DEFAULT_BLOCK_SIZE Set the default block size used for CoAP block transfers.

Depending on your platform, you need to define LWM2M_BIG_ENDIAN or LWM2M_LITTLE_ENDIAN.
LWM2M_CLIENT_MODE and LWM2M_SERVER_MODE can be defined at the same time.
Expand Down Expand Up @@ -110,7 +111,15 @@ The lwm2mserver listens on UDP port 5683. It features a basic command line
interface. Type 'help' for a list of supported commands.

Options are:
- -4 Use IPv4 connection. Default: IPv6 connection
```
Usage: lwm2mserver [OPTION]
Launch a LWM2M server on localhost.
Options:
-4 Use IPv4 connection. Default: IPv6 connection
-l PORT Set the local UDP port of the Server. Default: 5683
-S BYTES CoAP block size. Options: 16, 32, 64, 128, 256, 512, 1024. Default: 1024
```

### Test client example
* Create a build directory and change to that.
Expand Down Expand Up @@ -159,18 +168,27 @@ The lwm2mclient opens udp port 56830 and tries to register to a LWM2M Server at
list of supported commands.

Options are:
- -n NAME Set the endpoint name of the Client. Default: testlwm2mclient
- -l PORT Set the local UDP port of the Client. Default: 56830
- -h HOST Set the hostname of the LWM2M Server to connect to. Default: localhost
- -p HOST Set the port of the LWM2M Server to connect to. Default: 5683
- -4 Use IPv4 connection. Default: IPv6 connection
- -t TIME Set the lifetime of the Client. Default: 300
- -b Bootstrap requested.
- -c Change battery level over time.

```
Usage: lwm2mclient [OPTION]
Launch a LWM2M client.
Options:
-n NAME Set the endpoint name of the Client. Default: testlwm2mclient
-l PORT Set the local UDP port of the Client. Default: 56830
-h HOST Set the hostname of the LWM2M Server to connect to. Default: localhost
-p PORT Set the port of the LWM2M Server to connect to. Default: 5683
-4 Use IPv4 connection. Default: IPv6 connection
-t TIME Set the lifetime of the Client. Default: 300
-b Bootstrap requested.
-c Change battery level over time.
-S BYTES CoAP block size. Options: 16, 32, 64, 128, 256, 512, 1024. Default: 1024
```

If DTLS feature enable:
- -i Set the device management or bootstrap server PSK identity. If not set use none secure mode
- -s Set the device management or bootstrap server Pre-Shared-Key. If not set use none secure mode
```
-i Set the device management or bootstrap server PSK identity. If not set use none secure mode
-s Set the device management or bootstrap server Pre-Shared-Key. If not set use none secure mode
```

To launch a bootstrap session:
``./lwm2mclient -b``
Expand All @@ -194,10 +212,15 @@ LWM2M objects:
The lightclient does not feature any command-line interface.

Options are:
- -n NAME Set the endpoint name of the Client. Default: testlightclient
- -l PORT Set the local UDP port of the Client. Default: 56830
- -4 Use IPv4 connection. Default: IPv6 connection

```
Usage: lwm2mclient [OPTION]
Launch a LWM2M client.
Options:
-n NAME Set the endpoint name of the Client. Default: testlightclient
-l PORT Set the local UDP port of the Client. Default: 56830
-4 Use IPv4 connection. Default: IPv6 connection
-S BYTES CoAP block size. Options: 16, 32, 64, 128, 256, 512, 1024. Default: 1024
```
### Bootstrap Server example
* Create a build directory and change to that.
* ``cmake [wakaama directory]/examples/bootstrap_server``
Expand Down
8 changes: 8 additions & 0 deletions coap/coap.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
set(COAP_SOURCES_DIR ${CMAKE_CURRENT_LIST_DIR})
set(COAP_HEADERS_DIR ${CMAKE_CURRENT_LIST_DIR})

# The maximum buffer size that is provided for resource responses and must be respected due to the limited IP buffer.
# Larger data must be handled by the resource and will be sent chunk-wise through a TCP stream or CoAP blocks.
# Block size is set to 1024 bytes if not specified otherwise to avoid block transfers in common use cases.
set(COAP_DEFAULT_BLOCK_SIZE 1024 CACHE STRING "Set default coap block size")
if (COAP_DEFAULT_BLOCK_SIZE)
add_compile_definitions(COAP_DEFAULT_BLOCK_SIZE=${COAP_DEFAULT_BLOCK_SIZE})
endif()

set(COAP_SOURCES
${COAP_SOURCES_DIR}/transaction.c
${COAP_SOURCES_DIR}/block.c
Expand Down
8 changes: 0 additions & 8 deletions coap/er-coap-13/er-coap-13.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,6 @@
#include <stdint.h>
#include <stddef.h> /* for size_t */

/*
* The maximum buffer size that is provided for resource responses and must be respected due to the limited IP buffer.
* Larger data must be handled by the resource and will be sent chunk-wise through a TCP stream or CoAP blocks.
*/
#ifndef REST_MAX_CHUNK_SIZE
#define REST_MAX_CHUNK_SIZE 128
#endif

#define COAP_DEFAULT_MAX_AGE 60
#define COAP_RESPONSE_TIMEOUT 2
#define COAP_MAX_RETRANSMIT 4
Expand Down
10 changes: 6 additions & 4 deletions coap/transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -488,17 +488,19 @@ void transaction_set_payload(lwm2m_transaction_t * transaction, uint8_t * buffer
transaction->payload = buffer;
transaction->payload_len = length;

if ( length > REST_MAX_CHUNK_SIZE ){
coap_set_header_block1(transaction->message, 0, true, REST_MAX_CHUNK_SIZE);
if (length > coap_block_size)
{
coap_set_header_block1(transaction->message, 0, true, coap_block_size);
}

coap_set_payload(transaction->message, buffer, MIN(length, REST_MAX_CHUNK_SIZE));
coap_set_payload(transaction->message, buffer, MIN(length, coap_block_size));
}

bool transaction_free_userData(lwm2m_context_t * context, lwm2m_transaction_t * transaction)
{
lwm2m_transaction_t * target = context->transactionList;
while (target != NULL){
while (target != NULL)
{
if (target->userData == transaction->userData && target != transaction) return false;
target = target->next;
}
Expand Down
2 changes: 2 additions & 0 deletions core/internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@

#define ATTR_FLAG_NUMERIC (uint8_t)(LWM2M_ATTR_FLAG_LESS_THAN | LWM2M_ATTR_FLAG_GREATER_THAN | LWM2M_ATTR_FLAG_STEP)

extern uint16_t coap_block_size;

typedef struct
{
uint16_t clientID;
Expand Down
59 changes: 39 additions & 20 deletions core/packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,26 @@ Contains code snippets which are:

#include <stdio.h>

uint16_t coap_block_size = COAP_DEFAULT_BLOCK_SIZE;

void lwm2m_set_block_size(uint16_t coap_block_size_arg)
{
coap_block_size = coap_block_size_arg;
}

bool lwm2m_validate_block_size(uint16_t coap_block_size_arg)
{
uint16_t valid_block_sizes[7] = {16, 32, 64, 128, 256, 512, 1024};
int i;
for (i=0;i<7;i++)
{
if (coap_block_size_arg == valid_block_sizes[i])
{
return true;
}
}
return false;
}

static void handle_reset(lwm2m_context_t * contextP,
void * fromSessionH,
Expand Down Expand Up @@ -349,7 +369,7 @@ static int prv_change_to_block1(lwm2m_context_t * contextP, void * sessionH, uin
block_size = 16 << n;
}

block_size = MIN(block_size, REST_MAX_CHUNK_SIZE);
block_size = MIN(block_size, coap_block_size);

return prv_send_new_block1(contextP, transaction, 0, block_size);
}
Expand Down Expand Up @@ -407,7 +427,7 @@ static int prv_send_get_block2(lwm2m_context_t * contextP,
if (next == NULL) return COAP_500_INTERNAL_SERVER_ERROR;

// set block2 header
coap_set_header_block2(next->message, block2_num, 0, MIN(block2_size, REST_MAX_CHUNK_SIZE));
coap_set_header_block2(next->message, block2_num, 0, MIN(block2_size, coap_block_size));

// update block2data to nect expected mid
coap_block2_set_expected_mid(blockDataHead, currentMID, nextMID);
Expand Down Expand Up @@ -451,7 +471,7 @@ void lwm2m_handle_packet(lwm2m_context_t * contextP,
if (message->code >= COAP_GET && message->code <= COAP_DELETE)
{
uint32_t block_num = 0;
uint16_t block_size = REST_MAX_CHUNK_SIZE;
uint16_t block_size = coap_block_size;
uint32_t block_offset = 0;

/* prepare response */
Expand All @@ -472,17 +492,17 @@ void lwm2m_handle_packet(lwm2m_context_t * contextP,
coap_set_header_token(response, message->token, message->token_len);
}

if (message->payload_len > REST_MAX_CHUNK_SIZE)
if (message->payload_len > coap_block_size)
{
coap_error_code = COAP_413_ENTITY_TOO_LARGE;

if (IS_OPTION(message, COAP_OPTION_BLOCK1)){
uint32_t block1_num;
uint8_t block1_more;
coap_get_header_block1(message, &block1_num, &block1_more, NULL, NULL);
coap_set_header_block1(response, block1_num, block1_more, REST_MAX_CHUNK_SIZE);
coap_set_header_block1(response, block1_num, block1_more, coap_block_size);
} else {
coap_set_header_block1(response, 0, 1, REST_MAX_CHUNK_SIZE);
coap_set_header_block1(response, 0, 1, coap_block_size);
}
}
else if (IS_OPTION(message, COAP_OPTION_BLOCK1))
Expand Down Expand Up @@ -531,7 +551,7 @@ void lwm2m_handle_packet(lwm2m_context_t * contextP,

// parse block1 header
coap_get_header_block1(message, &block1_num, &block1_more, &block1_size, NULL);
LOG_ARG("Blockwise: block1 request NUM %u (SZX %u/ SZX Max%u) MORE %u", block1_num, block1_size, REST_MAX_CHUNK_SIZE, block1_more);
LOG_ARG("Blockwise: block1 request NUM %u (SZX %u/ SZX Max%u) MORE %u", block1_num, block1_size, coap_block_size, block1_more);

char * uri = coap_get_packet_uri_as_string(message);
if (uri == NULL){
Expand All @@ -553,7 +573,7 @@ void lwm2m_handle_packet(lwm2m_context_t * contextP,
message->payload_len = complete_buffer_size;
}
#endif
block1_size = MIN(block1_size, REST_MAX_CHUNK_SIZE);
block1_size = MIN(block1_size, coap_block_size);
coap_set_header_block1(response, block1_num, block1_more, block1_size);
}
}
Expand All @@ -574,8 +594,8 @@ void lwm2m_handle_packet(lwm2m_context_t * contextP,
/* get offset for blockwise transfers */
if (coap_get_header_block2(message, &block_num, NULL, &block_size, &block_offset))
{
LOG_ARG("Blockwise: block request %u (%u/%u) @ %u bytes", block_num, block_size, REST_MAX_CHUNK_SIZE, block_offset);
block_size = MIN(block_size, REST_MAX_CHUNK_SIZE);
LOG_ARG("Blockwise: block request %u (%u/%u) @ %u bytes", block_num, block_size, coap_block_size, block_offset);
block_size = MIN(block_size, coap_block_size);
}

if (block_offset >= response->payload_len)
Expand All @@ -591,9 +611,9 @@ void lwm2m_handle_packet(lwm2m_context_t * contextP,
coap_set_payload(response, response->payload+block_offset, MIN(response->payload_len - block_offset, block_size));
} /* if (valid offset) */
}
else if (response->payload_len > REST_MAX_CHUNK_SIZE){
coap_set_header_block2(response, 0, response->payload_len > REST_MAX_CHUNK_SIZE, REST_MAX_CHUNK_SIZE);
coap_set_payload(response, response->payload, REST_MAX_CHUNK_SIZE);
else if (response->payload_len > coap_block_size){
coap_set_header_block2(response, 0, response->payload_len > coap_block_size, coap_block_size);
coap_set_payload(response, response->payload, coap_block_size);
}

coap_error_code = message_send(contextP, response, fromSessionH);
Expand Down Expand Up @@ -631,7 +651,7 @@ void lwm2m_handle_packet(lwm2m_context_t * contextP,
{
case COAP_TYPE_NON:
case COAP_TYPE_CON:
if (message->payload_len > REST_MAX_CHUNK_SIZE)
if (message->payload_len > coap_block_size)
{
#ifdef LWM2M_CLIENT_MODE
// get server
Expand All @@ -650,7 +670,7 @@ void lwm2m_handle_packet(lwm2m_context_t * contextP,
if (peerP != NULL)
{
// retry as a block2 request
prv_send_get_block2(contextP, fromSessionH, peerP->blockData, message->mid, 0, REST_MAX_CHUNK_SIZE);
prv_send_get_block2(contextP, fromSessionH, peerP->blockData, message->mid, 0, coap_block_size);
}
transaction_handleResponse(contextP, fromSessionH, message, NULL);
} else {
Expand All @@ -667,7 +687,7 @@ void lwm2m_handle_packet(lwm2m_context_t * contextP,
if (!done && message->type == COAP_TYPE_CON )
{
coap_init_message(response, COAP_TYPE_ACK, 0, message->mid);
if (message->payload_len > REST_MAX_CHUNK_SIZE)
if (message->payload_len > coap_block_size)
{
coap_set_status_code(response, COAP_413_ENTITY_TOO_LARGE);
}
Expand All @@ -683,7 +703,7 @@ void lwm2m_handle_packet(lwm2m_context_t * contextP,
break;

case COAP_TYPE_ACK:
if (message->payload_len > REST_MAX_CHUNK_SIZE)
if (message->payload_len > coap_block_size)
{
#ifdef LWM2M_CLIENT_MODE
// get server
Expand All @@ -702,7 +722,7 @@ void lwm2m_handle_packet(lwm2m_context_t * contextP,
if (peerP != NULL)
{
// retry as a block2 request
prv_send_get_block2(contextP, fromSessionH, peerP->blockData, message->mid, 0, REST_MAX_CHUNK_SIZE);
prv_send_get_block2(contextP, fromSessionH, peerP->blockData, message->mid, 0, coap_block_size);
}
transaction_handleResponse(contextP, fromSessionH, message, NULL);
}
Expand Down Expand Up @@ -760,7 +780,7 @@ void lwm2m_handle_packet(lwm2m_context_t * contextP,

// parse block2 header
coap_get_header_block2(message, &block2_num, &block2_more, &block2_size, NULL);
LOG_ARG("Blockwise: block2 response NUM %u (SZX %u/ SZX Max%u) MORE %u", block2_num, block2_size, REST_MAX_CHUNK_SIZE, block2_more);
LOG_ARG("Blockwise: block2 response NUM %u (SZX %u/ SZX Max%u) MORE %u", block2_num, block2_size, coap_block_size, block2_more);

// handle block 2
coap_error_code = coap_block2_handler(&peerP->blockData, message->mid, message->payload, message->payload_len, block2_size, block2_num, block2_more, &complete_buffer, &complete_buffer_size);
Expand Down Expand Up @@ -852,4 +872,3 @@ uint8_t message_send(lwm2m_context_t * contextP,

return result;
}

1 change: 1 addition & 0 deletions core/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
*/

#include "internals.h"

#include <ctype.h>
#include <math.h>
#include <stdlib.h>
Expand Down
1 change: 1 addition & 0 deletions examples/bootstrap_server/README
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Options:
-f FILE Specify BootStrap Information file. Default: ./bootstrap_info.ini
-l PORT Set the local UDP port of the Bootstrap Server. Default: 5685
-4 Use IPv4 connection. Default: IPv6 connection
-S BYTES CoAP block size. Options: 16, 32, 64, 128, 256, 512, 1024. Default: 1024

When it receives a Bootstrap Request from a LWM2M Client, it sends commands as
described in the Bootstrap Information file.
Expand Down
21 changes: 20 additions & 1 deletion examples/bootstrap_server/bootstrap_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ void print_usage(char * filename,
fprintf(stdout, " -f FILE\tSpecify BootStrap Information file. Default: ./%s\r\n", filename);
fprintf(stdout, " -l PORT\tSet the local UDP port of the Bootstrap Server. Default: %s\r\n", port);
fprintf(stdout, " -4\t\tUse IPv4 connection. Default: IPv6 connection\r\n");
fprintf(stdout, " -S BYTES\tCoAP block size. Options: 16, 32, 64, 128, 256, 512, 1024. Default: %d\r\n", COAP_DEFAULT_BLOCK_SIZE);
fprintf(stdout, "\r\n");
}

Expand Down Expand Up @@ -617,6 +618,24 @@ int main(int argc, char *argv[])
case '4':
data.addressFamily = AF_INET;
break;
case 'S':
opt++;
if (opt >= argc)
{
print_usage(filename, port);
return 0;
}
uint16_t coap_block_size_arg;
if (1 == sscanf(argv[opt], "%hu", &coap_block_size_arg) && lwm2m_validate_block_size(coap_block_size_arg))
{
lwm2m_set_block_size(coap_block_size_arg);
break;
}
else
{
print_usage(filename, port);
return 0;
}
default:
print_usage(filename, port);
return 0;
Expand Down Expand Up @@ -715,7 +734,7 @@ int main(int argc, char *argv[])
in_port_t port;
connection_t * connP;

s[0] = 0;
s[0] = 0;
if (AF_INET == addr.ss_family)
{
struct sockaddr_in *saddr = (struct sockaddr_in *)&addr;
Expand Down
Loading

0 comments on commit b65fb0f

Please sign in to comment.