MINOR: quic: Add a ring buffer implementation for QUIC

This implementation is inspired from Linux kernel circular buffer implementation
(see include/linux/circ-buf.h). Such buffers may be used at the same time both
by writer and reader (lock-free).
This commit is contained in:
Frédéric Lécaille 2021-06-30 14:25:10 +02:00 committed by Amaury Denoyelle
parent f3d078d22e
commit c6bc185c18
4 changed files with 240 additions and 1 deletions

View File

@ -590,7 +590,7 @@ endif
ifneq ($(USE_QUIC),)
OPTIONS_OBJS += src/quic_sock.o src/proto_quic.o src/xprt_quic.o src/quic_tls.o \
src/quic_frame.o src/quic_cc.o src/quic_cc_newreno.o src/mux_quic.o \
src/qpack-dec.o src/qpack-tbl.o src/h3.o
src/cbuf.o src/qpack-dec.o src/qpack-tbl.o src/h3.o
endif
ifneq ($(USE_LUA),)

46
include/haproxy/cbuf-t.h Normal file
View File

@ -0,0 +1,46 @@
/*
* include/haprox/cbuf-t.h
* This file contains definition for circular buffers.
*
* Copyright 2021 HAProxy Technologies, Frédéric Lécaille <flecaille@haproxy.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, version 2.1
* exclusively.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _HAPROXY_CBUF_T_H
#define _HAPROXY_CBUF_T_H
#ifdef USE_QUIC
#ifndef USE_OPENSSL
#error "Must define USE_OPENSSL"
#endif
#endif
#include <haproxy/list-t.h>
/* QUIC circular buffer internal buffer size (must be a power of 2) */
#define CBUF_BUFSZ (1UL << 11)
extern struct pool_head *pool_head_cbuf;
struct cbuf {
/* buffer */
unsigned char buf[CBUF_BUFSZ];
/* Writer index */
int wr;
/* Reader index */
int rd;
};
#endif /* _HAPROXY_CBUF_T_H */

138
include/haproxy/cbuf.h Normal file
View File

@ -0,0 +1,138 @@
/*
* include/haprox/cbuf.h
* This file contains definitions and prototypes for circular buffers.
* Inspired from Linux circular buffers (include/linux/circ_buf.h).
*
* Copyright 2021 HAProxy Technologies, Frédéric Lécaille <flecaille@haproxy.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, version 2.1
* exclusively.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _HAPROXY_CBUF_H
#define _HAPROXY_CBUF_H
#ifdef USE_QUIC
#ifndef USE_OPENSSL
#error "Must define USE_OPENSSL"
#endif
#endif
#include <haproxy/atomic.h>
#include <haproxy/list.h>
#include <haproxy/cbuf-t.h>
struct cbuf *cbuf_new(void);
void cbuf_free(struct cbuf *cbuf);
/* Amount of data between <rd> and <wr> */
#define CBUF_DATA(wr, rd, size) (((wr) - (rd)) & ((size) - 1))
/* Return the writer position in <cbuf>.
* To be used only by the writer!
*/
static inline unsigned char *cb_wr(struct cbuf *cbuf)
{
return cbuf->buf + cbuf->wr;
}
/* Reset the reader index.
* To be used by a reader!
*/
static inline void cb_rd_reset(struct cbuf *cbuf)
{
cbuf->rd = 0;
}
/* Reset the writer index.
* To be used by a writer!
*/
static inline void cb_wr_reset(struct cbuf *cbuf)
{
cbuf->wr = 0;
}
/* Increase <cbuf> circular buffer data by <count>.
* To be used by a writer!
*/
static inline void cb_add(struct cbuf *cbuf, size_t count)
{
cbuf->wr = (cbuf->wr + count) & (CBUF_BUFSZ - 1);
}
/* Return the reader position in <cbuf>.
* To be used only by the reader!
*/
static inline unsigned char *cb_rd(struct cbuf *cbuf)
{
return cbuf->buf + cbuf->rd;
}
/* Skip <count> byte in <cbuf> circular buffer.
* To be used by a reader!
*/
static inline void cb_del(struct cbuf *cbuf, size_t count)
{
cbuf->rd = (cbuf->rd + count) & (CBUF_BUFSZ - 1);
}
/* Return the amount of data left in <cbuf>.
* To be used only by the writer!
*/
static inline int cb_data(struct cbuf *cbuf)
{
int rd;
rd = HA_ATOMIC_LOAD(&cbuf->rd);
return CBUF_DATA(cbuf->wr, rd, CBUF_BUFSZ);
}
/* Return the amount of room left in <cbuf> minus 1 to distinguish
* the case where the buffer is full from the case where is is empty
* To be used only by the write!
*/
static inline int cb_room(struct cbuf *cbuf)
{
int rd;
rd = HA_ATOMIC_LOAD(&cbuf->rd);
return CBUF_DATA(rd, cbuf->wr + 1, CBUF_BUFSZ);
}
/* Return the amount of contiguous data left in <cbuf>.
* To be used only by the reader!
*/
static inline int cb_contig_data(struct cbuf *cbuf)
{
int end, n;
end = CBUF_BUFSZ - cbuf->rd;
n = (HA_ATOMIC_LOAD(&cbuf->wr) + end) & (CBUF_BUFSZ - 1);
return n < end ? n : end;
}
/* Return the amount of contiguous space left in <cbuf>.
* To be used only by the writer!
*/
static inline int cb_contig_space(struct cbuf *cbuf)
{
int end, n;
end = CBUF_BUFSZ - 1 - cbuf->wr;
n = (HA_ATOMIC_LOAD(&cbuf->rd) + end) & (CBUF_BUFSZ - 1);
return n <= end ? n : end + 1;
}
#endif /* _HAPROXY_CBUF_H */

55
src/cbuf.c Normal file
View File

@ -0,0 +1,55 @@
/*
* Circular buffer management
*
* Copyright 2021 HAProxy Technologies, Frédéric Lécaille <flecaill@haproxy.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, version 2.1
* exclusively.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <haproxy/list.h>
#include <haproxy/pool.h>
#include <haproxy/cbuf-t.h>
DECLARE_POOL(pool_head_cbuf, "cbuf_pool", sizeof(struct cbuf));
/* Allocate and return a new circular buffer if succeeded, NULL if not. */
struct cbuf *cbuf_new(void)
{
struct cbuf *cbuf;
cbuf = pool_alloc(pool_head_cbuf);
if (cbuf) {
cbuf->wr = 0;
cbuf->rd = 0;
}
return cbuf;
}
/* Free QUIC ring <cbuf> */
void cbuf_free(struct cbuf *cbuf)
{
if (!cbuf)
return;
pool_free(pool_head_cbuf, cbuf);
}
/*
* Local variables:
* c-indent-level: 8
* c-basic-offset: 8
* End:
*/