You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2015/12/03 04:08:36 UTC

incubator-mynewt-larva git commit: Implement os_mbuf_pullup().

Repository: incubator-mynewt-larva
Updated Branches:
  refs/heads/master e878a3d55 -> 6a4288c93


Implement os_mbuf_pullup().


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/commit/6a4288c9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/6a4288c9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/6a4288c9

Branch: refs/heads/master
Commit: 6a4288c938dc700ed4abb1db36ddf76c35af42a8
Parents: e878a3d
Author: Christopher Collins <cc...@gmail.com>
Authored: Wed Dec 2 19:08:21 2015 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Wed Dec 2 19:08:21 2015 -0800

----------------------------------------------------------------------
 libs/os/include/os/os_mbuf.h |  7 +++
 libs/os/src/os_mbuf.c        | 81 ++++++++++++++++++++--------------
 libs/os/src/test/mbuf_test.c | 93 ++++++++++++++++++++++++++++++++++++++-
 3 files changed, 147 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6a4288c9/libs/os/include/os/os_mbuf.h
----------------------------------------------------------------------
diff --git a/libs/os/include/os/os_mbuf.h b/libs/os/include/os/os_mbuf.h
index d5cc471..9eaee38 100644
--- a/libs/os/include/os/os_mbuf.h
+++ b/libs/os/include/os/os_mbuf.h
@@ -132,6 +132,12 @@ struct os_mqueue {
 #define OS_MBUF_PKTHDR_TO_MBUF(__hdr)   \
      (struct os_mbuf *)((uint8_t *)(__hdr) - sizeof(struct os_mbuf))
 
+/**
+ * Gets the length of an entire mbuf chain.  The specified mbuf must have a
+ * packet header.
+ */
+#define OS_MBUF_PKTLEN(__om) (OS_MBUF_PKTHDR(__om)->omp_len)
+
 /*
  * Access the data of a mbuf, and cast it to type
  *
@@ -253,5 +259,6 @@ struct os_mbuf *os_mbuf_prepend(struct os_mbuf *om, int len);
 int os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len);
 void os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second);
 void *os_mbuf_extend(struct os_mbuf *om, uint16_t len);
+struct os_mbuf *os_mbuf_pullup(struct os_mbuf *om, uint16_t len);
 
 #endif /* _OS_MBUF_H */ 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6a4288c9/libs/os/src/os_mbuf.c
----------------------------------------------------------------------
diff --git a/libs/os/src/os_mbuf.c b/libs/os/src/os_mbuf.c
index e5d8ff3..8700e31 100644
--- a/libs/os/src/os_mbuf.c
+++ b/libs/os/src/os_mbuf.c
@@ -241,6 +241,7 @@ os_mbuf_get(struct os_mbuf_pool *omp, uint16_t leadingspace)
 
     SLIST_NEXT(om, om_next) = NULL;
     om->om_flags = 0;
+    om->om_pkthdr_len = 0;
     om->om_len = 0;
     om->om_data = (&om->om_databuf[0] + leadingspace);
     om->om_omp = omp;
@@ -909,8 +910,6 @@ os_mbuf_extend(struct os_mbuf *om, uint16_t len)
     return data;
 }
 
-#if 0
-
 /**
  * Rearrange a mbuf chain so that len bytes are contiguous, 
  * and in the data area of an mbuf (so that OS_MBUF_DATA() will 
@@ -931,40 +930,58 @@ struct os_mbuf *
 os_mbuf_pullup(struct os_mbuf *om, uint16_t len)
 {
     struct os_mbuf_pool *omp;
-    struct os_mbuf *newm;
+    struct os_mbuf *next;
+    struct os_mbuf *om2;
+    int count;
+    int space;
 
     omp = om->om_omp;
 
-    if (len > omp->omp_databuf_len) {
-        goto err;
-    }
-
-    /* Is 'n' bytes already contiguous? */
-    if (((uint8_t *) &om->om_databuf[0] + omp->omp_databuf_len) - 
-            OS_MBUF_DATA(om, uint8_t *) >= len) {
-        newm = om;
-        goto done;
-    }
-
-    /* Nope, OK. Allocate a new buffer, and then go through and copy 'n' 
-     * bytes into that buffer.
+    /*
+     * If first mbuf has no cluster, and has room for len bytes
+     * without shifting current data, pullup into it,
+     * otherwise allocate a new mbuf to prepend to the chain.
      */
-    newm = os_mbuf_get(omp, 0);
-    if (!newm) {
-        goto err;
+    if (om->om_len >= len) {
+        return (om);
     }
-
-    written = 0; 
-    while (written < len
-
-
-done:
-    return (newm);
-err:
-    if (om) {
-        os_mbuf_free_chain(om);
-    }
-
+    if (om->om_len + OS_MBUF_TRAILINGSPACE(om) >= len &&
+        SLIST_NEXT(om, om_next)) {
+        om2 = om;
+        om = SLIST_NEXT(om, om_next);
+        len -= om2->om_len;
+    } else {
+        if (len > omp->omp_databuf_len - om->om_pkthdr_len)
+            goto bad;
+        om2 = os_mbuf_get(omp, 0);
+        if (om2 == NULL)
+            goto bad;
+        if (OS_MBUF_IS_PKTHDR(om))
+            _os_mbuf_copypkthdr(om2, om);
+    }
+    space = OS_MBUF_TRAILINGSPACE(om2);
+    do {
+        count = min(min(len, space), om->om_len);
+        memcpy(om2->om_data + om2->om_len, om->om_data, count);
+        len -= count;
+        om2->om_len += count;
+        om->om_len -= count;
+        space -= count;
+        if (om->om_len)
+            om->om_data += count;
+        else {
+            next = SLIST_NEXT(om, om_next);
+            os_mbuf_free(om);
+            om = next;
+        }
+    } while (len > 0 && om);
+    if (len > 0) {
+        os_mbuf_free(om2);
+        goto bad;
+    }
+    SLIST_NEXT(om2, om_next) = om;
+    return (om2);
+bad:
+    os_mbuf_free_chain(om);
     return (NULL);
 }
-#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6a4288c9/libs/os/src/test/mbuf_test.c
----------------------------------------------------------------------
diff --git a/libs/os/src/test/mbuf_test.c b/libs/os/src/test/mbuf_test.c
index 8652494..fb7c4de 100644
--- a/libs/os/src/test/mbuf_test.c
+++ b/libs/os/src/test/mbuf_test.c
@@ -50,6 +50,8 @@ TEST_CASE(os_mbuf_test_case_1)
     struct os_mbuf *m; 
     int rc;
 
+    os_mbuf_test_setup();
+
     m = os_mbuf_get(&os_mbuf_pool, 0);
     TEST_ASSERT_FATAL(m != NULL, "Error allocating mbuf");
 
@@ -64,6 +66,8 @@ TEST_CASE(os_mbuf_test_case_2)
     struct os_mbuf *dup;
     int rc;
 
+    os_mbuf_test_setup();
+
     /* Test first allocating and duplicating a single mbuf */
     m = os_mbuf_get(&os_mbuf_pool, 0);
     TEST_ASSERT_FATAL(m != NULL, "Error allocating mbuf");
@@ -106,6 +110,8 @@ TEST_CASE(os_mbuf_test_case_3)
     uint8_t databuf[] = {0xa, 0xb, 0xc, 0xd};
     uint8_t cmpbuf[] = {0xff, 0xff, 0xff, 0xff};
 
+    os_mbuf_test_setup();
+
     m = os_mbuf_get(&os_mbuf_pool, 0);
     TEST_ASSERT_FATAL(m != NULL, "Error allocating mbuf");
 
@@ -121,15 +127,98 @@ TEST_CASE(os_mbuf_test_case_3)
             "Databuf doesn't match cmpbuf");
 }
 
