From 68b9412776d11cdc3f8d5987409df27c38a0b115 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Mon, 2 Sep 2013 16:19:08 +0200 Subject: [PATCH 1/3] Drop packet if there are not enough free buffers to perform fragmentation --- core/lib/memb.c | 13 +++++++++++++ core/lib/memb.h | 1 + core/net/ipv6/sicslowpan.c | 7 +++++++ core/net/queuebuf.c | 10 ++++++++++ core/net/queuebuf.h | 4 +++- 5 files changed, 34 insertions(+), 1 deletion(-) diff --git a/core/lib/memb.c b/core/lib/memb.c index f07414435..b4056dd9f 100644 --- a/core/lib/memb.c +++ b/core/lib/memb.c @@ -107,5 +107,18 @@ memb_inmemb(struct memb *m, void *ptr) (char *)ptr < (char *)m->mem + (m->num * m->size); } /*---------------------------------------------------------------------------*/ +int +memb_numfree(struct memb *m) +{ + int i; + int num_free = 0; + for(i = 0; i < m->num; ++i) { + if(m->count[i] == 0) { + ++num_free; + } + } + + return num_free; +} /** @} */ diff --git a/core/lib/memb.h b/core/lib/memb.h index f5e654cc1..d66e5a419 100644 --- a/core/lib/memb.h +++ b/core/lib/memb.h @@ -130,6 +130,7 @@ char memb_free(struct memb *m, void *ptr); int memb_inmemb(struct memb *m, void *ptr); +int memb_numfree(struct memb *m); /** @} */ /** @} */ diff --git a/core/net/ipv6/sicslowpan.c b/core/net/ipv6/sicslowpan.c index e69bdd88b..8e139d3ce 100644 --- a/core/net/ipv6/sicslowpan.c +++ b/core/net/ipv6/sicslowpan.c @@ -1454,6 +1454,13 @@ output(const uip_lladdr_t *localdest) * IPv6/HC1/HC06/HC_UDP dispatchs/headers. * The following fragments contain only the fragn dispatch. */ + int estimated_fragments = ((int)uip_len) / ((int)MAC_MAX_PAYLOAD - SICSLOWPAN_FRAGN_HDR_LEN) + 1; + int freebuf = queuebuf_numfree() - 1; + PRINTFO("uip_len: %d, fragments: %d, free bufs: %d\n", uip_len, estimated_fragments, freebuf); + if(freebuf < estimated_fragments) { + PRINTFO("Dropping packet, not enough free bufs\n"); + return 0; + } PRINTFO("Fragmentation sending packet len %d\n", uip_len); diff --git a/core/net/queuebuf.c b/core/net/queuebuf.c index 8cb8708b3..ca49b68fc 100644 --- a/core/net/queuebuf.c +++ b/core/net/queuebuf.c @@ -307,6 +307,16 @@ queuebuf_init(void) #endif /* QUEUEBUF_STATS */ } /*---------------------------------------------------------------------------*/ +int +queuebuf_numfree(void) +{ + if(packetbuf_is_reference()) { + return memb_numfree(&refbufmem); + } else { + return memb_numfree(&bufmem); + } +} +/*---------------------------------------------------------------------------*/ #if QUEUEBUF_DEBUG struct queuebuf * queuebuf_new_from_packetbuf_debug(const char *file, int line) diff --git a/core/net/queuebuf.h b/core/net/queuebuf.h index a1727342d..cfa33a34b 100644 --- a/core/net/queuebuf.h +++ b/core/net/queuebuf.h @@ -108,7 +108,9 @@ packetbuf_attr_t queuebuf_attr(struct queuebuf *b, uint8_t type); void queuebuf_debug_print(void); -#endif /* QUEUEBUF_H_ */ +int queuebuf_numfree(void); + +#endif /* __QUEUEBUF_H__ */ /** @} */ /** @} */ From 91d84a3086c87b2f86e68f3b6358e9b84a20a6db Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Wed, 20 Nov 2013 13:09:48 +0100 Subject: [PATCH 2/3] Improve csma debug traces --- core/net/mac/csma.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/core/net/mac/csma.c b/core/net/mac/csma.c index c07f5887a..9bb2ef239 100644 --- a/core/net/mac/csma.c +++ b/core/net/mac/csma.c @@ -173,8 +173,8 @@ free_packet(struct neighbor_queue *n, struct rdc_buf_list *p) queuebuf_free(p->buf); memb_free(&metadata_memb, p->ptr); memb_free(&packet_memb, p); - PRINTF("csma: free_queued_packet, queue length %d\n", - list_length(n->queued_packet_list)); + PRINTF("csma: free_queued_packet, queue length %d, free packets %d\n", + list_length(n->queued_packet_list), memb_numfree(&packet_memb)); if(list_head(n->queued_packet_list) != NULL) { /* There is a next packet. We reset current tx information */ n->transmissions = 0; @@ -298,7 +298,11 @@ packet_sent(void *ptr, int status, int num_transmissions) free_packet(n, q); mac_call_sent_callback(sent, cptr, status, num_tx); } + } else { + PRINTF("csma: no metadata\n"); } + } else { + PRINTF("csma: seqno %d not found\n", packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)); } } /*---------------------------------------------------------------------------*/ @@ -369,6 +373,8 @@ send_packet(mac_callback_t sent, void *ptr) list_add(n->queued_packet_list, q); } + PRINTF("csma: send_packet, queue length %d, free packets %d\n", + list_length(n->queued_packet_list), memb_numfree(&packet_memb)); /* If q is the first packet in the neighbor's queue, send asap */ if(list_head(n->queued_packet_list) == q) { ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n); From 7cbd59df03aed89d647f7a06d37e83b6e286892f Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Wed, 20 Nov 2013 13:40:56 +0100 Subject: [PATCH 3/3] Add per neighbor packet throttle --- core/net/mac/csma.c | 91 +++++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/core/net/mac/csma.c b/core/net/mac/csma.c index 9bb2ef239..99dc50f5f 100644 --- a/core/net/mac/csma.c +++ b/core/net/mac/csma.c @@ -108,6 +108,13 @@ struct neighbor_queue { #define CSMA_MAX_NEIGHBOR_QUEUES 2 #endif /* CSMA_CONF_MAX_NEIGHBOR_QUEUES */ +/* The maximum number of pending packet per neighbor */ +#ifdef CSMA_CONF_MAX_PACKET_PER_NEIGHBOR +#define CSMA_MAX_PACKET_PER_NEIGHBOR CSMA_CONF_MAX_PACKET_PER_NEIGHBOR +#else +#define CSMA_MAX_PACKET_PER_NEIGHBOR MAX_QUEUED_PACKETS +#endif /* CSMA_CONF_MAX_PACKET_PER_NEIGHBOR */ + #define MAX_QUEUED_PACKETS QUEUEBUF_NUM MEMB(neighbor_memb, struct neighbor_queue, CSMA_MAX_NEIGHBOR_QUEUES); MEMB(packet_memb, struct rdc_buf_list, MAX_QUEUED_PACKETS); @@ -348,49 +355,53 @@ send_packet(mac_callback_t sent, void *ptr) if(n != NULL) { /* Add packet to the neighbor's queue */ - q = memb_alloc(&packet_memb); - if(q != NULL) { - q->ptr = memb_alloc(&metadata_memb); - if(q->ptr != NULL) { - q->buf = queuebuf_new_from_packetbuf(); - if(q->buf != NULL) { - struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr; - /* Neighbor and packet successfully allocated */ - if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) { - /* Use default configuration for max transmissions */ - metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS; - } else { - metadata->max_transmissions = - packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS); - } - metadata->sent = sent; - metadata->cptr = ptr; + if(list_length(n->queued_packet_list) < CSMA_MAX_PACKET_PER_NEIGHBOR) { + q = memb_alloc(&packet_memb); + if(q != NULL) { + q->ptr = memb_alloc(&metadata_memb); + if(q->ptr != NULL) { + q->buf = queuebuf_new_from_packetbuf(); + if(q->buf != NULL) { + struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr; + /* Neighbor and packet successfully allocated */ + if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) { + /* Use default configuration for max transmissions */ + metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS; + } else { + metadata->max_transmissions = + packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS); + } + metadata->sent = sent; + metadata->cptr = ptr; - if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == - PACKETBUF_ATTR_PACKET_TYPE_ACK) { - list_push(n->queued_packet_list, q); - } else { - list_add(n->queued_packet_list, q); - } + if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == + PACKETBUF_ATTR_PACKET_TYPE_ACK) { + list_push(n->queued_packet_list, q); + } else { + list_add(n->queued_packet_list, q); + } - PRINTF("csma: send_packet, queue length %d, free packets %d\n", - list_length(n->queued_packet_list), memb_numfree(&packet_memb)); - /* If q is the first packet in the neighbor's queue, send asap */ - if(list_head(n->queued_packet_list) == q) { - ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n); - } - return; - } - memb_free(&metadata_memb, q->ptr); - PRINTF("csma: could not allocate queuebuf, dropping packet\n"); + PRINTF("csma: send_packet, queue length %d, free packets %d\n", + list_length(n->queued_packet_list), memb_numfree(&packet_memb)); + /* If q is the first packet in the neighbor's queue, send asap */ + if(list_head(n->queued_packet_list) == q) { + ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n); + } + return; + } + memb_free(&metadata_memb, q->ptr); + PRINTF("csma: could not allocate queuebuf, dropping packet\n"); + } + memb_free(&packet_memb, q); + PRINTF("csma: could not allocate queuebuf, dropping packet\n"); } - memb_free(&packet_memb, q); - PRINTF("csma: could not allocate queuebuf, dropping packet\n"); - } - /* The packet allocation failed. Remove and free neighbor entry if empty. */ - if(list_length(n->queued_packet_list) == 0) { - list_remove(neighbor_list, n); - memb_free(&neighbor_memb, n); + /* The packet allocation failed. Remove and free neighbor entry if empty. */ + if(list_length(n->queued_packet_list) == 0) { + list_remove(neighbor_list, n); + memb_free(&neighbor_memb, n); + } + } else { + PRINTF("csma: Neighbor queue full\n"); } PRINTF("csma: could not allocate packet, dropping packet\n"); } else {