]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3896. [bug] Address performance issues with DSCP code on some
authorMark Andrews <marka@isc.org>
Fri, 18 Jul 2014 01:40:44 +0000 (11:40 +1000)
committerMark Andrews <marka@isc.org>
Fri, 18 Jul 2014 01:41:46 +0000 (11:41 +1000)
                        platforms. [RT #36534]

CHANGES
lib/isc/unix/net.c
lib/isc/unix/socket.c
lib/isc/win32/socket.c

diff --git a/CHANGES b/CHANGES
index a024a2d69882978530a3c6e2395bb2d21bd90e7c..32aefce60d9aa07e7cb1ede0d5ba2a0f5a95ad0e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+3896.  [bug]           Address performance issues with DSCP code on some
+                       platforms. [RT #36534]
+
 3894.  [bug]           Buffers in isc_print_vsnprintf were not properly
                        initialized leading to potential overflows when
                        printing out quad values. [RT #36505]
index ad1a3413ad7c8fb0c06ed39fae059513c382ce9b..31840ad644e0012761c8b1803f1689976f8337f9 100644 (file)
@@ -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
index 2c5b1ee5d9e05293f676dbf35dd0a05384283dd4..9ded1aefebd3085900a9d11d6d59f17188d622f1 100644 (file)
@@ -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
index 0c694b2b08b09cfd350c57a5f15bf3c779bed2d1..8f7197e12dc6b4ef66e89ee038d31230d8b9ce4d 100644 (file)
@@ -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);