net: net_pkt_append: Refactor to return length of data actually added

For stream-based protocols (TCP), adding less data than requested
("short write") is generally not a problem - the rest of data can
be sent in the next packet. So, make net_pkt_append() return length
of written data instead of just bool flag, which makes it closer
to the behavior of POSIX send()/write() calls.

There're many users of older net_pkt_append() in the codebase
however, so net_pkt_append_all() convenience function is added which
keeps returning a boolean flag. All current users were converted to
this function, except for two:

samples/net/http_server/src/ssl_utils.c
samples/net/mbedtls_sslclient/src/tcp.c

Both are related to TLS and implement mbedTLS "tx callback", which
follows POSIX short-write semantics. Both cases also had a code to
workaround previous boolean-only behavior of net_pkt_append() - after
calling it, they measured length of the actual data added (but only
in case of successful return of net_pkt_append(), so that didn't
really help). So, these 2 cases are already improved.

Jira: ZEP-1984

Change-Id: Ibaf7c029b15e91b516d73dab3612eed190ee982b
Signed-off-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>
This commit is contained in:
Paul Sokolovsky 2017-04-21 13:55:45 +03:00 committed by Jukka Rissanen
parent 3051fc2035
commit 25307d5331
25 changed files with 99 additions and 80 deletions

View File

