With this change there is no need to restart the DB or OVS on configuring a
different value for the manager or controller connection respectively. On
detecting a change in the dscp value on the socket, the previous socket is
closed and a new socket is created and connection is established with the new
configured dscp value.

Signed-off-by: Mehak Mahajan <mmaha...@nicira.com>
---
 lib/rconn.c                |    7 ++++
 lib/rconn.h                |    1 +
 lib/socket-util.c          |   85 ++++++++++++++++++++++++++++++++++++++++++--
 ofproto/connmgr.c          |   46 ++++++++++++++++++++++++
 vswitchd/vswitch.ovsschema |    4 +-
 vswitchd/vswitch.xml       |   14 +++----
 6 files changed, 144 insertions(+), 13 deletions(-)

diff --git a/lib/rconn.c b/lib/rconn.c
index 2ddfc69..954835e 100644
--- a/lib/rconn.c
+++ b/lib/rconn.c
@@ -664,6 +664,13 @@ rconn_set_name(struct rconn *rc, const char *new_name)
     rc->name = xstrdup(new_name);
 }
 
+/* Returns dscp value associated with the target in rconn. */
+const uint8_t
+rconn_get_dscp(const struct rconn *rc)
+{
+    return rc->dscp;
+}
+
 /* Returns 'rc''s target.  This is intended to be a string that may be passed
  * directly to, e.g., vconn_open(). */
 const char *
diff --git a/lib/rconn.h b/lib/rconn.h
index 2b1332c..7c32232 100644
--- a/lib/rconn.h
+++ b/lib/rconn.h
@@ -67,6 +67,7 @@ void rconn_add_monitor(struct rconn *, struct vconn *);
 const char *rconn_get_name(const struct rconn *);
 void rconn_set_name(struct rconn *, const char *new_name);
 const char *rconn_get_target(const struct rconn *);
+const uint8_t rconn_get_dscp(const struct rconn *);
 
 bool rconn_is_alive(const struct rconn *);
 bool rconn_is_connected(const struct rconn *);
diff --git a/lib/socket-util.c b/lib/socket-util.c
index 82a33c2..cb3542c 100644
--- a/lib/socket-util.c
+++ b/lib/socket-util.c
@@ -564,7 +564,9 @@ exit:
  *
  * '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. */
+ * appropriately place in the IP tos field.  If the dscp value has changed from
+ * from one call to the next, the exisitng socket is closed and a new socket is
+ * created and connected. */
 int
 inet_open_active(int style, const char *target, uint16_t default_port,
                  struct sockaddr_in *sinp, int *fdp, uint8_t dscp)
