Skip to content

Commit

Permalink
MINOR: quic: only use sendmsg() syscall variant
Browse files Browse the repository at this point in the history
This patch is the direct followup of the previous one :
  MINOR: quic: remove sendto() usage variant

This finalizes qc_snd_buf() simplification by removing send() syscall
usage for quic-conn owned socket. Syscall invocation is merged in a
single code location to the sendmsg() variant.

The only difference for owned socket is that destination address for
sendmsg() is set to NULL. This usage is documented in man 2 sendmsg as
valid for connected sockets. This allows maximum performance by avoiding
unnecessary lookups on kernel socket address tables.

As the previous patch, no functional change should happen here. However,
it will be simpler to extend qc_snd_buf() for GSO usage.
  • Loading branch information
a-denoyelle committed Feb 20, 2024
1 parent 8de9f8f commit 8b950f4
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 37 deletions.
8 changes: 8 additions & 0 deletions include/haproxy/quic_sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ static inline char qc_test_fd(struct quic_conn *qc)
return qc->fd >= 0;
}

/* Returns active socket for <qc> connection. This may be its owned connection
* socket or the listener one as a fallback.
*/
static inline int qc_fd(struct quic_conn *qc)
{
return qc_test_fd(qc) ? qc->fd : qc->li->rx.fd;
}

/* Try to increment <l> handshake current counter. If listener limit is
* reached, incrementation is rejected and 0 is returned.
*/
Expand Down
82 changes: 45 additions & 37 deletions src/quic_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -661,49 +661,57 @@ int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t sz,
int flags)
{
ssize_t ret;
struct msghdr msg;
struct iovec vec;
struct cmsghdr *cmsg __maybe_unused = NULL;

if (qc_test_fd(qc) && !fd_send_ready(qc->fd))
return 0;

do {
if (qc_test_fd(qc)) {
ret = send(qc->fd, b_peek(buf, b_head_ofs(buf)), sz,
MSG_DONTWAIT | MSG_NOSIGNAL);
}
else {
struct msghdr msg;
struct iovec vec;
struct cmsghdr *cmsg __maybe_unused = NULL;

union {
union {
#ifdef IP_PKTINFO
char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
#endif /* IP_PKTINFO */
#ifdef IPV6_RECVPKTINFO
char buf6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
char buf6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
#endif /* IPV6_RECVPKTINFO */
char bufaddr[CMSG_SPACE(sizeof(struct in_addr))];
struct cmsghdr align;
} ancillary_data;

vec.iov_base = b_peek(buf, b_head_ofs(buf));
vec.iov_len = sz;

msg.msg_name = &qc->peer_addr;
msg.msg_namelen = get_addr_len(&qc->peer_addr);
msg.msg_iov = &vec;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;

/* Set source address for listener socket if known. */
if (is_addr(&qc->local_addr)) {
msg.msg_control = ancillary_data.bufaddr;
cmsg_set_saddr(&msg, &cmsg, &qc->local_addr);
}
char bufaddr[CMSG_SPACE(sizeof(struct in_addr))];
struct cmsghdr align;
} ancillary_data;

ret = sendmsg(qc->li->rx.fd, &msg, MSG_DONTWAIT|MSG_NOSIGNAL);
}
vec.iov_base = b_peek(buf, b_head_ofs(buf));
vec.iov_len = sz;

/* man 2 sendmsg
*
* The msg_name field is used on an unconnected socket to specify the
* target address for a datagram. It points to a buffer containing the
* address; the msg_namelen field should be set to the size of the
* address. For a connected socket, these fields should be specified
* as NULL and 0, respectively.
*/
if (!qc_test_fd(qc)) {
msg.msg_name = &qc->peer_addr;
msg.msg_namelen = get_addr_len(&qc->peer_addr);
}
else {
msg.msg_name = NULL;
msg.msg_namelen = 0;
}

msg.msg_iov = &vec;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;

if (qc_test_fd(qc) && !fd_send_ready(qc->fd))
return 0;

/* Set source address when using listener socket if possible. */
if (!qc_test_fd(qc) && is_addr(&qc->local_addr)) {
msg.msg_control = ancillary_data.bufaddr;
cmsg_set_saddr(&msg, &cmsg, &qc->local_addr);
}

do {
ret = sendmsg(qc_fd(qc), &msg, MSG_DONTWAIT|MSG_NOSIGNAL);
} while (ret < 0 && errno == EINTR);

if (ret < 0) {
Expand Down

0 comments on commit 8b950f4

Please sign in to comment.