@ -234,7 +234,7 @@ static inline bool telnet_send(void)
struct line_buf *lb = telnet_rb_get_line_out();
if (lb) {
net_pkt_append(out_pkt, lb->len, lb->buf, K_FOREVER);
net_pkt_append_all(out_pkt, lb->len, lb->buf, K_FOREVER);
/* We reinitialize the line buffer */
lb->len = 0;
@ -258,7 +258,7 @@ static int telnet_console_out_nothing(int c)
static inline void telnet_command_send_reply(u8_t *msg, u16_t len)
{
net_pkt_append(out_pkt, len, msg, K_FOREVER);
net_pkt_append_all(out_pkt, len, msg, K_FOREVER);
net_context_send(out_pkt, telnet_sent_cb,
K_NO_WAIT, NULL, NULL);

View File

@ -853,11 +853,34 @@ int net_frag_linear_copy(struct net_buf *dst, struct net_buf *src,
bool net_pkt_compact(struct net_pkt *pkt);
/**
* @brief Append data to last fragment in fragment list of a packet
* @brief Append data to fragment list of a packet
*
* @details Append data to last fragment. If there is not enough space in
* last fragment then new data fragment will be created and will be added to
* fragment list. Caller has to take care of endianness if needed.
* last fragment then more data fragments will be added, unless there are
* no free fragments and timeout occurs.
*
* @param pkt Network packet.
* @param len Total length of input data
* @param data Data to be added
* @param timeout Affects the action taken should the net buf pool be empty.
* If K_NO_WAIT, then return immediately. If K_FOREVER, then
* wait as long as necessary. Otherwise, wait up to the specified
* number of milliseconds before timing out.
*
* @return Length of data actually added. This may be less than input
* length if other timeout than K_FOREVER was used, and there
* were no free fragments in a pool to accommodate all data.
*/
u16_t net_pkt_append(struct net_pkt *pkt, u16_t len, const u8_t *data,
s32_t timeout);
/**
* @brief Append all data to fragment list of a packet (or fail)
*
* @details Append data to last fragment. If there is not enough space in
* last fragment then more data fragments will be added. Return unsuccessful
* status if there are no free fragments to accommodate all data and timeout
* occurs.
*
* @param pkt Network packet.
* @param len Total length of input data
@ -868,11 +891,14 @@ bool net_pkt_compact(struct net_pkt *pkt);
* number of milliseconds before timing out.
*
* @return True if all the data is placed at end of fragment list,
* False otherwise (In-case of false pkt might contain input
* data in the process of placing into fragments).
* false otherwise (in which case packet may contain incomplete
* input data).
*/
bool net_pkt_append(struct net_pkt *pkt, u16_t len, const u8_t *data,
s32_t timeout);
static inline bool net_pkt_append_all(struct net_pkt *pkt, u16_t len,
const u8_t *data, int32_t timeout)
{
return net_pkt_append(pkt, len, data, timeout) == len;
}
/**
* @brief Append u8_t data to last fragment in fragment list of a packet
@ -890,7 +916,7 @@ bool net_pkt_append(struct net_pkt *pkt, u16_t len, const u8_t *data,
*/
static inline bool net_pkt_append_u8(struct net_pkt *pkt, u8_t data)
{
return net_pkt_append(pkt, 1, &data, K_FOREVER);
return net_pkt_append_all(pkt, 1, &data, K_FOREVER);
}
/**
@ -911,7 +937,7 @@ static inline bool net_pkt_append_be16(struct net_pkt *pkt, u16_t data)
{
u16_t value = sys_cpu_to_be16(data);
return net_pkt_append(pkt, sizeof(u16_t), (u8_t *)&value,
return net_pkt_append_all(pkt, sizeof(u16_t), (u8_t *)&value,
K_FOREVER);
}
@ -933,7 +959,7 @@ static inline bool net_pkt_append_be32(struct net_pkt *pkt, u32_t data)
{
u32_t value = sys_cpu_to_be32(data);
return net_pkt_append(pkt, sizeof(u32_t), (u8_t *)&value,
return net_pkt_append_all(pkt, sizeof(u32_t), (u8_t *)&value,
K_FOREVER);
}
@ -955,7 +981,7 @@ static inline bool net_pkt_append_le32(struct net_pkt *pkt, u32_t data)
{
u32_t value = sys_cpu_to_le32(data);
return net_pkt_append(pkt, sizeof(u32_t), (u8_t *)&value,
return net_pkt_append_all(pkt, sizeof(u32_t), (u8_t *)&value,
K_FOREVER);
}

View File

@ -63,7 +63,7 @@ int udp_tx(void *context, const unsigned char *buf, size_t size)
return MBEDTLS_ERR_SSL_ALLOC_FAILED;
}
rc = net_pkt_append(send_pkt, size, (u8_t *) buf, K_FOREVER);
rc = net_pkt_append_all(send_pkt, size, (u8_t *) buf, K_FOREVER);
if (!rc) {
return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
}

View File

@ -53,7 +53,7 @@ int udp_tx(void *context, const unsigned char *buf, size_t size)
return -EIO;
}
rc = net_pkt_append(send_pkt, size, (u8_t *) buf, K_FOREVER);
rc = net_pkt_append_all(send_pkt, size, (u8_t *) buf, K_FOREVER);
if (!rc) {
printk("cannot write buf\n");
return -EIO;

View File

@ -400,7 +400,7 @@ static struct net_pkt *prepare_send_pkt(const char *name,
NET_ASSERT(send_pkt);
status = net_pkt_append(send_pkt, expecting_len, lorem_ipsum,
status = net_pkt_append_all(send_pkt, expecting_len, lorem_ipsum,
K_FOREVER);
if (!status) {
NET_ERR("%s: cannot create send pkt", name);

View File

@ -76,13 +76,7 @@ int ssl_tx(void *context, const unsigned char *buf, size_t size)
return MBEDTLS_ERR_SSL_ALLOC_FAILED;
}
rc = net_pkt_append(send_buf, size, (u8_t *) buf, K_FOREVER);
if (!rc) {
net_pkt_unref(send_buf);
return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
}
len = net_buf_frags_len(send_buf);
len = net_pkt_append(send_buf, size, (u8_t *) buf, K_FOREVER);
rc = net_context_send(send_buf, ssl_sent, K_NO_WAIT, NULL, ctx);

View File

@ -145,7 +145,7 @@ transmit(struct net_context *ctx, char buffer[], size_t len)
return -ENOMEM;
}
if (!net_pkt_append(send_pkt, len, buffer, K_FOREVER)) {
if (!net_pkt_append_all(send_pkt, len, buffer, K_FOREVER)) {
return -EINVAL;
}

View File

@ -86,7 +86,7 @@ int udp_tx(void *context, const unsigned char *buf, size_t size)
return -EIO;
}
rc = net_pkt_append(send_buf, size, (u8_t *) buf, K_FOREVER);
rc = net_pkt_append_all(send_buf, size, (u8_t *) buf, K_FOREVER);
if (!rc) {
printk("cannot write buf\n");
net_pkt_unref(send_buf);

View File

@ -66,7 +66,7 @@ int udp_tx(void *context, const unsigned char *buf, size_t size)
return -EIO;
}
rc = net_pkt_append(send_buf, size, (u8_t *) buf, K_FOREVER);
rc = net_pkt_append_all(send_buf, size, (u8_t *) buf, K_FOREVER);
if (!rc) {
printk("cannot write buf\n");
return -EIO;

View File

@ -55,13 +55,7 @@ int tcp_tx(void *context, const unsigned char *buf, size_t size)
return -EIO;
}
rc = net_pkt_append(send_pkt, size, (u8_t *) buf, K_FOREVER);
if (!rc) {
printk("cannot write buf\n");
return -EIO;
}
len = net_pkt_get_len(send_pkt);
len = net_pkt_append(send_pkt, size, (u8_t *) buf, K_FOREVER);
rc = net_context_send(send_pkt, NULL, ctx->timeout, NULL, NULL);

View File

@ -107,7 +107,8 @@ static int transmitv(struct net_context *conn, int iovcnt,
}
for (i = 0; i < iovcnt; i++) {
if (!net_pkt_append(pkt, iov[i].len, iov[i].base, K_FOREVER)) {
if (!net_pkt_append_all(pkt, iov[i].len, iov[i].base,
K_FOREVER)) {
net_pkt_unref(pkt);
return -ENOMEM;

View File

@ -71,7 +71,7 @@ void zperf_tcp_upload(struct net_context *ctx,
net_pkt_frag_add(pkt, frag);
/* Fill in the TCP payload */
st = net_pkt_append(pkt, sizeof(sample_packet),
st = net_pkt_append_all(pkt, sizeof(sample_packet),
sample_packet, K_FOREVER);
if (!st) {
printk(TAG "ERROR! Failed to fill packet\n");

View File

@ -108,7 +108,7 @@ static inline void zperf_upload_fin(struct net_context *context,
datagram.tv_usec = htonl(HW_CYCLES_TO_USEC(end_time) %
USEC_PER_SEC);
status = net_pkt_append(pkt, sizeof(datagram),
status = net_pkt_append_all(pkt, sizeof(datagram),
(u8_t *)&datagram, K_FOREVER);
if (!status) {
printk(TAG "ERROR! Cannot append datagram data\n");
@ -254,7 +254,7 @@ void zperf_udp_upload(struct net_context *context,
datagram.tv_usec =
htonl(HW_CYCLES_TO_USEC(loop_time) % USEC_PER_SEC);
status = net_pkt_append(pkt, sizeof(datagram),
status = net_pkt_append_all(pkt, sizeof(datagram),
(u8_t *)&datagram, K_FOREVER);
if (!status) {
printk(TAG "ERROR! Cannot append datagram data\n");

View File

@ -157,7 +157,7 @@ net_dhcpv4_msg_type_name(enum dhcpv4_msg_type msg_type)
/* Add magic cookie to DCHPv4 messages */
static inline bool add_cookie(struct net_pkt *pkt)
{
return net_pkt_append(pkt, sizeof(magic_cookie),
return net_pkt_append_all(pkt, sizeof(magic_cookie),
magic_cookie, K_FOREVER);
}
@ -173,7 +173,7 @@ static bool add_option_length_value(struct net_pkt *pkt, u8_t option,
return false;
}
if (!net_pkt_append(pkt, size, value, K_FOREVER)) {
if (!net_pkt_append_all(pkt, size, value, K_FOREVER)) {
return false;
}
@ -197,7 +197,7 @@ static bool add_req_options(struct net_pkt *pkt)
DHCPV4_OPTIONS_ROUTER,
DHCPV4_OPTIONS_DNS_SERVER };
return net_pkt_append(pkt, sizeof(data), data, K_FOREVER);
return net_pkt_append_all(pkt, sizeof(data), data, K_FOREVER);
}
static bool add_server_id(struct net_pkt *pkt, const struct in_addr *addr)

View File

@ -2388,12 +2388,12 @@ static struct net_pkt *create_mldv2(struct net_pkt *pkt,
net_pkt_append_u8(pkt, record_type);
net_pkt_append_u8(pkt, 0); /* aux data len */
net_pkt_append_be16(pkt, num_sources); /* number of addresses */
net_pkt_append(pkt, sizeof(struct in6_addr), addr->s6_addr,
net_pkt_append_all(pkt, sizeof(struct in6_addr), addr->s6_addr,
K_FOREVER);
if (num_sources > 0) {
/* All source addresses, RFC 3810 ch 3 */
net_pkt_append(pkt, sizeof(struct in6_addr),
net_pkt_append_all(pkt, sizeof(struct in6_addr),
net_ipv6_unspecified_address()->s6_addr,
K_FOREVER);
}
@ -3196,7 +3196,7 @@ static int send_ipv6_fragment(struct net_if *iface,
NET_IPV6_NEXTHDR_FRAG);
/* Then just add the fragmentation header. */
ret = net_pkt_append(ipv6, sizeof(hdr), (u8_t *)&hdr,
ret = net_pkt_append_all(ipv6, sizeof(hdr), (u8_t *)&hdr,
FRAG_BUF_WAIT);
if (!ret) {
ret = -ENOMEM;

View File

@ -1079,11 +1079,12 @@ bool net_pkt_compact(struct net_pkt *pkt)
* the data in current fragment then create new fragment and add it to
* the buffer. It assumes that the buffer has at least one fragment.
*/
static inline bool net_pkt_append_bytes(struct net_pkt *pkt,
static inline u16_t net_pkt_append_bytes(struct net_pkt *pkt,
const u8_t *value,
u16_t len, s32_t timeout)
{
struct net_buf *frag = net_buf_frag_last(pkt->frags);
u16_t added_len = 0;
do {
u16_t count = min(len, net_buf_tailroom(frag));
@ -1091,36 +1092,38 @@ static inline bool net_pkt_append_bytes(struct net_pkt *pkt,
memcpy(data, value, count);
len -= count;
added_len += count;
value += count;
if (len == 0) {
return true;
return added_len;
}
frag = net_pkt_get_frag(pkt, timeout);
if (!frag) {
return false;
return added_len;
}
net_pkt_frag_add(pkt, frag);
} while (1);
return false;
/* Unreachable */
return 0;
}
bool net_pkt_append(struct net_pkt *pkt, u16_t len, const u8_t *data,
u16_t net_pkt_append(struct net_pkt *pkt, u16_t len, const u8_t *data,
s32_t timeout)
{
struct net_buf *frag;
if (!pkt || !data) {
return false;
return 0;
}
if (!pkt->frags) {
frag = net_pkt_get_frag(pkt, timeout);
if (!frag) {
return false;
return 0;
}
net_pkt_frag_add(pkt, frag);

View File

@ -1586,7 +1586,7 @@ static int shell_cmd_tcp(int argc, char *argv[])
return 0;
}
ret = net_pkt_append(pkt, strlen(argv[arg]),
ret = net_pkt_append_all(pkt, strlen(argv[arg]),
argv[arg], TCP_TIMEOUT);
if (!ret) {
printk("Cannot build msg (out of pkts)\n");

View File

@ -473,7 +473,7 @@ int net_rpl_dio_send(struct net_if *iface,
/* Flags and reserved are set to 0 */
net_pkt_append_be16(pkt, 0);
net_pkt_append(pkt, sizeof(struct in6_addr), dag->dag_id.s6_addr,
net_pkt_append_all(pkt, sizeof(struct in6_addr), dag->dag_id.s6_addr,
K_FOREVER);
if (instance->mc.type != NET_RPL_MC_NONE) {
@ -533,7 +533,7 @@ int net_rpl_dio_send(struct net_if *iface,
net_pkt_append_be32(pkt, dag->prefix_info.lifetime);
net_pkt_append_be32(pkt, 0); /* reserved */
net_pkt_append(pkt, sizeof(struct in6_addr),
net_pkt_append_all(pkt, sizeof(struct in6_addr),
dag->prefix_info.prefix.s6_addr,
K_FOREVER);
@ -3053,7 +3053,7 @@ int net_rpl_dao_send(struct net_if *iface,
net_pkt_append_u8(pkt, rpl_dao_sequence);
#if defined(CONFIG_NET_RPL_DAO_SPECIFY_DAG)
net_pkt_append(pkt, sizeof(dag->dag_id), dag->dag_id.s6_addr,
net_pkt_append_all(pkt, sizeof(dag->dag_id), dag->dag_id.s6_addr,
K_FOREVER);
#endif
@ -3064,7 +3064,7 @@ int net_rpl_dao_send(struct net_if *iface,
net_pkt_append_u8(pkt, 2 + prefix_bytes);
net_pkt_append_u8(pkt, 0); /* reserved */
net_pkt_append_u8(pkt, prefixlen);
net_pkt_append(pkt, prefix_bytes, prefix->s6_addr, K_FOREVER);
net_pkt_append_all(pkt, prefix_bytes, prefix->s6_addr, K_FOREVER);
net_pkt_append_u8(pkt, NET_RPL_OPTION_TRANSIT);
net_pkt_append_u8(pkt, 4); /* length */

View File

@ -667,7 +667,7 @@ static int dns_write(struct dns_resolve_context *ctx,
goto quit;
}
ret = net_pkt_append(pkt, dns_data->len, dns_data->data,
ret = net_pkt_append_all(pkt, dns_data->len, dns_data->data,
ctx->buf_timeout);
if (ret < 0) {
ret = -ENOMEM;

View File

@ -27,35 +27,35 @@ int http_request(struct net_context *net_ctx, s32_t timeout,
return -ENOMEM;
}
if (!net_pkt_append(tx, strlen(req->method), (u8_t *)req->method,
if (!net_pkt_append_all(tx, strlen(req->method), (u8_t *)req->method,
timeout)) {
goto lb_exit;
}
if (!net_pkt_append(tx, strlen(req->url), (u8_t *)req->url,
if (!net_pkt_append_all(tx, strlen(req->url), (u8_t *)req->url,
timeout)) {
goto lb_exit;
}
if (!net_pkt_append(tx, strlen(req->protocol),
if (!net_pkt_append_all(tx, strlen(req->protocol),
(u8_t *)req->protocol, timeout)) {
goto lb_exit;
}
if (!net_pkt_append(tx, strlen(req->header_fields),
if (!net_pkt_append_all(tx, strlen(req->header_fields),
(u8_t *)req->header_fields,
timeout)) {
goto lb_exit;
}
if (req->content_type_value) {
if (!net_pkt_append(tx, strlen(HTTP_CONTENT_TYPE),
if (!net_pkt_append_all(tx, strlen(HTTP_CONTENT_TYPE),
(u8_t *)HTTP_CONTENT_TYPE,
timeout)) {
goto lb_exit;
}
if (!net_pkt_append(tx, strlen(req->content_type_value),
if (!net_pkt_append_all(tx, strlen(req->content_type_value),
(u8_t *)req->content_type_value,
timeout)) {
goto lb_exit;
@ -73,13 +73,13 @@ int http_request(struct net_context *net_ctx, s32_t timeout,
goto lb_exit;
}
if (!net_pkt_append(tx, rc, (u8_t *)content_len_str,
if (!net_pkt_append_all(tx, rc, (u8_t *)content_len_str,
timeout)) {
rc = -ENOMEM;
goto lb_exit;
}
if (!net_pkt_append(tx, req->payload_size,
if (!net_pkt_append_all(tx, req->payload_size,
(u8_t *)req->payload,
timeout)) {
rc = -ENOMEM;
@ -87,7 +87,7 @@ int http_request(struct net_context *net_ctx, s32_t timeout,
}
} else {
if (!net_pkt_append(tx, strlen(HTTP_EOF),
if (!net_pkt_append_all(tx, strlen(HTTP_EOF),
(u8_t *)HTTP_EOF,
timeout)) {
goto lb_exit;

View File

@ -34,7 +34,7 @@ static inline u16_t http_strlen(const char *str)
static int http_add_header(struct net_pkt *tx, s32_t timeout, const char *str)
{
if (net_pkt_append(tx, strlen(str), (u8_t *)str, timeout)) {
if (net_pkt_append_all(tx, strlen(str), (u8_t *)str, timeout)) {
return 0;
}
@ -51,17 +51,18 @@ static int http_add_chunk(struct net_pkt *tx, s32_t timeout, const char *str)
snprintk(chunk_header, sizeof(chunk_header), "%x\r\n", str_len);
if (!net_pkt_append(tx, strlen(chunk_header), chunk_header, timeout)) {
if (!net_pkt_append_all(tx, strlen(chunk_header), chunk_header,
timeout)) {
return -ENOMEM;
}
if (str_len > 0) {
if (!net_pkt_append(tx, str_len, (u8_t *)str, timeout)) {
if (!net_pkt_append_all(tx, str_len, (u8_t *)str, timeout)) {
return -ENOMEM;
}
}
if (!net_pkt_append(tx, strlen(rn), rn, timeout)) {
if (!net_pkt_append_all(tx, strlen(rn), rn, timeout)) {
return -ENOMEM;
}

View File

@ -87,7 +87,7 @@ int mqtt_tx_disconnect(struct mqtt_ctx *ctx)
goto exit_disconnect;
}
rc = net_pkt_append(tx, len, msg, ctx->net_timeout);
rc = net_pkt_append_all(tx, len, msg, ctx->net_timeout);
if (rc != true) {
rc = -ENOMEM;
goto exit_disconnect;
@ -160,7 +160,7 @@ int mqtt_tx_pub_msgs(struct mqtt_ctx *ctx, u16_t id,
goto exit_send;
}
rc = net_pkt_append(tx, len, msg, ctx->net_timeout);
rc = net_pkt_append_all(tx, len, msg, ctx->net_timeout);
if (rc != true) {
rc = -ENOMEM;
goto exit_send;
@ -261,7 +261,7 @@ int mqtt_tx_pingreq(struct mqtt_ctx *ctx)
goto exit_pingreq;
}
rc = net_pkt_append(tx, len, msg, ctx->net_timeout);
rc = net_pkt_append_all(tx, len, msg, ctx->net_timeout);
if (rc != true) {
rc = -ENOMEM;
goto exit_pingreq;

View File

@ -287,7 +287,7 @@ static bool send_iface(struct net_if *iface, int val, bool expect_fail)
pkt = net_pkt_get_reserve_tx(0, K_FOREVER);
net_pkt_set_iface(pkt, iface);
net_pkt_append(pkt, sizeof(data), data, K_FOREVER);
net_pkt_append_all(pkt, sizeof(data), data, K_FOREVER);
ret = net_send_data(pkt);
if (!expect_fail && ret < 0) {

View File

@ -325,7 +325,7 @@ static void send_query(struct net_if *iface)
net_pkt_append_be16(pkt, 3); /* maximum response code */
net_pkt_append_be16(pkt, 0); /* reserved field */
net_pkt_append(pkt, sizeof(struct in6_addr),
net_pkt_append_all(pkt, sizeof(struct in6_addr),
(const u8_t *)net_ipv6_unspecified_address(),
K_FOREVER); /* multicast address */

View File

@ -508,13 +508,13 @@ static int test_pkt_read_append(void)
tfrag = net_buf_frag_last(pkt->frags);
off = tfrag->len;
if (!net_pkt_append(pkt, (u16_t)sizeof(test_rw_short),
if (!net_pkt_append_all(pkt, (u16_t)sizeof(test_rw_short),
test_rw_short, K_FOREVER)) {
printk("net_pkt_append failed\n");
return -EINVAL;
}
if (!net_pkt_append(pkt, (u16_t)sizeof(test_rw_short),
if (!net_pkt_append_all(pkt, (u16_t)sizeof(test_rw_short),
test_rw_short, K_FOREVER)) {
printk("net_pkt_append failed\n");
return -EINVAL;
@ -546,14 +546,14 @@ static int test_pkt_read_append(void)
tfrag = net_buf_frag_last(pkt->frags);
off = tfrag->len;
if (!net_pkt_append(pkt, (u16_t)sizeof(test_rw_long), test_rw_long,
K_FOREVER)) {
if (!net_pkt_append_all(pkt, (u16_t)sizeof(test_rw_long),
test_rw_long, K_FOREVER)) {
printk("net_pkt_append failed\n");
return -EINVAL;
}
if (!net_pkt_append(pkt, (u16_t)sizeof(test_rw_long), test_rw_long,
K_FOREVER)) {
if (!net_pkt_append_all(pkt, (u16_t)sizeof(test_rw_long),
test_rw_long, K_FOREVER)) {
printk("net_pkt_append failed\n");
return -EINVAL;
}