From 67e9d43993ca90c6fa70ab0f7a739090cabcda3e Mon Sep 17 00:00:00 2001
From: Axel Lin <axel.lin@ingics.com>
Date: Sat, 3 Mar 2018 23:46:34 +0800
Subject: [PATCH] lowpan6: Rework to speed up dequeue datagram process

Current implementation iterates the lowpan6_data.reass_list every time
dequeue_datagram() is called.
We can get previous lrh in all the context calling dequeue_datagram().
By adding a prev arguemnt to dequeue_datagram(), we can speed up the
dequeue datagram process.

All the callers never check return value of dequeue_datagram() as it
always return ERR_OR, thus make it return void instead.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
---
 src/netif/lowpan6.c | 57 ++++++++++++++++++++++++-----------------------------
 1 file changed, 26 insertions(+), 31 deletions(-)

diff --git a/src/netif/lowpan6.c b/src/netif/lowpan6.c
index d82aec20..178e56e9 100644
--- a/src/netif/lowpan6.c
+++ b/src/netif/lowpan6.c
@@ -106,7 +106,7 @@ static const struct ieee_802154_addr ieee_802154_broadcast = {2, {0xff, 0xff}};
 static struct ieee_802154_addr short_mac_addr = {2, {0, 0}};
 #endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */
 
-static err_t dequeue_datagram(struct lowpan6_reass_helper *lrh);
+static void dequeue_datagram(struct lowpan6_reass_helper *lrh, struct lowpan6_reass_helper *prev);
 
 /**
  * Periodic timer for 6LowPAN functions:
@@ -116,42 +116,35 @@ static err_t dequeue_datagram(struct lowpan6_reass_helper *lrh);
 void
 lowpan6_tmr(void)
 {
-  struct lowpan6_reass_helper *lrh, *lrh_temp;
+  struct lowpan6_reass_helper *lrh, *lrh_next, *lrh_prev = NULL;
 
   lrh = lowpan6_data.reass_list;
   while (lrh != NULL) {
-    lrh_temp = lrh->next_packet;
+    lrh_next = lrh->next_packet;
     if ((--lrh->timer) == 0) {
-      dequeue_datagram(lrh);
+      dequeue_datagram(lrh, lrh_prev);
       pbuf_free(lrh->pbuf);
       mem_free(lrh);
+    } else {
+      lrh_prev = lrh;
     }
-    lrh = lrh_temp;
+    lrh = lrh_next;
   }
 }
 
 /**
  * Removes a datagram from the reassembly queue.
  **/
-static err_t
-dequeue_datagram(struct lowpan6_reass_helper *lrh)
+static void
+dequeue_datagram(struct lowpan6_reass_helper *lrh, struct lowpan6_reass_helper *prev)
 {
-  struct lowpan6_reass_helper *lrh_temp;
-
   if (lowpan6_data.reass_list == lrh) {
     lowpan6_data.reass_list = lowpan6_data.reass_list->next_packet;
   } else {
-    lrh_temp = lowpan6_data.reass_list;
-    while (lrh_temp != NULL) {
-      if (lrh_temp->next_packet == lrh) {
-        lrh_temp->next_packet = lrh->next_packet;
-        break;
-      }
-      lrh_temp = lrh_temp->next_packet;
-    }
+    /* it wasn't the first, so it must have a valid 'prev' */
+    LWIP_ASSERT("sanity check linked list", prev != NULL);
+    prev->next_packet = lrh->next_packet;
   }
-
-  return ERR_OK;
 }
 
 /** Write the IEEE 802.15.4 header that encapsulates the 6LoWPAN frame.
@@ -1188,7 +1181,7 @@ lowpan6_input(struct pbuf *p, struct netif *netif)
   s8_t i;
   struct ieee_802154_addr src, dest;
   u16_t datagram_size, datagram_offset, datagram_tag;
-  struct lowpan6_reass_helper *lrh, *lrh_temp;
+  struct lowpan6_reass_helper *lrh, *lrh_next, *lrh_prev = NULL;
 
   if (p == NULL) {
     return ERR_OK;
@@ -1216,6 +1209,8 @@ lowpan6_input(struct pbuf *p, struct netif *netif)
     /* check for duplicate */
     lrh = lowpan6_data.reass_list;
     while (lrh != NULL) {
+      uint8_t discard = 0;
+      lrh_next = lrh->next_packet;
       if ((lrh->sender_addr.addr_len == src.addr_len) &&
           (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0)) {
         /* address match with packet in reassembly. */
@@ -1224,18 +1219,18 @@ lowpan6_input(struct pbuf *p, struct netif *netif)
           goto lowpan6_input_discard;
         } else {
           /* We are receiving the start of a new datagram. Discard old one (incomplete). */
-          lrh_temp = lrh->next_packet;
-          dequeue_datagram(lrh);
+          discard = 1;
+        }
+      }
+      if (discard) {
+          dequeue_datagram(lrh, lrh_prev);
           pbuf_free(lrh->pbuf);
           mem_free(lrh);
-
-          /* Check next datagram in queue. */
-          lrh = lrh_temp;
-        }
       } else {
-        /* Check next datagram in queue. */
-        lrh = lrh->next_packet;
+        lrh_prev = lrh;
       }
+      /* Check next datagram in queue. */
+      lrh = lrh_next;
     }
 
     pbuf_remove_header(p, 4); /* hide frag1 dispatch */
@@ -1264,7 +1259,7 @@ lowpan6_input(struct pbuf *p, struct netif *netif)
     datagram_offset = (u16_t)puc[4] << 3;
     pbuf_remove_header(p, 5); /* hide frag1 dispatch */
 
-    for (lrh = lowpan6_data.reass_list; lrh != NULL; lrh = lrh->next_packet) {
+    for (lrh = lowpan6_data.reass_list; lrh != NULL; lrh_prev = lrh, lrh = lrh->next_packet) {
       if ((lrh->sender_addr.addr_len == src.addr_len) &&
           (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0) &&
           (datagram_tag == lrh->datagram_tag) &&
@@ -1282,7 +1277,7 @@ lowpan6_input(struct pbuf *p, struct netif *netif)
       goto lowpan6_input_ignore;
     } else if (lrh->pbuf->tot_len > datagram_offset) {
       /* We have missed a fragment. Delete whole reassembly. */
-      dequeue_datagram(lrh);
+      dequeue_datagram(lrh, lrh_prev);
       pbuf_free(lrh->pbuf);
       mem_free(lrh);
       goto lowpan6_input_discard;
@@ -1293,7 +1288,7 @@ lowpan6_input(struct pbuf *p, struct netif *netif)
     /* is packet now complete?*/
     if (lrh->pbuf->tot_len >= lrh->datagram_size) {
       /* dequeue from reass list. */
-      dequeue_datagram(lrh);
+      dequeue_datagram(lrh, lrh_prev);
 
       /* get pbuf */
       p = lrh->pbuf;
-- 
2.14.1

