Bugfix: when a CSMA callback is received, we should remove the packet

that was transmitted and not just the first packet that happens to be on
the output queue.
This commit is contained in:
Adam Dunkels 2013-05-25 12:13:07 +02:00
parent 0a135eeba1
commit 09f30e875d
1 changed files with 29 additions and 16 deletions

View File

@ -156,24 +156,25 @@ transmit_packet_list(void *ptr)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
free_first_packet(struct neighbor_queue *n) free_packet(struct neighbor_queue *n, struct rdc_buf_list *p)
{ {
struct rdc_buf_list *q = list_head(n->queued_packet_list); if(p != NULL) {
if(q != NULL) { /* Remove packet from list and deallocate */
/* Remove first packet from list and deallocate */ list_remove(n->queued_packet_list, p);
queuebuf_free(q->buf);
list_pop(n->queued_packet_list); queuebuf_free(p->buf);
memb_free(&metadata_memb, q->ptr); memb_free(&metadata_memb, p->ptr);
memb_free(&packet_memb, q); memb_free(&packet_memb, p);
PRINTF("csma: free_queued_packet, queue length %d\n", PRINTF("csma: free_queued_packet, queue length %d\n",
list_length(n->queued_packet_list)); list_length(n->queued_packet_list));
if(list_head(n->queued_packet_list)) { if(list_head(n->queued_packet_list) != NULL) {
/* There is a next packet. We reset current tx information */ /* There is a next packet. We reset current tx information */
n->transmissions = 0; n->transmissions = 0;
n->collisions = 0; n->collisions = 0;
n->deferrals = 0; n->deferrals = 0;
/* Set a timer for next transmissions */ /* Set a timer for next transmissions */
ctimer_set(&n->transmit_timer, default_timebase(), transmit_packet_list, n); ctimer_set(&n->transmit_timer, default_timebase(),
transmit_packet_list, n);
} else { } else {
/* This was the last packet in the queue, we free the neighbor */ /* This was the last packet in the queue, we free the neighbor */
ctimer_stop(&n->transmit_timer); ctimer_stop(&n->transmit_timer);
@ -212,7 +213,14 @@ packet_sent(void *ptr, int status, int num_transmissions)
break; break;
} }
q = list_head(n->queued_packet_list); for(q = list_head(n->queued_packet_list);
q != NULL; q = list_item_next(q)) {
if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) ==
packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) {
break;
}
}
if(q != NULL) { if(q != NULL) {
metadata = (struct qbuf_metadata *)q->ptr; metadata = (struct qbuf_metadata *)q->ptr;
@ -245,16 +253,16 @@ packet_sent(void *ptr, int status, int num_transmissions)
interval between the transmissions increase with each interval between the transmissions increase with each
retransmit. */ retransmit. */
backoff_transmissions = n->transmissions + 1; backoff_transmissions = n->transmissions + 1;
/* Clamp the number of backoffs so that we don't get a too long /* Clamp the number of backoffs so that we don't get a too long
timeout here, since that will delay all packets in the timeout here, since that will delay all packets in the
queue. */ queue. */
if(backoff_transmissions > 3) { if(backoff_transmissions > 3) {
backoff_transmissions = 3; backoff_transmissions = 3;
} }
time = time + (random_rand() % (backoff_transmissions * time)); time = time + (random_rand() % (backoff_transmissions * time));
if(n->transmissions < metadata->max_transmissions) { if(n->transmissions < metadata->max_transmissions) {
PRINTF("csma: retransmitting with time %lu %p\n", time, q); PRINTF("csma: retransmitting with time %lu %p\n", time, q);
ctimer_set(&n->transmit_timer, time, ctimer_set(&n->transmit_timer, time,
@ -265,7 +273,7 @@ packet_sent(void *ptr, int status, int num_transmissions)
} else { } else {
PRINTF("csma: drop with status %d after %d transmissions, %d collisions\n", PRINTF("csma: drop with status %d after %d transmissions, %d collisions\n",
status, n->transmissions, n->collisions); status, n->transmissions, n->collisions);
free_first_packet(n); free_packet(n, q);
mac_call_sent_callback(sent, cptr, status, num_tx); mac_call_sent_callback(sent, cptr, status, num_tx);
} }
} else { } else {
@ -274,7 +282,7 @@ packet_sent(void *ptr, int status, int num_transmissions)
} else { } else {
PRINTF("csma: rexmit failed %d: %d\n", n->transmissions, status); PRINTF("csma: rexmit failed %d: %d\n", n->transmissions, status);
} }
free_first_packet(n); free_packet(n, q);
mac_call_sent_callback(sent, cptr, status, num_tx); mac_call_sent_callback(sent, cptr, status, num_tx);
} }
} }
@ -289,6 +297,11 @@ send_packet(mac_callback_t sent, void *ptr)
static uint16_t seqno; static uint16_t seqno;
const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
if(seqno == 0) {
/* PACKETBUF_ATTR_MAC_SEQNO cannot be zero, due to a pecuilarity
in framer-802154.c. */
seqno++;
}
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++); packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++);
/* Look for the neighbor entry */ /* Look for the neighbor entry */