From: Amaury Denoyelle Date: Tue, 20 Feb 2024 10:23:17 +0000 (+0100) Subject: OPTIM: quic: improve slightly qc_snd_buf() internal X-Git-Tag: v3.0-dev4~23 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=107d6d75465419a09d90c790edb617091a04468a;p=thirdparty%2Fhaproxy.git OPTIM: quic: improve slightly qc_snd_buf() internal qc_snd_buf() is a wrapper for sendmsg() syscall (or its derivatives) used for all QUIC emissions. This patch aims at removing several non-optimal code sections : * fd_send_ready() for connected sockets is only checked on the function preambule instead of inside the emission loop * zero-ing msghdr structure for unconnected sockets is removed. This is unnecessary as all fields are properly initialized then. * extra memcpy/memset invocations when using IP_PKTINFO/IPV6_RECVPKTINFO are removed by setting directly the address value into cmsg buffer --- diff --git a/src/quic_sock.c b/src/quic_sock.c index f79651334b..47534beb32 100644 --- a/src/quic_sock.c +++ b/src/quic_sock.c @@ -582,31 +582,31 @@ int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t sz, { ssize_t ret; + if (qc_test_fd(qc) && !fd_send_ready(qc->fd)) + return 0; + do { if (qc_test_fd(qc)) { - if (!fd_send_ready(qc->fd)) - return 0; - ret = send(qc->fd, b_peek(buf, b_head_ofs(buf)), sz, MSG_DONTWAIT | MSG_NOSIGNAL); } #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) || defined(IPV6_RECVPKTINFO) else if (is_addr(&qc->local_addr)) { - struct msghdr msg = { 0 }; + struct msghdr msg; struct iovec vec; struct cmsghdr *cmsg; #ifdef IP_PKTINFO - struct in_pktinfo in; + struct in_pktinfo *in; #endif /* IP_PKTINFO */ #ifdef IPV6_RECVPKTINFO - struct in6_pktinfo in6; + struct in6_pktinfo *in6; #endif /* IPV6_RECVPKTINFO */ union { #ifdef IP_PKTINFO - char buf[CMSG_SPACE(sizeof(in))]; + char buf[CMSG_SPACE(sizeof(struct in_pktinfo))]; #endif /* IP_PKTINFO */ #ifdef IPV6_RECVPKTINFO - char buf6[CMSG_SPACE(sizeof(in6))]; + char buf6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; #endif /* IPV6_RECVPKTINFO */ char bufaddr[CMSG_SPACE(sizeof(struct in_addr))]; struct cmsghdr align; @@ -622,19 +622,20 @@ int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t sz, switch (qc->local_addr.ss_family) { case AF_INET: #if defined(IP_PKTINFO) - memset(&in, 0, sizeof(in)); - memcpy(&in.ipi_spec_dst, - &((struct sockaddr_in *)&qc->local_addr)->sin_addr, - sizeof(struct in_addr)); - msg.msg_control = u.buf; msg.msg_controllen = sizeof(u.buf); cmsg = CMSG_FIRSTHDR(&msg); + in = (struct in_pktinfo *)CMSG_DATA(cmsg); + in->ipi_ifindex = 0; + in->ipi_addr.s_addr = 0; + memcpy(&in->ipi_spec_dst, + &((struct sockaddr_in *)&qc->local_addr)->sin_addr, + sizeof(struct in_addr)); + cmsg->cmsg_level = IPPROTO_IP; cmsg->cmsg_type = IP_PKTINFO; cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); - memcpy(CMSG_DATA(cmsg), &in, sizeof(in)); #elif defined(IP_RECVDSTADDR) msg.msg_control = u.bufaddr; msg.msg_controllen = sizeof(u.bufaddr); @@ -651,19 +652,19 @@ int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t sz, case AF_INET6: #ifdef IPV6_RECVPKTINFO - memset(&in6, 0, sizeof(in6)); - memcpy(&in6.ipi6_addr, - &((struct sockaddr_in6 *)&qc->local_addr)->sin6_addr, - sizeof(struct in6_addr)); - msg.msg_control = u.buf6; msg.msg_controllen = sizeof(u.buf6); cmsg = CMSG_FIRSTHDR(&msg); + in6 = (struct in6_pktinfo *)CMSG_DATA(cmsg); + in6->ipi6_ifindex = 0; + memcpy(&in6->ipi6_addr, + &((struct sockaddr_in6 *)&qc->local_addr)->sin6_addr, + sizeof(struct in6_addr)); + cmsg->cmsg_level = IPPROTO_IPV6; cmsg->cmsg_type = IPV6_PKTINFO; cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); - memcpy(CMSG_DATA(cmsg), &in6, sizeof(in6)); #endif /* IPV6_RECVPKTINFO */ break;