Global replace of Nicira Networks.
[sliver-openvswitch.git] / lib / socket-util.c
index aded01c..82a33c2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
 #include <config.h>
 #include "socket-util.h"
 #include <arpa/inet.h>
+#include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <net/if.h>
@@ -81,6 +82,21 @@ set_nonblocking(int fd)
     }
 }
 
+static int
+set_dscp(int fd, uint8_t dscp)
+{
+    if (dscp > 63) {
+        return EINVAL;
+    }
+
+    dscp = dscp << 2;
+    if (setsockopt(fd, IPPROTO_IP, IP_TOS, &dscp, sizeof dscp)) {
+        return errno;
+    }
+
+    return 0;
+}
+
 static bool
 rlim_is_finite(rlim_t limit)
 {
@@ -546,8 +562,9 @@ exit:
  * If 'sinp' is non-null, then on success the target address is stored into
  * '*sinp'.
  *
- * 'dscp'  If not DSCP_INVALID, its value becomes the DSCP bits in the IP
- * headers for the new connection. */
+ * 'dscp' becomes the DSCP bits in the IP headers for the new connection.  It
+ * should be in the range [0, 63] and will automatically be shifted to the
+ * appropriately place in the IP tos field. */
 int
 inet_open_active(int style, const char *target, uint16_t default_port,
                  struct sockaddr_in *sinp, int *fdp, uint8_t dscp)
@@ -574,15 +591,13 @@ inet_open_active(int style, const char *target, uint16_t default_port,
         goto exit;
     }
 
-    /* The socket options set here ensure that the TOS bits are set during
-     * the connection establishment.  If set after connect(), the handshake
-     * SYN frames will be sent with a TOS of 0. */
-    if (dscp != DSCP_INVALID) {
-        if (setsockopt(fd, IPPROTO_IP, IP_TOS, &dscp, sizeof dscp)) {
-            VLOG_ERR("%s: socket: %s", target, strerror(errno));
-            error = errno;
-            goto exit;
-        }
+    /* The dscp bits must be configured before connect() to ensure that the TOS
+     * field is set during the connection establishment.  If set after
+     * connect(), the handshake SYN frames will be sent with a TOS of 0. */
+    error = set_dscp(fd, dscp);
+    if (error) {
+        VLOG_ERR("%s: socket: %s", target, strerror(error));
+        goto exit;
     }
 
     /* Connect. */
@@ -672,8 +687,9 @@ exit:
  * If 'sinp' is non-null, then on success the bound address is stored into
  * '*sinp'.
  *
- * 'dscp'  If not DSCP_INVALID, its value becomes the DSCP bits in the IP
- * headers for the new connection. */
+ * 'dscp' becomes the DSCP bits in the IP headers for the new connection.  It
+ * should be in the range [0, 63] and will automatically be shifted to the
+ * appropriately place in the IP tos field. */
 int
 inet_open_passive(int style, const char *target, int default_port,
                   struct sockaddr_in *sinp, uint8_t dscp)
@@ -711,15 +727,13 @@ inet_open_passive(int style, const char *target, int default_port,
         goto error;
     }
 
-    /* The socket options set here ensure that the TOS bits are set during
-     * the connection establishment.  If set after connect(), the handshake
-     * SYN frames will be sent with a TOS of 0. */
-    if (dscp != DSCP_INVALID) {
-        if (setsockopt(fd, IPPROTO_IP, IP_TOS, &dscp, sizeof dscp)) {
-            VLOG_ERR("%s: socket: %s", target, strerror(errno));
-            error = errno;
-            goto error;
-        }
+    /* The dscp bits must be configured before connect() to ensure that the TOS
+     * field is set during the connection establishment.  If set after
+     * connect(), the handshake SYN frames will be sent with a TOS of 0. */
+    error = set_dscp(fd, dscp);
+    if (error) {
+        VLOG_ERR("%s: socket: %s", target, strerror(error));
+        goto error;
     }
 
     /* Listen. */