From 806a05ba6f5bd4f160b9f795af1ac60ee740b3a3 Mon Sep 17 00:00:00 2001
From: Axel Lin <axel.lin@ingics.com>
Date: Sun, 11 Mar 2018 11:33:00 +0800
Subject: [PATCH v2] 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>
---
v2: Rebase to current git tree.
 src/netif/lowpan6.c | 61 ++++++++++++++++++++++++-----------------------------
 1 file changed, 28 insertions(+), 33 deletions(-)

diff --git a/src/netif/lowpan6.c b/src/netif/lowpan6.c
index 5a91adc4..8a3a6af0 100644
--- a/src/netif/lowpan6.c
+++ b/src/netif/lowpan6.c
@@ -110,7 +110,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);
 
 static void
 free_reass_datagram(struct lowpan6_reass_helper *lrh)
@@ -132,41 +132,34 @@ free_reass_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);
       free_reass_datagram(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.
@@ -1281,7 +1274,7 @@ lowpan6_input(struct pbuf *p, struct netif *netif)
   struct ieee_802154_addr src, dest;
   u16_t datagram_size = 0;
   u16_t 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;
@@ -1310,6 +1303,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. */
@@ -1318,17 +1313,17 @@ 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);
-          free_reass_datagram(lrh);
-
-          /* Check next datagram in queue. */
-          lrh = lrh_temp;
+          discard = 1;
         }
+      }
+      if (discard) {
+        dequeue_datagram(lrh, lrh_prev);
+        free_reass_datagram(lrh);
       } 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 */
@@ -1370,7 +1365,7 @@ lowpan6_input(struct pbuf *p, struct netif *netif)
     datagram_offset = (u16_t)puc[4] << 3;
     pbuf_remove_header(p, 4); /* hide frag1 dispatch but keep datagram offset for reassembly */
 
-    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) &&
@@ -1389,7 +1384,7 @@ lowpan6_input(struct pbuf *p, struct netif *netif)
       /* FRAG1 already received, check this offset against first len */
       if (datagram_offset < lrh->reass->len) {
         /* fragment overlap, discard old fragments */
-        dequeue_datagram(lrh);
+        dequeue_datagram(lrh, lrh_prev);
         free_reass_datagram(lrh);
         goto lowpan6_input_discard;
       }
@@ -1407,7 +1402,7 @@ lowpan6_input(struct pbuf *p, struct netif *netif)
         if (datagram_offset < q_datagram_offset) {
           if (datagram_offset + new_frag_len > q_datagram_offset) {
             /* overlap, discard old fragments */
-            dequeue_datagram(lrh);
+            dequeue_datagram(lrh, lrh_prev);
             free_reass_datagram(lrh);
             goto lowpan6_input_discard;
           }
@@ -1416,7 +1411,7 @@ lowpan6_input(struct pbuf *p, struct netif *netif)
         } else if (datagram_offset == q_datagram_offset) {
           if (q_frag_len != new_frag_len) {
             /* fragment mismatch, discard old fragments */
-            dequeue_datagram(lrh);
+            dequeue_datagram(lrh, lrh_prev);
             free_reass_datagram(lrh);
             goto lowpan6_input_discard;
           }
@@ -1460,7 +1455,7 @@ lowpan6_input(struct pbuf *p, struct netif *netif)
         q->next = lrh->frags;
         lrh->frags = NULL;
         lrh->reass = NULL;
-        dequeue_datagram(lrh);
+        dequeue_datagram(lrh, lrh_prev);
         mem_free(lrh);
 
         /* @todo: distinguish unicast/multicast */
-- 
2.14.1

