linux,udp: enable full ICMP error reporting
The Linux kernel suppresses some ICMP error messages by default for UDP sockets. This commit sets IP_RECVERR/IPV6_RECVERR on the socket to enable full ICMP error reporting, hopefully resulting in faster failover to working name servers. PR-URL: https://github.com/libuv/libuv/pull/2872 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
This commit is contained in:
parent
c464d21323
commit
c382d39a85
@ -53,6 +53,14 @@ Data types
|
||||
* in uv_udp_recv_cb, nread will always be 0 and addr will always be NULL.
|
||||
*/
|
||||
UV_UDP_MMSG_FREE = 16,
|
||||
/*
|
||||
* Indicates if IP_RECVERR/IPV6_RECVERR will be set when binding the handle.
|
||||
* This sets IP_RECVERR for IPv4 and IPV6_RECVERR for IPv6 UDP sockets on
|
||||
* Linux. This stops the Linux kernel from supressing some ICMP error messages
|
||||
* and enables full ICMP error reporting for faster failover.
|
||||
* This flag is no-op on platforms other than Linux.
|
||||
*/
|
||||
UV_UDP_LINUX_RECVERR = 32,
|
||||
/*
|
||||
* Indicates that recvmmsg should be used, if available.
|
||||
*/
|
||||
@ -178,7 +186,8 @@ API
|
||||
with the address and port to bind to.
|
||||
|
||||
:param flags: Indicate how the socket will be bound,
|
||||
``UV_UDP_IPV6ONLY`` and ``UV_UDP_REUSEADDR`` are supported.
|
||||
``UV_UDP_IPV6ONLY``, ``UV_UDP_REUSEADDR``, and ``UV_UDP_RECVERR``
|
||||
are supported.
|
||||
|
||||
:returns: 0 on success, or an error code < 0 on failure.
|
||||
|
||||
|
||||
@ -626,7 +626,14 @@ enum uv_udp_flags {
|
||||
* in uv_udp_recv_cb, nread will always be 0 and addr will always be NULL.
|
||||
*/
|
||||
UV_UDP_MMSG_FREE = 16,
|
||||
|
||||
/*
|
||||
* Indicates if IP_RECVERR/IPV6_RECVERR will be set when binding the handle.
|
||||
* This sets IP_RECVERR for IPv4 and IPV6_RECVERR for IPv6 UDP sockets on
|
||||
* Linux. This stops the Linux kernel from supressing some ICMP error messages
|
||||
* and enables full ICMP error reporting for faster failover.
|
||||
* This flag is no-op on platforms other than Linux.
|
||||
*/
|
||||
UV_UDP_LINUX_RECVERR = 32,
|
||||
/*
|
||||
* Indicates that recvmmsg should be used, if available.
|
||||
*/
|
||||
|
||||
@ -504,6 +504,28 @@ static int uv__set_reuse(int fd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The Linux kernel suppresses some ICMP error messages by default for UDP
|
||||
* sockets. Setting IP_RECVERR/IPV6_RECVERR on the socket enables full ICMP
|
||||
* error reporting, hopefully resulting in faster failover to working name
|
||||
* servers.
|
||||
*/
|
||||
static int uv__set_recverr(int fd, sa_family_t ss_family) {
|
||||
#if defined(__linux__)
|
||||
int yes;
|
||||
|
||||
yes = 1;
|
||||
if (ss_family == AF_INET) {
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_RECVERR, &yes, sizeof(yes)))
|
||||
return UV__ERR(errno);
|
||||
} else if (ss_family == AF_INET6) {
|
||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVERR, &yes, sizeof(yes)))
|
||||
return UV__ERR(errno);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv__udp_bind(uv_udp_t* handle,
|
||||
const struct sockaddr* addr,
|
||||
@ -514,7 +536,7 @@ int uv__udp_bind(uv_udp_t* handle,
|
||||
int fd;
|
||||
|
||||
/* Check for bad flags. */
|
||||
if (flags & ~(UV_UDP_IPV6ONLY | UV_UDP_REUSEADDR))
|
||||
if (flags & ~(UV_UDP_IPV6ONLY | UV_UDP_REUSEADDR | UV_UDP_LINUX_RECVERR))
|
||||
return UV_EINVAL;
|
||||
|
||||
/* Cannot set IPv6-only mode on non-IPv6 socket. */
|
||||
@ -530,6 +552,12 @@ int uv__udp_bind(uv_udp_t* handle,
|
||||
handle->io_watcher.fd = fd;
|
||||
}
|
||||
|
||||
if (flags & UV_UDP_LINUX_RECVERR) {
|
||||
err = uv__set_recverr(fd, addr->sa_family);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (flags & UV_UDP_REUSEADDR) {
|
||||
err = uv__set_reuse(fd);
|
||||
if (err)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user