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