From 5731b8a19c7fddf18da56f93c23fa23045b6d4b0 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Wed, 13 Aug 2025 13:39:26 +0000 Subject: [PATCH] MEDIUM: xprt: Add a "get_capability" method. Add a new method to xprts, get_capability, that can be used to query if an xprt supports something or not. The first capability implemented is XPRT_CAN_SPLICE, to know if the xprt will be able to use splicing for the provided connection. The possible answers are XPRT_CONN_CAN_NOT_SPLICE, which indicates splicing will never be possible for that connection, XPRT_CONN_COULD_SPLICE, which indicates that splicing is not usable right now, but may be in the future, and XPRT_CONN_CAN_SPLICE, that means we can splice right away. --- include/haproxy/connection-t.h | 16 ++++++++++++++++ src/raw_sock.c | 14 ++++++++++++++ src/ssl_sock.c | 13 +++++++++++++ 3 files changed, 43 insertions(+) diff --git a/include/haproxy/connection-t.h b/include/haproxy/connection-t.h index 69a41d74e..35b7eaf34 100644 --- a/include/haproxy/connection-t.h +++ b/include/haproxy/connection-t.h @@ -433,6 +433,16 @@ union conn_handle { int fd; /* file descriptor, for regular sockets (CO_FL_FDLESS=0) */ }; +enum xprt_capabilities { + XPRT_CAN_SPLICE, +}; + +enum xprt_splice_cap { + XPRT_CONN_CAN_NOT_SPLICE, /* This connection can't, and won't ever be able to splice */ + XPRT_CONN_COULD_SPLICE, /* This connection can't splice, but may later */ + XPRT_CONN_CAN_SPLICE /* This connection can splice */ +}; + /* xprt_ops describes transport-layer operations for a connection. They * generally run over a socket-based control layer, but not always. Some * of them are used for data transfer with the upper layer (rcv_*, snd_*) @@ -464,6 +474,12 @@ struct xprt_ops { struct ssl_sock_ctx *(*get_ssl_sock_ctx)(struct connection *); /* retrieve the ssl_sock_ctx in use, or NULL if none */ int (*show_fd)(struct buffer *, const struct connection *, const void *ctx); /* append some data about xprt for "show fd"; returns non-zero if suspicious */ void (*dump_info)(struct buffer *, const struct connection *); + /* + * Returns the value for various capabilities. + * Returns 0 if the capability is known, iwth the actual value in arg, + * or -1 otherwise + */ + int (*get_capability)(struct connection *connection, void *xprt_ctx, enum xprt_capabilities, void *arg); }; /* mux_ops describes the mux operations, which are to be performed at the diff --git a/src/raw_sock.c b/src/raw_sock.c index a769c20f4..ddfe0e464 100644 --- a/src/raw_sock.c +++ b/src/raw_sock.c @@ -506,6 +506,19 @@ static int raw_sock_remove_xprt(struct connection *conn, void *xprt_ctx, void *t return -1; } +static int raw_sock_get_capability(struct connection *conn, void *xprt_ctx, enum xprt_capabilities cap, void *arg) +{ + int *ret; + + switch (cap) { + case XPRT_CAN_SPLICE: + ret = arg; + *ret = XPRT_CONN_CAN_SPLICE; + return 0; + } + return -1; +} + /* transport-layer operations for RAW sockets */ static struct xprt_ops raw_sock = { .snd_buf = raw_sock_from_buf, @@ -517,6 +530,7 @@ static struct xprt_ops raw_sock = { .rcv_pipe = raw_sock_to_pipe, .snd_pipe = raw_sock_from_pipe, #endif + .get_capability = raw_sock_get_capability, .shutr = NULL, .shutw = NULL, .close = raw_sock_close, diff --git a/src/ssl_sock.c b/src/ssl_sock.c index f67e30b0d..de4de7449 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -6981,6 +6981,18 @@ yield: } #endif +static int ssl_sock_get_capability(struct connection *conn, void *xprt_ctx, enum xprt_capabilities cap, void *arg) +{ + int *ret; + + switch (cap) { + case XPRT_CAN_SPLICE: + ret = arg; + *ret = XPRT_CONN_CAN_NOT_SPLICE; + return 0; + } + return -1; +} /* register cli keywords */ static struct cli_kw_list cli_kws = {{ },{ @@ -7011,6 +7023,7 @@ struct xprt_ops ssl_sock = { .close = ssl_sock_close, .init = ssl_sock_init, .start = ssl_sock_start, + .get_capability = ssl_sock_get_capability, .prepare_bind_conf = ssl_sock_prepare_bind_conf, .destroy_bind_conf = ssl_sock_destroy_bind_conf, .prepare_srv = ssl_sock_prepare_srv_ctx,