Introduce functions for creating and operating netbuf chains. With
this, network packet data that is scattered in memory can be
described.
Signed-off-by: Simon Kuenzer <simon.kuenzer@xxxxxxxxx>
---
lib/uknetdev/exportsyms.uk | 3 ++
lib/uknetdev/include/uk/netbuf.h | 80
++++++++++++++++++++++++++++++++++++++++
lib/uknetdev/netbuf.c | 55 +++++++++++++++++++++++++++
3 files changed, 138 insertions(+)
diff --git a/lib/uknetdev/exportsyms.uk b/lib/uknetdev/exportsyms.uk
index 5473bba..3153a5d 100644
--- a/lib/uknetdev/exportsyms.uk
+++ b/lib/uknetdev/exportsyms.uk
@@ -2,3 +2,6 @@ uk_netbuf_init_indir
uk_netbuf_alloc_indir
uk_netbuf_alloc_buf
uk_netbuf_prepare_buf
+uk_netbuf_disconnect
+uk_netbuf_connect
+uk_netbuf_append
diff --git a/lib/uknetdev/include/uk/netbuf.h
b/lib/uknetdev/include/uk/netbuf.h
index 295e9eb..c448c6a 100644
--- a/lib/uknetdev/include/uk/netbuf.h
+++ b/lib/uknetdev/include/uk/netbuf.h
@@ -282,6 +282,86 @@ struct uk_netbuf *uk_netbuf_prepare_buf(void
*mem, size_t size,
uint16_t headroom,
size_t privlen, uk_netbuf_dtor_t dtor);
+/**
+ * Connects two netbuf chains
+ * @param headtail
+ * Last netbuf element of chain that should come first.
+ * It can also be just a single netbuf.
+ * @param tail
+ * Head element of the second netbuf chain.
+ * It can also be just a single netbuf.
+ */
+void uk_netbuf_connect(struct uk_netbuf *headtail,
+ struct uk_netbuf *tail);
+
+/**
+ * Connects two netbuf chains
+ * @param head
+ * Heading netbuf element of chain that should come first.
+ * It can also be just a single netbuf.
+ * @param tail
+ * Head element of the second netbuf chain.
+ * It can also be just a single netbuf.
+ */
+void uk_netbuf_append(struct uk_netbuf *head,
+ struct uk_netbuf *tail);
+
+/**
+ * Disconnects a netbuf from its chain. The chain will remain
+ * without the removed element.
+ * @param m
+ * uk_netbuf to be removed from its chain
+ * @returns
+ * - (NULL) Chain consisted only of m
+ * - Head of the remaining netbuf chain
+ */
+struct uk_netbuf *uk_netbuf_disconnect(struct uk_netbuf *m);
+
+/*
+ * Iterator helpers for netbuf chains
+ */
+/* head -> tail */
+#define UK_NETBUF_CHAIN_FOREACH(var, head) \
+ for ((var) = (head); (var) != NULL; (var) = (var)->next)
+
+/* tail -> head (reverse) */
+#define UK_NETBUF_CHAIN_FOREACH_R(var, tail) \
+ for ((var) = (tail); (var) != NULL; (var) = (var)->prev)
+
+/**
+ * Retrieves the last element of a netbuf chain
+ * @param m
+ * uk_netbuf that is part of a chain
+ * @returns
+ * Last uk_netbuf of the chain
+ */
+#define uk_netbuf_chain_last(m) \
+ ({ \
+ struct uk_netbuf *__ret = NULL; \
+ struct uk_netbuf *__iter; \
+ UK_NETBUF_CHAIN_FOREACH(__iter, (m)) \
+ __ret = __iter; \
+ \
+ (__ret); \
+ })
+
+/**
+ * Retrieves the first element of a netbuf chain
+ * @param m
+ * uk_netbuf that is part of a chain
+ * @returns
+ * First uk_netbuf of the chain
+ */
+#define uk_netbuf_chain_first(m) \
+ ({ \
+ struct uk_netbuf *__ret = NULL; \
+ struct uk_netbuf *__iter; \
+ UK_NETBUF_CHAIN_FOREACH_R(__iter, (m)) \
+ __ret = __iter; \
+ \
+ (__ret); \
+ })
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/uknetdev/netbuf.c b/lib/uknetdev/netbuf.c
index 72c349b..5bc2312 100644
--- a/lib/uknetdev/netbuf.c
+++ b/lib/uknetdev/netbuf.c
@@ -188,3 +188,58 @@ struct uk_netbuf *uk_netbuf_prepare_buf(void
*mem, size_t size,
dtor);
return m;
}
+
+struct uk_netbuf *uk_netbuf_disconnect(struct uk_netbuf *m)
+{
+ struct uk_netbuf *remhead = NULL;
+
+ UK_ASSERT(m);
+
+ /* It is possible that m was the first element of the chain.
+ * In such a case we want to return the next element of m as the
+ * remaining head of the chain. If there is no next element
+ * there was no chain.
+ */