summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorQuentin Young <qlyoung@cumulusnetworks.com>2017-12-19 22:28:45 +0100
committerQuentin Young <qlyoung@cumulusnetworks.com>2017-12-19 23:12:43 +0100
commit5318d8963816f607e8ab648eb17c784617b90270 (patch)
tree085ccbf03f8691f5c4d1546c8e4da02ba7ae71b8 /lib
parentMerge pull request #1543 from donaldsharp/pim_sg_rpt (diff)
downloadfrr-5318d8963816f607e8ab648eb17c784617b90270.tar.xz
frr-5318d8963816f607e8ab648eb17c784617b90270.zip
lib: add ring buffer
Simple ring buffer implementation useful for fixed size FIFO queues. Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/ringbuf.c104
-rw-r--r--lib/ringbuf.h100
-rw-r--r--lib/subdir.am2
3 files changed, 206 insertions, 0 deletions
diff --git a/lib/ringbuf.c b/lib/ringbuf.c
new file mode 100644
index 000000000..fee5b5d69
--- /dev/null
+++ b/lib/ringbuf.c
@@ -0,0 +1,104 @@
+/*
+ * Circular buffer implementation.
+ * Copyright (C) 2017 Cumulus Networks
+ * Quentin Young
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <zebra.h>
+
+#include "ringbuf.h"
+#include "memory.h"
+
+DEFINE_MTYPE_STATIC(LIB, RINGBUFFER, "Ring buffer")
+
+struct ringbuf *ringbuf_new(size_t size)
+{
+ struct ringbuf *buf = XCALLOC(MTYPE_RINGBUFFER, sizeof(struct ringbuf));
+ buf->data = XCALLOC(MTYPE_RINGBUFFER, size);
+ buf->size = size;
+ buf->empty = true;
+ return buf;
+}
+
+void ringbuf_del(struct ringbuf *buf)
+{
+ XFREE(MTYPE_RINGBUFFER, buf->data);
+ XFREE(MTYPE_RINGBUFFER, buf);
+}
+
+size_t ringbuf_remain(struct ringbuf *buf)
+{
+ ssize_t diff = buf->end - buf->start;
+ diff += ((diff == 0) && !buf->empty) ? buf->size : 0;
+ diff += (diff < 0) ? buf->size : 0;
+ return (size_t)diff;
+}
+
+size_t ringbuf_space(struct ringbuf *buf)
+{
+ return buf->size - ringbuf_remain(buf);
+}
+
+size_t ringbuf_put(struct ringbuf *buf, const void *data, size_t size)
+{
+ const uint8_t *dp = data;
+ size_t space = ringbuf_space(buf);
+ size_t copysize = MIN(size, space);
+ size_t tocopy = copysize;
+ if (tocopy > buf->size - buf->end) {
+ size_t ts = buf->size - buf->end;
+ memcpy(buf->data + buf->end, dp, ts);
+ buf->end = 0;
+ tocopy -= ts;
+ dp += ts;
+ }
+ memcpy(buf->data + buf->end, dp, tocopy);
+ buf->end += tocopy;
+ buf->empty = (buf->start == buf->end) && (buf->empty && !copysize);
+ return copysize;
+}
+
+size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size)
+{
+ uint8_t *dp = data;
+ size_t remain = ringbuf_remain(buf);
+ size_t copysize = MIN(remain, size);
+ size_t tocopy = copysize;
+ if (tocopy > buf->size - buf->start) {
+ size_t ts = buf->size - buf->start;
+ memcpy(dp, buf->data + buf->start, ts);
+ buf->start = 0;
+ tocopy -= ts;
+ dp += ts;
+ }
+ memcpy(dp, buf->data + buf->start, tocopy);
+ buf->start = buf->start + tocopy;
+ buf->empty = (buf->start == buf->end) && (buf->empty || copysize);
+ return copysize;
+}
+
+void ringbuf_reset(struct ringbuf *buf)
+{
+ buf->start = buf->end = 0;
+ buf->empty = true;
+}
+
+void ringbuf_wipe(struct ringbuf *buf)
+{
+ memset(buf->data, 0x00, buf->size);
+ ringbuf_reset(buf);
+ buf->empty = true;
+}
diff --git a/lib/ringbuf.h b/lib/ringbuf.h
new file mode 100644
index 000000000..af07c93a6
--- /dev/null
+++ b/lib/ringbuf.h
@@ -0,0 +1,100 @@
+/*
+ * Circular buffer implementation.
+ * Copyright (C) 2017 Cumulus Networks
+ * Quentin Young
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef _FRR_RINGBUF_H_
+#define _FRR_RINGBUF_H_
+
+#include <zebra.h>
+#include <stdint.h>
+
+#include "memory.h"
+
+struct ringbuf {
+ size_t size;
+ ssize_t start;
+ ssize_t end;
+ bool empty;
+ uint8_t *data;
+};
+
+/*
+ * Creates a new ring buffer.
+ *
+ * @param size buffer size, in bytes
+ * @return the newly created buffer
+ */
+struct ringbuf *ringbuf_new(size_t size);
+
+/*
+ * Deletes a ring buffer and frees all associated resources.
+ *
+ * @param buf the ring buffer to destroy
+ */
+void ringbuf_del(struct ringbuf *buf);
+
+/*
+ * Get amount of data left to read from the buffer.
+ *
+ * @return number of readable bytes
+ */
+size_t ringbuf_remain(struct ringbuf *buf);
+
+/*
+ * Get amount of space left to write to the buffer
+ *
+ * @return number of writeable bytes
+ */
+size_t ringbuf_space(struct ringbuf *buf);
+
+
+/*
+ * Put data into the ring buffer.
+ *
+ * @param data the data to put in the buffer
+ * @param size how much of data to put in
+ * @return number of bytes written; will be less than size if there was not
+ * enough space
+ */
+size_t ringbuf_put(struct ringbuf *buf, const void *data, size_t size);
+
+/*
+ * Get data from the ring buffer.
+ *
+ * @param data where to put the data
+ * @param size how much of data to get
+ * @return number of bytes read into data; will be less than size if there was
+ * not enough data to read
+ */
+size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size);
+
+/*
+ * Reset buffer. Does not wipe.
+ *
+ * @param buf
+ */
+void ringbuf_reset(struct ringbuf *buf);
+
+/*
+ * Reset buffer. Wipes.
+ *
+ * @param buf
+ */
+void ringbuf_wipe(struct ringbuf *buf);
+
+#endif /* _FRR_RINGBUF_H_ */
diff --git a/lib/subdir.am b/lib/subdir.am
index c8eddc8e2..44870917b 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -51,6 +51,7 @@ lib_libfrr_la_SOURCES = \
lib/privs.c \
lib/ptm_lib.c \
lib/qobj.c \
+ lib/ringbuf.c \
lib/routemap.c \
lib/sbuf.c \
lib/sha256.c \
@@ -130,6 +131,7 @@ pkginclude_HEADERS += \
lib/pw.h \
lib/qobj.h \
lib/queue.h \
+ lib/ringbuf.h \
lib/routemap.h \
lib/sbuf.h \
lib/sha256.h \