net: lwm2m: increase packet reference to avoid packet being freed

CoAP packet w/ confirmation flag set is required to be retransmitted
before it got the ACK message from the peer.

However, the packet is usally unreference once it's sent to the network.
Although we set the timeout as no wait when calling function
net_app_send_pkt(), it's still possible that the packet is unreferenced
before we got a chance to increase the packet reference by calling
coap_pending_cycle().

Usually, the IP stack will generate an ARP packet first and then send
out the packet.  However, this is not the case when the remote is a
loopback address.

As issue #5101 described, when asking client to perform a firmware pull
on URL "coap://127.0.0.1:7783/large". The packet will be unreferenced
immediately after calling net_app_send_pkt(). Which then result in
client hang.

The solution to the issue is to increase the reference count on the
sending packet and decrease it after the process is finished.

Signed-off-by: Robert Chou <robert.ch.chou@acer.com>
This commit is contained in:
Robert Chou 2017-12-08 11:55:01 +08:00 committed by Jukka Rissanen
commit 33030721c4

View file

@ -886,34 +886,42 @@ cleanup:
int lwm2m_send_message(struct lwm2m_message *msg)
{
int ret;
struct net_pkt *pkt;
if (!msg || !msg->ctx) {
SYS_LOG_ERR("LwM2M message is invalid.");
return -EINVAL;
}
/* protect the packet from being released inbetween net_app_send_pkt()
* to coap_pending_cycle()
*/
pkt = msg->cpkt.pkt;
net_pkt_ref(pkt);
msg->send_attempts++;
ret = net_app_send_pkt(&msg->ctx->net_app_ctx, msg->cpkt.pkt,
&msg->ctx->net_app_ctx.default_ctx->remote,
NET_SOCKADDR_MAX_SIZE, K_NO_WAIT, NULL);
if (ret < 0) {
return ret;
goto out;
}
if (msg->type == COAP_TYPE_CON) {
if (msg->send_attempts > 1) {
return 0;
goto out;
}
coap_pending_cycle(msg->pending);
k_delayed_work_submit(&msg->ctx->retransmit_work,
msg->pending->timeout);
} else {
/* if we're not expecting an ACK, free up the msg data */
lwm2m_reset_message(msg, true);
}
return 0;
out:
net_pkt_unref(pkt);
return ret;
}
u16_t lwm2m_get_rd_data(u8_t *client_data, u16_t size)