net: contiki: Fix net_buf lifecycle

siscslowpan_fragmentation would only free net_buf on failure.
nullmac does not touch the net_buf, this results in all net_buf
being exhausted eventually.
csma always frees the net_buf, so in case of failure there is a double
free with the one from siscslowpan_fragmentation.

Fix:
ref net_buf before every send, unref on every callback and once at the end,
regardless of result. Don't free or ref the net_buf in csma.

Also, replaced some code in fragment() with a call to send_packet()

Change-Id: I4f329810ace07c09cde8f7522a83a1d6681f0906
Signed-off-by: Vlad Lungu <vlad.lungu@windriver.com>
This commit is contained in:
Vlad Lungu 2016-03-16 14:39:34 +02:00 committed by Gerrit Code Review
commit 244d5f8d07
2 changed files with 5 additions and 4 deletions

View file

@ -189,7 +189,6 @@ free_packet(struct net_buf *buf, struct neighbor_queue *n, struct rdc_buf_list *
/* This was the last packet in the queue, we free the neighbor */ /* This was the last packet in the queue, we free the neighbor */
list_remove(uip_neighbor_list(buf), n); list_remove(uip_neighbor_list(buf), n);
memb_free(&neighbor_memb, n); memb_free(&neighbor_memb, n);
l2_buf_unref(buf);
} }
} }
} }

View file

@ -390,6 +390,7 @@ packet_sent(struct net_buf *buf, void *ptr, int status, int transmissions)
const linkaddr_t *dest = packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER); const linkaddr_t *dest = packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER);
uip_ds6_link_neighbor_callback(dest, status, transmissions); uip_ds6_link_neighbor_callback(dest, status, transmissions);
uip_last_tx_status(buf) = status; uip_last_tx_status(buf) = status;
l2_buf_unref(buf);
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
@ -467,10 +468,8 @@ static int fragment(struct net_buf *buf, void *ptr)
if((int)uip_len(buf) <= max_payload) { if((int)uip_len(buf) <= max_payload) {
/* The packet does not need to be fragmented, send buf */ /* The packet does not need to be fragmented, send buf */
packetbuf_copyfrom(mbuf, uip_buf(buf), uip_len(buf)); packetbuf_copyfrom(mbuf, uip_buf(buf), uip_len(buf));
packetbuf_set_addr(mbuf, PACKETBUF_ADDR_RECEIVER, send_packet(mbuf, &ip_buf_ll_dest(buf), true, ptr);
&ip_buf_ll_dest(buf));
ip_buf_unref(buf); ip_buf_unref(buf);
NETSTACK_LLSEC.send(mbuf, &packet_sent, true, ptr);
return 1; return 1;
} }
@ -521,6 +520,7 @@ static int fragment(struct net_buf *buf, void *ptr)
PRINTFO("could not allocate queuebuf for first fragment, dropping packet\n"); PRINTFO("could not allocate queuebuf for first fragment, dropping packet\n");
goto fail; goto fail;
} }
net_buf_ref(mbuf);
send_packet(mbuf, &ip_buf_ll_dest(buf), last_fragment, ptr); send_packet(mbuf, &ip_buf_ll_dest(buf), last_fragment, ptr);
queuebuf_to_packetbuf(mbuf, q); queuebuf_to_packetbuf(mbuf, q);
queuebuf_free(q); queuebuf_free(q);
@ -567,6 +567,7 @@ static int fragment(struct net_buf *buf, void *ptr)
PRINTFO("could not allocate queuebuf, dropping fragment\n"); PRINTFO("could not allocate queuebuf, dropping fragment\n");
goto fail; goto fail;
} }
net_buf_ref(mbuf);
send_packet(mbuf, &ip_buf_ll_dest(buf), last_fragment, ptr); send_packet(mbuf, &ip_buf_ll_dest(buf), last_fragment, ptr);
queuebuf_to_packetbuf(mbuf, q); queuebuf_to_packetbuf(mbuf, q);
queuebuf_free(q); queuebuf_free(q);
@ -583,6 +584,7 @@ static int fragment(struct net_buf *buf, void *ptr)
} }
ip_buf_unref(buf); ip_buf_unref(buf);
l2_buf_unref(mbuf);
return 1; return 1;
fail: fail: