You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by st...@apache.org on 2016/12/18 21:56:30 UTC

[02/50] incubator-mynewt-core git commit: util/mem - Generic packet fragmentation function.

util/mem - Generic packet fragmentation function.

/**
 * Specifies a function used as a callback.  Functions of this type allocate an
 * mbuf chain meant to hold a packet fragment.  The resulting mbuf must contain
 * a pkthdr.
 *
 * @param frag_size             The number of data bytes that the mbuf will
 *                                  eventually contain.
 * @param arg                   A generic parameter.
 *
 * @return                      An allocated mbuf chain on success;
 *                              NULL on failure.
 */
typedef struct os_mbuf *mem_frag_alloc_fn(uint16_t frag_size, void *arg);

/*
 * Splits an appropriately-sized fragment from the front of an mbuf chain, as
 * neeeded.  If the length of the mbuf chain greater than specified maximum
 * fragment size, a new mbuf is allocated, and data is moved from the source
 * mbuf to the new mbuf.  If the mbuf chain is small enough to fit in a single
 * fragment, the source mbuf itself is returned unmodified, and the suplied
 * pointer is set to NULL.
 *
 * This function is expected to be called in a loop until the entire mbuf chain
 * has been consumed.  For example:
 *
 *     struct os_mbuf *frag;
 *     struct os_mbuf *rsp;
 *     // [...]
 *     while (rsp != NULL) {
 *         frag = mem_split_frag(&rsp, get_mtu(), frag_alloc, NULL);
 *         if (frag == NULL) {
 *             os_mbuf_free_chain(rsp);
 *             return SYS_ENOMEM;
 *         }
 *         send_packet(frag)
 *     }
 *
 * @param om                    The packet to fragment.  Upon fragmentation,
 *                                  this mbuf is adjusted such that the
 *                                  fragment data is removed.  If the packet
 *                                  constitutes a single fragment, this gets
 *                                  set to NULL on success.
 * @param max_frag_sz           The maximum payload size of a fragment.
 *                                  Typically this is the MTU of the
 *                                  connection.
 * @param alloc_cb              Points to a function that allocates an mbuf to
 *                                  hold a fragment.  This function gets called
 *                                  before the source mbuf chain is modified,
 *                                  so it can safely inspect it.
 * @param cb_arg                Generic parameter that gets passed to the
 *                                  callback function.
 *
 * @return                      The next fragment to send on success;
 *                              NULL on failure.
 */


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/93cb0c08
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/93cb0c08
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/93cb0c08

Branch: refs/heads/sensors_branch
Commit: 93cb0c08c8226fc729e2e824ebf8947014e310c3
Parents: 7f8109d
Author: Christopher Collins <cc...@apache.org>
Authored: Tue Dec 13 18:06:31 2016 -0800
Committer: Sterling Hughes <st...@apache.org>
Committed: Sun Dec 18 13:56:16 2016 -0800

----------------------------------------------------------------------
 util/mem/include/mem/mem.h | 17 +++++++++
 util/mem/src/mem.c         | 79 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 96 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/93cb0c08/util/mem/include/mem/mem.h
----------------------------------------------------------------------
diff --git a/util/mem/include/mem/mem.h b/util/mem/include/mem/mem.h
index 2ea7276..18461b6 100644
--- a/util/mem/include/mem/mem.h
+++ b/util/mem/include/mem/mem.h
@@ -42,6 +42,23 @@ int mem_init_mbuf_pool(void *mem, struct os_mempool *mempool,
                        struct os_mbuf_pool *mbuf_pool, int num_blocks,
                        int block_size, char *name);
 
+/**
+ * Specifies a function used as a callback.  Functions of this type allocate an
+ * mbuf chain meant to hold a packet fragment.  The resulting mbuf must contain
+ * a pkthdr.
+ *
+ * @param frag_size             The number of data bytes that the mbuf will
+ *                                  eventually contain.
+ * @param arg                   A generic parameter.
+ *
+ * @return                      An allocated mbuf chain on success;
+ *                              NULL on failure.
+ */
+typedef struct os_mbuf *mem_frag_alloc_fn(uint16_t frag_size, void *arg);
+
+struct os_mbuf *mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz,
+                               mem_frag_alloc_fn *alloc_cb, void *cb_arg);
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/93cb0c08/util/mem/src/mem.c
----------------------------------------------------------------------
diff --git a/util/mem/src/mem.c b/util/mem/src/mem.c
index 637edbc..340e60e 100644
--- a/util/mem/src/mem.c
+++ b/util/mem/src/mem.c
@@ -18,6 +18,7 @@
  */
 
 #include "os/os.h"
+#include "mem/mem.h"
 
 /**
  * Mallocs a block of memory and initializes a mempool to use it.
@@ -164,3 +165,81 @@ mem_init_mbuf_pool(void *mem, struct os_mempool *mempool,
 
     return 0;
 }
+
+/*
+ * Splits an appropriately-sized fragment from the front of an mbuf chain, as
+ * neeeded.  If the length of the mbuf chain greater than specified maximum
+ * fragment size, a new mbuf is allocated, and data is moved from the source
+ * mbuf to the new mbuf.  If the mbuf chain is small enough to fit in a single
+ * fragment, the source mbuf itself is returned unmodified, and the suplied
+ * pointer is set to NULL.
+ *
+ * This function is expected to be called in a loop until the entire mbuf chain
+ * has been consumed.  For example:
+ *
+ *     struct os_mbuf *frag;
+ *     struct os_mbuf *rsp;
+ *     // [...]
+ *     while (rsp != NULL) {
+ *         frag = mem_split_frag(&rsp, get_mtu(), frag_alloc, NULL);
+ *         if (frag == NULL) {
+ *             os_mbuf_free_chain(rsp);
+ *             return SYS_ENOMEM;
+ *         }
+ *         send_packet(frag)
+ *     }
+ *
+ * @param om                    The packet to fragment.  Upon fragmentation,
+ *                                  this mbuf is adjusted such that the
+ *                                  fragment data is removed.  If the packet
+ *                                  constitutes a single fragment, this gets
+ *                                  set to NULL on success.
+ * @param max_frag_sz           The maximum payload size of a fragment.
+ *                                  Typically this is the MTU of the
+ *                                  connection.
+ * @param alloc_cb              Points to a function that allocates an mbuf to
+ *                                  hold a fragment.  This function gets called
+ *                                  before the source mbuf chain is modified,
+ *                                  so it can safely inspect it.
+ * @param cb_arg                Generic parameter that gets passed to the
+ *                                  callback function.
+ *
+ * @return                      The next fragment to send on success;
+ *                              NULL on failure.
+ */
+struct os_mbuf *
+mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz,
+               mem_frag_alloc_fn *alloc_cb, void *cb_arg)
+{
+    struct os_mbuf *frag;
+    int rc;
+
+    if (OS_MBUF_PKTLEN(*om) <= max_frag_sz) {
+        /* Final fragment. */
+        frag = *om;
+        *om = NULL;
+        return frag;
+    }
+
+    /* Packet needs to be split.  Allocate a new buffer for the fragment. */
+    frag = alloc_cb(max_frag_sz, cb_arg);
+    if (frag == NULL) {
+        goto err;
+    }
+
+    /* Move data from the front of the packet into the fragment mbuf. */
+    rc = os_mbuf_appendfrom(frag, *om, 0, max_frag_sz);
+    if (rc != 0) {
+        goto err;
+    }
+    os_mbuf_adj(*om, max_frag_sz);
+
+    /* Free unused portion of of source mbuf chain, if possible. */
+    *om = os_mbuf_trim_front(*om);
+
+    return frag;
+
+err:
+    os_mbuf_free_chain(frag);
+    return NULL;
+}