]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: ncbmbuf: define new ncbmbuf type
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 14 Oct 2025 09:29:40 +0000 (11:29 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 22 Oct 2025 13:04:06 +0000 (15:04 +0200)
Define ncbmbuf which is an alternative non-contiguous buffer
implementation. "bm" abbreviation stands for bitmap, which reflects how
gaps and filled blocks are encoded. The main purpose of this
implementation is to get rid of the ncbuf limitation regarding the
minimal size for gaps between two blocks of data.

This commit adds the new module ncbmbuf. Along with it, some utility
functions such as ncbmb_make(), ncbmb_init() and ncbmb_is_empty() are
defined. Public API of ncbmbuf will be extended in the following
patches.

This patch is not considered a bug fix. However, it will be required to
fix issue encountered on QUIC CRYPTO frames parsing. Thus, it will be
necessary to backport the current patch prior to the fix to come.

Makefile
include/haproxy/ncbmbuf-t.h [new file with mode: 0644]
include/haproxy/ncbmbuf.h [new file with mode: 0644]
src/ncbmbuf.c [new file with mode: 0644]

index 88c7548e8eb4d5f4017e49e6219d17a1bae6a90b..59b706ec3c1afc7ceeecf0e687ba76f5e424e546 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -999,7 +999,7 @@ OBJS += src/mux_h2.o src/mux_h1.o src/mux_fcgi.o src/log.o          \
         src/ebsttree.o src/freq_ctr.o src/systemd.o src/init.o         \
         src/http_acl.o src/dict.o src/dgram.o src/pipe.o               \
         src/hpack-huff.o src/hpack-enc.o src/ebtree.o src/hash.o       \
-        src/httpclient_cli.o src/version.o
+        src/httpclient_cli.o src/version.o src/ncbmbuf.o
 
 ifneq ($(TRACE),)
   OBJS += src/calltrace.o
diff --git a/include/haproxy/ncbmbuf-t.h b/include/haproxy/ncbmbuf-t.h
new file mode 100644 (file)
index 0000000..19cef2e
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _HAPROXY_NCBMBUF_T_H
+#define _HAPROXY_NCBMBUF_T_H
+
+#include <haproxy/ncbuf_common-t.h>
+
+/* Non-contiguous bitmap buffer
+ *
+ * This module is an alternative implementation to ncbuf type. Its main
+ * difference is that filled blocks and gaps are encoded via a bitmap.
+ *
+ * The main advantage of the bitmap is that contrary to ncbuf type there is no
+ * limitation on the minimal size of gaps. Thus, operation such as add and
+ * advance are guaranteed to succeed.
+ *
+ * Storage is reserved for the bitmap at the end of the buffer area,
+ * representing roughly 1/9 of the total space. Thus, usable buffer storage is
+ * smaller than the default ncbuf type.
+ */
+
+#define NCBMBUF_NULL ((struct ncbmbuf){ })
+
+struct ncbmbuf {
+       char *area; /* allocated area used for both data and bitmap storage */
+       unsigned char *bitmap; /* bitmap storage located at the end of allocated area */
+
+       ncb_sz_t size;    /* size usable for data storage */
+       ncb_sz_t size_bm; /* size of bitmap storage */
+
+       ncb_sz_t head;
+};
+
+#endif /* _HAPROXY_NCBMBUF_T_H */
diff --git a/include/haproxy/ncbmbuf.h b/include/haproxy/ncbmbuf.h
new file mode 100644 (file)
index 0000000..7119850
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _HAPROXY_NCBMBUF_H
+#define _HAPROXY_NCBMBUF_H
+
+#include <haproxy/ncbmbuf-t.h>
+
+static inline int ncbmb_is_null(const struct ncbmbuf *buf)
+{
+       return buf->size == 0;
+}
+
+void ncbmb_init(struct ncbmbuf *buf, ncb_sz_t head);
+struct ncbmbuf ncbmb_make(char *area, ncb_sz_t size, ncb_sz_t head);
+
+/* Returns the usable size of <buf> for data storage. This is the size of the
+ * allocated buffer without the bitmap space.
+ */
+static inline ncb_sz_t ncbmb_size(const struct ncbmbuf *buf)
+{
+       if (ncbmb_is_null(buf))
+               return 0;
+
+       return buf->size;
+}
+
+int ncbmb_is_empty(const struct ncbmbuf *buf);
+
+#endif /* _HAPROXY_NCBMBUF_H */
diff --git a/src/ncbmbuf.c b/src/ncbmbuf.c
new file mode 100644 (file)
index 0000000..c268d14
--- /dev/null
@@ -0,0 +1,101 @@
+#include <haproxy/ncbmbuf.h>
+
+#include <string.h>
+
+#ifdef DEBUG_STRICT
+# include <haproxy/bug.h>
+#else
+# include <stdio.h>
+# include <stdlib.h>
+
+# undef  BUG_ON
+# define BUG_ON(x)     if (x) { fprintf(stderr, "CRASH ON %s:%d\n", __func__, __LINE__); abort(); }
+
+# undef  BUG_ON_HOT
+# define BUG_ON_HOT(x) if (x) { fprintf(stderr, "CRASH ON %s:%d\n", __func__, __LINE__); abort(); }
+#endif /* DEBUG_STRICT */
+
+/* Initialize or reset <buf> by clearing all data. Its size is untouched.
+ * Buffer is positioned to <head> offset. Use 0 to realign it. <buf> must not
+ * be NCBUF_NULL.
+ */
+void ncbmb_init(struct ncbmbuf *buf, ncb_sz_t head)
+{
+       BUG_ON_HOT(ncbmb_is_null(buf));
+
+       BUG_ON_HOT(head >= buf->size);
+       buf->head = head;
+       memset(buf->bitmap, 0, buf->size_bm);
+}
+
+/* Construct a ncbmbuf with all its parameters. */
+struct ncbmbuf ncbmb_make(char *area, ncb_sz_t size, ncb_sz_t head)
+{
+       struct ncbmbuf buf;
+       ncb_sz_t size_bm;
+
+       size_bm = (size + 8) / 9;
+
+       buf.area = area;
+       buf.bitmap = (unsigned char *)area + size - size_bm;
+       buf.size = size - size_bm;
+       buf.size_bm = size_bm;
+       buf.head = head;
+
+       memset(area, 0, size);
+
+       return buf;
+}
+
+ncb_sz_t ncbmb_total_data(const struct ncbmbuf *buf)
+{
+       /* TODO */
+       return 0;
+}
+
+/* Returns true if there is no data anywhere in <buf>. */
+int ncbmb_is_empty(const struct ncbmbuf *buf)
+{
+       size_t i = 0;
+
+       if (ncbmb_is_null(buf))
+               return 1;
+
+       for (i = 0; i < buf->size_bm; ++i) {
+               if (buf->bitmap[i])
+                       return 0;
+       }
+
+       return 1;
+}
+
+int ncbmb_is_full(const struct ncbmbuf *buf)
+{
+       /* TODO */
+       return 0;
+}
+
+int ncbmb_is_fragmented(const struct ncbmbuf *buf)
+{
+       /* TODO */
+       return 0;
+}
+
+ncb_sz_t ncbmb_data(const struct ncbmbuf *buf, ncb_sz_t off)
+{
+       /* TODO */
+       return 0;
+}
+
+enum ncb_ret ncbmb_add(struct ncbmbuf *buf, ncb_sz_t off,
+                       const char *data, ncb_sz_t len, enum ncb_add_mode mode)
+{
+       /* TODO */
+       return NCB_RET_OK;
+}
+
+enum ncb_ret ncbmb_advance(struct ncbmbuf *buf, ncb_sz_t adv)
+{
+       /* TODO */
+       return NCB_RET_OK;
+}