From 89cf81b4625c574f60c21e0dce12b150f3c5583c Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Fri, 18 Jul 2014 11:40:44 +1000 Subject: [PATCH] 3896. [bug] Address performance issues with DSCP code on some platforms. [RT #36534] --- CHANGES | 3 +++ lib/isc/unix/net.c | 37 +++++++++++++++++++++++-------------- lib/isc/unix/socket.c | 41 +++++++++++++++++++++++------------------ lib/isc/win32/socket.c | 2 ++ 4 files changed, 51 insertions(+), 32 deletions(-) diff --git a/CHANGES b/CHANGES index cc6be576ed..6698f0ae00 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +3896. [bug] Address performance issues with DSCP code on some + platforms. [RT #36534] + 3895. [func] Add the ability to set the DSCP code point to dig. [RT #36546] diff --git a/lib/isc/unix/net.c b/lib/isc/unix/net.c index ad1a3413ad..31840ad644 100644 --- a/lib/isc/unix/net.c +++ b/lib/isc/unix/net.c @@ -614,7 +614,7 @@ try_dscp_v4(void) { int s, dscp = 0, n; #ifdef IP_RECVTOS int on = 1; -#endif +#endif /* IP_RECVTOS */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; @@ -648,23 +648,29 @@ try_dscp_v4(void) { on = 1; if (setsockopt(s, IPPROTO_IP, IP_RECVTOS, &on, sizeof(on)) == 0) dscp_result |= ISC_NET_DSCPRECVV4; -#endif +#endif /* IP_RECVTOS */ + #ifdef ISC_NET_BSD44MSGHDR + #ifndef ISC_CMSG_IP_TOS #ifdef __APPLE__ #define ISC_CMSG_IP_TOS 0 /* As of 10.8.2. */ -#else +#else /* ! __APPLE__ */ #define ISC_CMSG_IP_TOS 1 -#endif -#endif +#endif /* ! __APPLE__ */ +#endif /* ! ISC_CMSG_IP_TOS */ + #if ISC_CMSG_IP_TOS if (cmsgsend(s, IPPROTO_IP, IP_TOS, res0)) dscp_result |= ISC_NET_DSCPPKTV4; -#endif -#endif +#endif /* ISC_CMSG_IP_TOS */ + +#endif /* ISC_NET_BSD44MSGHDR */ + freeaddrinfo(res0); close(s); -#endif + +#endif /* IP_TOS */ } static void @@ -677,7 +683,7 @@ try_dscp_v6(void) { int s, dscp = 0, n; #if defined(IPV6_RECVTCLASS) int on = 1; -#endif +#endif /* IPV6_RECVTCLASS */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; @@ -709,16 +715,19 @@ try_dscp_v6(void) { on = 1; if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVTCLASS, &on, sizeof(on)) == 0) dscp_result |= ISC_NET_DSCPRECVV6; -#endif +#endif /* IPV6_RECVTCLASS */ + #ifdef ISC_NET_BSD44MSGHDR if (cmsgsend(s, IPPROTO_IPV6, IPV6_TCLASS, res0)) dscp_result |= ISC_NET_DSCPPKTV6; -#endif +#endif /* ISC_NET_BSD44MSGHDR */ + freeaddrinfo(res0); close(s); -#endif -#endif -#endif + +#endif /* IPV6_TCLASS */ +#endif /* WANT_IPV6 */ +#endif /* ISC_PLATFORM_HAVEIPV6 */ } static void diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index 2c5b1ee5d9..9ded1aefeb 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -363,7 +363,8 @@ struct isc__socket { connecting : 1, /* connect pending */ bound : 1, /* bound to local addr */ dupped : 1, - active : 1; /* currently active */ + active : 1, /* currently active */ + pktdscp : 1; /* per packet dscp */ #ifdef ISC_NET_RECVOVERFLOW unsigned char overflow; /* used for MSG_TRUNC fake */ @@ -378,7 +379,7 @@ struct isc__socket { isc_sockfdwatch_t fdwatchcb; int fdwatchflags; isc_task_t *fdwatchtask; - int dscp; + unsigned int dscp; }; #define SOCKET_MANAGER_MAGIC ISC_MAGIC('I', 'O', 'm', 'g') @@ -1527,11 +1528,12 @@ build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev, memmove(CMSG_DATA(cmsgp), &use_min_mtu, sizeof(use_min_mtu)); #endif } - if (isc_dscp_check_value != -1) { + + if (isc_dscp_check_value > -1) { if (sock->type == isc_sockettype_udp) INSIST((int)dev->dscp == isc_dscp_check_value); - if (sock->type == isc_sockettype_tcp) - INSIST(sock->dscp == isc_dscp_check_value); + else if (sock->type == isc_sockettype_tcp) + INSIST((int)sock->dscp == isc_dscp_check_value); } if ((sock->type == isc_sockettype_udp) && @@ -1539,10 +1541,10 @@ build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev, { int dscp = (dev->dscp << 2) & 0xff; + INSIST(dev->dscp < 0x40 && dev->dscp >= 0); + #ifdef IP_TOS - if (sock->pf == AF_INET && - ((isc_net_probedscp() & ISC_NET_DSCPPKTV4) != 0)) - { + if (sock->pf == AF_INET && sock->pktdscp) { cmsgp = (struct cmsghdr *)(sock->sendcmsgbuf + msg->msg_controllen); msg->msg_control = (void *)sock->sendcmsgbuf; @@ -1553,7 +1555,7 @@ build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev, cmsgp->cmsg_type = IP_TOS; cmsgp->cmsg_len = cmsg_len(sizeof(char)); *(unsigned char*)CMSG_DATA(cmsgp) = dscp; - } else if (sock->pf == AF_INET) { + } else if (sock->pf == AF_INET && sock->dscp != dev->dscp) { if (setsockopt(sock->fd, IPPROTO_IP, IP_TOS, (void *)&dscp, sizeof(int)) < 0) { @@ -1568,13 +1570,12 @@ build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev, ISC_MSG_FAILED, "failed"), strbuf); - } + } else + sock->dscp = dscp; } #endif #if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS) - if (sock->pf == AF_INET6 && - ((isc_net_probedscp() & ISC_NET_DSCPPKTV6) != 0)) - { + if (sock->pf == AF_INET6 && sock->pktdscp) { cmsgp = (struct cmsghdr *)(sock->sendcmsgbuf + msg->msg_controllen); msg->msg_control = (void *)sock->sendcmsgbuf; @@ -1585,7 +1586,7 @@ build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev, cmsgp->cmsg_type = IPV6_TCLASS; cmsgp->cmsg_len = cmsg_len(sizeof(dscp)); memmove(CMSG_DATA(cmsgp), &dscp, sizeof(dscp)); - } else if (sock->pf == AF_INET6) { + } else if (sock->pf == AF_INET6 && sock->dscp != dev->dscp) { if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_TCLASS, (void *)&dscp, sizeof(int)) < 0) { char strbuf[ISC_STRERRORSIZE]; @@ -1599,7 +1600,8 @@ build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev, ISC_MSG_FAILED, "failed"), strbuf); - } + } else + sock->dscp = dscp; } #endif } @@ -2257,7 +2259,7 @@ allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type, sock->manager = manager; sock->type = type; sock->fd = -1; - sock->dscp = -1; + sock->dscp = 0; /* TOS/TCLASS is zero until set. */ sock->dupped = 0; sock->statsindex = NULL; @@ -2328,6 +2330,7 @@ allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type, sock->connected = 0; sock->connecting = 0; sock->bound = 0; + sock->pktdscp = 0; /* * Initialize the lock. @@ -2861,6 +2864,8 @@ socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, case isc_sockettype_udp: sock->statsindex = (pf == AF_INET) ? udp4statsindex : udp6statsindex; +#define DCSPPKT(pf) ((pf == AF_INET) ? ISC_NET_DSCPPKTV4 : ISC_NET_DSCPPKTV6) + sock->pktdscp = (isc_net_probedscp() & DCSPPKT(pf)) != 0; break; case isc_sockettype_tcp: sock->statsindex = @@ -3566,8 +3571,7 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { /* * Ensure DSCP settings are inherited across accept. */ - if (sock->dscp != -1) - setdscp(NEWCONNSOCK(dev), sock->dscp); + setdscp(NEWCONNSOCK(dev), sock->dscp); /* * Save away the remote address @@ -6148,6 +6152,7 @@ isc__socket_dscp(isc_socket_t *sock0, isc_dscp_t dscp) { if (dscp < 0) return; + /* The DSCP value must not be changed once it has been set. */ if (isc_dscp_check_value != -1) INSIST(dscp == isc_dscp_check_value); #endif diff --git a/lib/isc/win32/socket.c b/lib/isc/win32/socket.c index 0c694b2b08..8f7197e12d 100644 --- a/lib/isc/win32/socket.c +++ b/lib/isc/win32/socket.c @@ -1090,6 +1090,7 @@ allocate_socketevent(isc_mem_t *mctx, isc_socket_t *sock, ev->attributes = 0; ev->destroy = ev->ev_destroy; ev->ev_destroy = destroy_socketevent; + ev->dscp = 0; return (ev); } @@ -1470,6 +1471,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, sock->manager = manager; sock->type = type; + sock->dscp = 0; /* TOS/TCLASS is zero until set. */ sock->fd = INVALID_SOCKET; ISC_LINK_INIT(sock, link);