From: Amaury Denoyelle Date: Tue, 14 Oct 2025 09:29:40 +0000 (+0200) Subject: MINOR: ncbmbuf: define new ncbmbuf type X-Git-Tag: v3.3-dev11~70 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b9f91ad3ff29c373a404b43b3d715955314c7b4f;p=thirdparty%2Fhaproxy.git MINOR: ncbmbuf: define new ncbmbuf type 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. --- diff --git a/Makefile b/Makefile index 88c7548e8..59b706ec3 100644 --- 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 index 000000000..19cef2e16 --- /dev/null +++ b/include/haproxy/ncbmbuf-t.h @@ -0,0 +1,32 @@ +#ifndef _HAPROXY_NCBMBUF_T_H +#define _HAPROXY_NCBMBUF_T_H + +#include + +/* 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 index 000000000..711985023 --- /dev/null +++ b/include/haproxy/ncbmbuf.h @@ -0,0 +1,27 @@ +#ifndef _HAPROXY_NCBMBUF_H +#define _HAPROXY_NCBMBUF_H + +#include + +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 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 index 000000000..c268d14ff --- /dev/null +++ b/src/ncbmbuf.c @@ -0,0 +1,101 @@ +#include + +#include + +#ifdef DEBUG_STRICT +# include +#else +# include +# include + +# 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 by clearing all data. Its size is untouched. + * Buffer is positioned to offset. Use 0 to realign it. 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 . */ +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; +}