MINOR: quic: only use sendmsg() syscall variant
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.
This commit is contained in:
parent
8de9f8f193
commit
8b950f40fa
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
|
||||
union {
|
||||
#ifdef IP_PKTINFO
|
||||
char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
||||
#endif /* IP_PKTINFO */
|
||||
#ifdef IPV6_RECVPKTINFO
|
||||
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;
|
||||
|
||||
/* 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 {
|
||||
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 {
|
||||
#ifdef IP_PKTINFO
|
||||
char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
||||
#endif /* IP_PKTINFO */
|
||||
#ifdef IPV6_RECVPKTINFO
|
||||
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);
|
||||
}
|
||||
|
||||
ret = sendmsg(qc->li->rx.fd, &msg, MSG_DONTWAIT|MSG_NOSIGNAL);
|
||||
}
|
||||
ret = sendmsg(qc_fd(qc), &msg, MSG_DONTWAIT|MSG_NOSIGNAL);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
|
||||
if (ret < 0) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user