mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-21 14:35:45 +00:00
MINOR: quic: add GSO parameter on quic_sock send API
Add <gso_size> parameter to qc_snd_buf(). When non-null, this specifies the value for socket option SOL_UDP/UDP_SEGMENT. This allows to send several datagrams in a single call by splitting data multiple times at <gso_size> boundary. For now, <gso_size> remains set to 0 by caller, as such there should not be any functional change.
This commit is contained in:
parent
96a34d79d9
commit
448d3d388a
@ -44,7 +44,7 @@ struct connection *quic_sock_accept_conn(struct listener *l, int *status);
|
|||||||
struct task *quic_lstnr_dghdlr(struct task *t, void *ctx, unsigned int state);
|
struct task *quic_lstnr_dghdlr(struct task *t, void *ctx, unsigned int state);
|
||||||
void quic_lstnr_sock_fd_iocb(int fd);
|
void quic_lstnr_sock_fd_iocb(int fd);
|
||||||
int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t count,
|
int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t count,
|
||||||
int flags);
|
int flags, uint16_t gso_size);
|
||||||
int qc_rcv_buf(struct quic_conn *qc);
|
int qc_rcv_buf(struct quic_conn *qc);
|
||||||
void quic_conn_sock_fd_iocb(int fd);
|
void quic_conn_sock_fd_iocb(int fd);
|
||||||
|
|
||||||
|
@ -654,7 +654,7 @@ static struct task *quic_conn_closed_io_cb(struct task *t, void *context, unsign
|
|||||||
|
|
||||||
buf = b_make(cc_qc->cc_buf_area + headlen,
|
buf = b_make(cc_qc->cc_buf_area + headlen,
|
||||||
QUIC_MAX_CC_BUFSIZE - headlen, 0, cc_qc->cc_dgram_len);
|
QUIC_MAX_CC_BUFSIZE - headlen, 0, cc_qc->cc_dgram_len);
|
||||||
if (qc_snd_buf(qc, &buf, buf.data, 0) < 0) {
|
if (qc_snd_buf(qc, &buf, buf.data, 0, 0) < 0) {
|
||||||
TRACE_ERROR("sendto fatal error", QUIC_EV_CONN_IO_CB, qc);
|
TRACE_ERROR("sendto fatal error", QUIC_EV_CONN_IO_CB, qc);
|
||||||
quic_release_cc_conn(cc_qc);
|
quic_release_cc_conn(cc_qc);
|
||||||
cc_qc = NULL;
|
cc_qc = NULL;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/udp.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
@ -652,8 +653,33 @@ static void cmsg_set_saddr(struct msghdr *msg, struct cmsghdr **cmsg,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a datagram stored into <buf> buffer with <sz> as size.
|
static void cmsg_set_gso(struct msghdr *msg, struct cmsghdr **cmsg,
|
||||||
* The caller must ensure there is at least <sz> bytes in this buffer.
|
uint16_t gso_size)
|
||||||
|
{
|
||||||
|
#ifdef UDP_SEGMENT
|
||||||
|
struct cmsghdr *c;
|
||||||
|
size_t sz = sizeof(gso_size);
|
||||||
|
|
||||||
|
/* Set first msg_controllen to be able to use CMSG_* macros. */
|
||||||
|
msg->msg_controllen += CMSG_SPACE(sz);
|
||||||
|
|
||||||
|
*cmsg = !(*cmsg) ? CMSG_FIRSTHDR(msg) : CMSG_NXTHDR(msg, *cmsg);
|
||||||
|
ALREADY_CHECKED(*cmsg);
|
||||||
|
c = *cmsg;
|
||||||
|
c->cmsg_len = CMSG_LEN(sz);
|
||||||
|
|
||||||
|
c->cmsg_level = SOL_UDP;
|
||||||
|
c->cmsg_type = UDP_SEGMENT;
|
||||||
|
c->cmsg_len = CMSG_LEN(sz);
|
||||||
|
*((uint16_t *)CMSG_DATA(c)) = gso_size;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send a datagram stored into <buf> buffer with <sz> as size. The caller must
|
||||||
|
* ensure there is at least <sz> bytes in this buffer.
|
||||||
|
*
|
||||||
|
* If <gso_size> is non null, it will be used as value for UDP_SEGMENT option.
|
||||||
|
* This allows to transmit multiple datagrams in a single syscall.
|
||||||
*
|
*
|
||||||
* Returns the total bytes sent over the socket. 0 is returned if a transient
|
* Returns the total bytes sent over the socket. 0 is returned if a transient
|
||||||
* error is encountered which allows send to be retry later. A negative value
|
* error is encountered which allows send to be retry later. A negative value
|
||||||
@ -664,7 +690,7 @@ static void cmsg_set_saddr(struct msghdr *msg, struct cmsghdr **cmsg,
|
|||||||
* done by removing the <qc> arg and replace it with address/port.
|
* done by removing the <qc> arg and replace it with address/port.
|
||||||
*/
|
*/
|
||||||
int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t sz,
|
int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t sz,
|
||||||
int flags)
|
int flags, uint16_t gso_size)
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
@ -673,15 +699,25 @@ int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t sz,
|
|||||||
|
|
||||||
union {
|
union {
|
||||||
#ifdef IP_PKTINFO
|
#ifdef IP_PKTINFO
|
||||||
char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
char buf[CMSG_SPACE(sizeof(struct in_pktinfo)) + CMSG_SPACE(sizeof(gso_size))];
|
||||||
#endif /* IP_PKTINFO */
|
#endif /* IP_PKTINFO */
|
||||||
#ifdef IPV6_RECVPKTINFO
|
#ifdef IPV6_RECVPKTINFO
|
||||||
char buf6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
|
char buf6[CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(gso_size))];
|
||||||
#endif /* IPV6_RECVPKTINFO */
|
#endif /* IPV6_RECVPKTINFO */
|
||||||
char bufaddr[CMSG_SPACE(sizeof(struct in_addr))];
|
char bufaddr[CMSG_SPACE(sizeof(struct in_addr)) + CMSG_SPACE(sizeof(gso_size))];
|
||||||
struct cmsghdr align;
|
struct cmsghdr align;
|
||||||
} ancillary_data;
|
} ancillary_data;
|
||||||
|
|
||||||
|
/* man 3 cmsg
|
||||||
|
*
|
||||||
|
* When initializing a buffer that will contain a
|
||||||
|
* series of cmsghdr structures (e.g., to be sent with
|
||||||
|
* sendmsg(2)), that buffer should first be
|
||||||
|
* zero-initialized to ensure the correct operation of
|
||||||
|
* CMSG_NXTHDR().
|
||||||
|
*/
|
||||||
|
memset(&ancillary_data, 0, sizeof(ancillary_data));
|
||||||
|
|
||||||
vec.iov_base = b_peek(buf, b_head_ofs(buf));
|
vec.iov_base = b_peek(buf, b_head_ofs(buf));
|
||||||
vec.iov_len = sz;
|
vec.iov_len = sz;
|
||||||
|
|
||||||
@ -717,6 +753,16 @@ int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t sz,
|
|||||||
cmsg_set_saddr(&msg, &cmsg, &qc->local_addr);
|
cmsg_set_saddr(&msg, &cmsg, &qc->local_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set GSO parameter if datagram size is bigger than MTU. */
|
||||||
|
if (gso_size) {
|
||||||
|
/* GSO size must be less than total data to sent for multiple datagrams. */
|
||||||
|
BUG_ON_HOT(b_data(buf) <= gso_size);
|
||||||
|
|
||||||
|
if (!msg.msg_control)
|
||||||
|
msg.msg_control = ancillary_data.bufaddr;
|
||||||
|
cmsg_set_gso(&msg, &cmsg, gso_size);
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = sendmsg(qc_fd(qc), &msg, MSG_DONTWAIT|MSG_NOSIGNAL);
|
ret = sendmsg(qc_fd(qc), &msg, MSG_DONTWAIT|MSG_NOSIGNAL);
|
||||||
} while (ret < 0 && errno == EINTR);
|
} while (ret < 0 && errno == EINTR);
|
||||||
|
@ -300,7 +300,7 @@ static int qc_send_ppkts(struct buffer *buf, struct ssl_sock_ctx *ctx)
|
|||||||
|
|
||||||
TRACE_PROTO("TX dgram", QUIC_EV_CONN_SPPKTS, qc);
|
TRACE_PROTO("TX dgram", QUIC_EV_CONN_SPPKTS, qc);
|
||||||
if (!skip_sendto) {
|
if (!skip_sendto) {
|
||||||
int ret = qc_snd_buf(qc, &tmpbuf, tmpbuf.data, 0);
|
int ret = qc_snd_buf(qc, &tmpbuf, tmpbuf.data, 0, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
TRACE_ERROR("sendto fatal error", QUIC_EV_CONN_SPPKTS, qc, first_pkt);
|
TRACE_ERROR("sendto fatal error", QUIC_EV_CONN_SPPKTS, qc, first_pkt);
|
||||||
qc_kill_conn(qc);
|
qc_kill_conn(qc);
|
||||||
|
Loading…
Reference in New Issue
Block a user