@@ -572,6 +574,7 @@ inet_open_active(int style, const char *target, uint16_t 
default_port,
     struct sockaddr_in sin;
     int fd = -1;
     int error;
+    static uint8_t socket_dscp = DSCP_DEFAULT;
 
     /* Parse. */
     if (!inet_parse_active(target, default_port, &sin)) {
@@ -586,6 +589,7 @@ inet_open_active(int style, const char *target, uint16_t 
default_port,
         error = errno;
         goto exit;
     }
+
     error = set_nonblocking(fd);
     if (error) {
         goto exit;
@@ -603,7 +607,43 @@ inet_open_active(int style, const char *target, uint16_t 
default_port,
     /* Connect. */
     error = connect(fd, (struct sockaddr *) &sin, sizeof sin) == 0 ? 0 : errno;
     if (error == EINPROGRESS) {
-        error = EAGAIN;
+
+        /* If the dscp value has changed, close the previous socket and create 
a
+         * new one. */
+        if (socket_dscp == dscp) {
+          error = EAGAIN;
+          goto exit;
+        }
+
+        /* Close previous socket. */
+        close(fd);
+        VLOG_ERR("MEHAK : %s DSCP = %d.\n", __FUNCTION__, dscp);
+        /* Create non-blocking socket. */
+        fd = socket(AF_INET, style, 0);
+        if (fd < 0) {
+            VLOG_ERR("%s: socket: %s", target, strerror(errno));
+            error = errno;
+            goto exit;
+        }
+
+        error = set_nonblocking(fd);
+        if (error) {
+            goto exit;
+        }
+
+        error = set_dscp(fd, dscp);
+        if (error) {
+            VLOG_ERR("%s: socket: %s", target, strerror(error));
+            goto exit;
+        }
+        socket_dscp = dscp;
+
+        /* Connect. */
+        error = connect(fd, (struct sockaddr *) &sin, sizeof sin) == 0 ?
+                    0 : errno;
+        if (error == EINPROGRESS) {
+            error = EAGAIN;
+        }
     }
 
 exit:
@@ -689,7 +729,9 @@ exit:
  *
  * '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. */
+ * appropriately place in the IP tos field. If the dscp value has changed from
+ * from one call to the next, the exisitng socket is closed and a new socket is
+ * created and connected. */
 int
 inet_open_passive(int style, const char *target, int default_port,
                   struct sockaddr_in *sinp, uint8_t dscp)
@@ -697,6 +739,7 @@ inet_open_passive(int style, const char *target, int 
default_port,
     struct sockaddr_in sin;
     int fd = 0, error;
     unsigned int yes = 1;
+    uint8_t socket_dscp = DSCP_DEFAULT;
 
     if (!inet_parse_passive(target, default_port, &sin)) {
         return -EAFNOSUPPORT;
@@ -736,6 +779,42 @@ inet_open_passive(int style, const char *target, int 
default_port,
         goto error;
     }
 
+    /* If the dscp value has changed, close the previous socket and create a
+     * new one. */
+    if (socket_dscp != dscp) {
+
+        /* Close previous socket. */
+        close(fd);
+
+        /* Create non-blocking socket, set SO_REUSEADDR. */
+        fd = socket(AF_INET, style, 0);
+        if (fd < 0) {
+            error = errno;
+            VLOG_ERR("%s: socket: %s", target, strerror(error));
+            return -error;
+        }
+        error = set_nonblocking(fd);
+        if (error) {
+            goto error;
+        }
+        if (style == SOCK_STREAM
+            && setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) < 0) 
{
+            error = errno;
+            VLOG_ERR("%s: setsockopt(SO_REUSEADDR): %s", target,
+                     strerror(error));
+            goto error;
+        }
+
+        /* Bind. */
+        if (bind(fd, (struct sockaddr *) &sin, sizeof sin) < 0) {
+            error = errno;
+            VLOG_ERR("%s: bind: %s", target, strerror(error));
+            goto error;
+        }
+
+        socket_dscp = dscp;
+    }
+
     /* Listen. */
     if (style == SOCK_STREAM && listen(fd, 10) < 0) {
         error = errno;
diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
index a0315b2..b0e6a5f 100644
--- a/ofproto/connmgr.c
+++ b/ofproto/connmgr.c
@@ -386,8 +386,13 @@ connmgr_retry(struct connmgr *mgr)
 /* OpenFlow configuration. */
 
 static void add_controller(struct connmgr *, const char *target, uint8_t dscp);
+static void
+reconfigure_controller(struct connmgr *mgr, const char *target, uint8_t dscp);
 static struct ofconn *find_controller_by_target(struct connmgr *,
                                                 const char *target);
+static
+bool has_controller_params_changed(struct connmgr *mgr, const char *target,
+                                   uint8_t dscp);
 static void update_fail_open(struct connmgr *);
 static int set_pvconns(struct pvconn ***pvconnsp, size_t *n_pvconnsp,
                        const struct sset *);
@@ -495,6 +500,10 @@ connmgr_set_controllers(struct connmgr *mgr,
                 VLOG_INFO("%s: added primary controller \"%s\"",
                           mgr->name, c->target);
                 add_controller(mgr, c->target, c->dscp);
+            } else if (has_controller_params_changed(mgr, c->target, c->dscp)) 
{
+                VLOG_INFO("%s: reconfiguring the controller \"%s\"",
+                          mgr->name, c->target);
+                reconfigure_controller(mgr, c->target, c->dscp);
             }
         } else if (!pvconn_verify_name(c->target)) {
             if (!ofservice_lookup(mgr, c->target)) {
@@ -608,6 +617,26 @@ add_controller(struct connmgr *mgr, const char *target, 
uint8_t dscp)
     free(name);
 }
 
+static void
+reconfigure_controller(struct connmgr *mgr, const char *target, uint8_t dscp)
+{
+    struct ofconn *ofconn;
+    char *name = ofconn_make_name(mgr, target);
+
+    HMAP_FOR_EACH_WITH_HASH (ofconn, hmap_node,
+                             hash_string(target, 0), &mgr->controllers) {
+        if (!strcmp(ofconn_get_target(ofconn), target)) {
+            /* Some value used for configuring the connection between the
+             * controller and switch has changed. Set the new value in 'rconn'
+             * and re-connect. */
+            rconn_set_dscp(ofconn->rconn, dscp);
+            rconn_connect(ofconn->rconn, target, name);
+        } else {
+            VLOG_ERR("error finding ofconn for target \"%s\"\n",target);
+        }
+    }
+}
+
 static struct ofconn *
 find_controller_by_target(struct connmgr *mgr, const char *target)
 {
@@ -622,6 +651,23 @@ find_controller_by_target(struct connmgr *mgr, const char 
*target)
     return NULL;
 }
 
+static bool
+has_controller_params_changed(struct connmgr *mgr, const char *target,
+                              uint8_t dscp)
+{
+    struct ofconn *ofconn;
+
+    HMAP_FOR_EACH_WITH_HASH (ofconn, hmap_node,
+                           hash_string(target, 0), &mgr->controllers) {
+        if (!strcmp(ofconn_get_target(ofconn), target)) {
+            if (rconn_get_dscp(ofconn) != dscp) {
+                return true;
+            }
+        }
+    }
+    return false;
+ }
+
 static void
 update_in_band_remotes(struct connmgr *mgr)
 {
diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema
index 9712003..18bd62b 100644
--- a/vswitchd/vswitch.ovsschema
+++ b/vswitchd/vswitch.ovsschema
@@ -1,6 +1,6 @@
 {"name": "Open_vSwitch",
- "version": "6.9.3",
- "cksum": "2110020336 16754",
+ "version": "6.9.4",
+ "cksum": "473114776 16754",
  "tables": {
    "Open_vSwitch": {
      "columns": {
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 32d4c59..780217c 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -2756,10 +2756,9 @@
         Service (QoS) on IP networks.
 
         The DSCP value specified here is used when establishing the connection
-        between the controller and the Open vSwitch.  The connection must be
-        reset for the new DSCP values to take effect.  If no value is
-        specified, a default value of 48 is chosen.  Valid DSCP values must be
-        in the range 0 to 63.
+        between the controller and the Open vSwitch.  If no value is specified,
+        a default value of 48 is chosen.  Valid DSCP values must be in the
+        range 0 to 63.
       </column>
     </group>
 
@@ -3003,10 +3002,9 @@
         Service (QoS) on IP networks.
 
         The DSCP value specified here is used when establishing the connection
-        between the manager and the Open vSwitch.  The connection must be
-        reset for the new DSCP values to take effect.  If no value is
-        specified, a default value of 48 is chosen.  Valid DSCP values must be
-        in the range 0 to 63.
+        between the manager and the Open vSwitch.  The new value is reflected
+        within a maximum of 8 seconds.  If no value is specified, a default
+        value of 48 is chosen.  Valid DSCP values must be in the range 0 to 63.
       </column>
     </group>
 
-- 
1.7.2.5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to