-TEST_SUITE(os_mbuf_test_case_4)
+static void
+os_mbuf_test_misc_assert_contiguous(struct os_mbuf *om, void *data, int len)
 {
+    TEST_ASSERT_FATAL(om != NULL);
+
+    if (OS_MBUF_IS_PKTHDR(om)) {
+        TEST_ASSERT(OS_MBUF_PKTLEN(om) == len);
+    }
+    TEST_ASSERT(om->om_len == len);
+    TEST_ASSERT(memcmp(om->om_data, data, len) == 0);
 }
 
-TEST_SUITE(os_mbuf_test_suite)
+TEST_CASE(os_mbuf_test_pullup)
 {
+    struct os_mbuf *om;
+    struct os_mbuf *om2;
+    uint8_t data[256];
+    int rc;
+    int i;
+
     os_mbuf_test_setup();
 
+    for (i = 0; i < sizeof data; i++) {
+        data[i] = i;
+    }
+
+    /*** Free when too much data is requested. */
+    om = os_mbuf_get_pkthdr(&os_mbuf_pool, 0);
+    TEST_ASSERT_FATAL(om != NULL);
+
+    om = os_mbuf_pullup(om, 1);
+    TEST_ASSERT(om == NULL);
+
+    /*** No effect when all data is already at the start. */
+    om = os_mbuf_get_pkthdr(&os_mbuf_pool, 0);
+    TEST_ASSERT_FATAL(om != NULL);
+
+    rc = os_mbuf_append(om, data, 1);
+    TEST_ASSERT_FATAL(rc == 0);
+    os_mbuf_test_misc_assert_contiguous(om, data, 1);
+
+    om = os_mbuf_pullup(om, 1);
+    os_mbuf_test_misc_assert_contiguous(om, data, 1);
+
+    /*** Spread data across four mbufs. */
+    om2 = os_mbuf_get(&os_mbuf_pool, 0);
+    TEST_ASSERT_FATAL(om2 != NULL);
+    rc = os_mbuf_append(om2, data + 1, 1);
+    TEST_ASSERT_FATAL(rc == 0);
+    os_mbuf_concat(om, om2);
+
+    om2 = os_mbuf_get(&os_mbuf_pool, 0);
+    TEST_ASSERT_FATAL(om2 != NULL);
+    rc = os_mbuf_append(om2, data + 2, 1);
+    TEST_ASSERT_FATAL(rc == 0);
+    os_mbuf_concat(om, om2);
+
+    om2 = os_mbuf_get(&os_mbuf_pool, 0);
+    TEST_ASSERT_FATAL(om2 != NULL);
+    rc = os_mbuf_append(om2, data + 3, 1);
+    TEST_ASSERT_FATAL(rc == 0);
+    os_mbuf_concat(om, om2);
+
+    TEST_ASSERT_FATAL(OS_MBUF_PKTLEN(om) == 4);
+
+    om = os_mbuf_pullup(om, 4);
+    os_mbuf_test_misc_assert_contiguous(om, data, 4);
+
+    os_mbuf_free_chain(om);
+
+    /*** Require an allocation. */
+    om = os_mbuf_get_pkthdr(&os_mbuf_pool, 0);
+    TEST_ASSERT_FATAL(om != NULL);
+
+    om->om_data += 100;
+    rc = os_mbuf_append(om, data, 100);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    om2 = os_mbuf_get(&os_mbuf_pool, 0);
+    TEST_ASSERT_FATAL(om2 != NULL);
+    rc = os_mbuf_append(om2, data + 100, 100);
+    TEST_ASSERT_FATAL(rc == 0);
+    os_mbuf_concat(om, om2);
+
+    om = os_mbuf_pullup(om, 200);
+    os_mbuf_test_misc_assert_contiguous(om, data, 200);
+}
+
+TEST_SUITE(os_mbuf_test_suite)
+{
     os_mbuf_test_case_1();
     os_mbuf_test_case_2();
     os_mbuf_test_case_3();
+    os_mbuf_test_pullup();
 }