From patchwork Mon Oct 29 22:57:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 990600 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ovn.org Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42kVRp6xGxz9s5c for ; Tue, 30 Oct 2018 10:00:06 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 35299347E; Mon, 29 Oct 2018 22:58:26 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 092033451 for ; Mon, 29 Oct 2018 22:58:06 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay12.mail.gandi.net (relay12.mail.gandi.net [217.70.178.232]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 7F15D75B for ; Mon, 29 Oct 2018 22:58:04 +0000 (UTC) Received: from sigabrt.benpfaff.org (unknown [208.91.3.26]) (Authenticated sender: blp@ovn.org) by relay12.mail.gandi.net (Postfix) with ESMTPSA id EB8B7200002; Mon, 29 Oct 2018 22:58:01 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Mon, 29 Oct 2018 15:57:50 -0700 Message-Id: <20181029225751.5936-5-blp@ovn.org> X-Mailer: git-send-email 2.16.1 In-Reply-To: <20181029225751.5936-1-blp@ovn.org> References: <20181029225751.5936-1-blp@ovn.org> X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Ben Pfaff Subject: [ovs-dev] [PATCH 5/6] vswitchd: Allow user to configure controllers as "primary" or "service". X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Normally it makes sense for an active connection to be primary and a passive connection to be a service connection, but I've run into a corner case where it is better for a passive connection to be a primary connection. This specific case is for use with OFtest, which expects to be a primary controller. However, it also wants to reconnect frequently, which is slow for active connections because of the backoff; by configuring a passive, primary controller, OFtest can reconnect as frequently and as quickly as it wants, making the overall test much faster. Signed-off-by: Ben Pfaff Acked-by: Justin Pettit --- ofproto/connmgr.c | 29 +++++------- ofproto/connmgr.h | 21 --------- ofproto/ofproto.c | 6 +++ ofproto/ofproto.h | 18 ++++++++ vswitchd/bridge.c | 11 +++++ vswitchd/vswitch.ovsschema | 8 +++- vswitchd/vswitch.xml | 111 ++++++++++++++++++++++----------------------- 7 files changed, 106 insertions(+), 98 deletions(-) diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c index 30d543d220e5..1674db1594a8 100644 --- a/ofproto/connmgr.c +++ b/ofproto/connmgr.c @@ -142,7 +142,7 @@ struct ofconn { static unsigned int bundle_idle_timeout = BUNDLE_IDLE_TIMEOUT_DEFAULT; -static void ofconn_create(struct ofservice *, struct rconn *, enum ofconn_type, +static void ofconn_create(struct ofservice *, struct rconn *, const struct ofproto_controller *settings) OVS_EXCLUDED(ofproto_mutex); static void ofconn_destroy(struct ofconn *) OVS_REQUIRES(ofproto_mutex); @@ -1150,7 +1150,7 @@ bundle_remove_expired(struct ofconn *ofconn, long long int now) static void ofconn_create(struct ofservice *ofservice, struct rconn *rconn, - enum ofconn_type type, const struct ofproto_controller *settings) + const struct ofproto_controller *settings) OVS_EXCLUDED(ofproto_mutex) { ovs_mutex_lock(&ofproto_mutex); @@ -1164,7 +1164,7 @@ ofconn_create(struct ofservice *ofservice, struct rconn *rconn, ovs_list_push_back(&ofservice->conns, &ofconn->ofservice_node); ofconn->rconn = rconn; - ofconn->type = type; + ofconn->type = settings->type; ofconn->band = settings->band; ofconn->role = OFPCR12_ROLE_EQUAL; @@ -1708,8 +1708,9 @@ connmgr_get_max_probe_interval(const struct connmgr *mgr) return max_probe_interval; } -/* Returns the number of seconds for which all of 'mgr's primary controllers - * have been disconnected. Returns 0 if 'mgr' has no primary controllers. */ +/* Returns the number of seconds for which all of 'mgr's active, primary + * controllers have been disconnected. Returns 0 if 'mgr' has no active, + * primary controllers. */ int connmgr_failure_duration(const struct connmgr *mgr) { @@ -1717,7 +1718,7 @@ connmgr_failure_duration(const struct connmgr *mgr) struct ofservice *ofservice; HMAP_FOR_EACH (ofservice, hmap_node, &mgr->services) { - if (ofservice->rconn) { + if (ofservice->s.type == OFCONN_PRIMARY && ofservice->rconn) { int failure_duration = rconn_failure_duration(ofservice->rconn); min_failure_duration = MIN(min_failure_duration, failure_duration); } @@ -1734,7 +1735,8 @@ connmgr_is_any_controller_connected(const struct connmgr *mgr) { struct ofservice *ofservice; HMAP_FOR_EACH (ofservice, hmap_node, &mgr->services) { - if (ofservice->rconn && rconn_is_connected(ofservice->rconn)) { + if (ofservice->s.type == OFCONN_PRIMARY + && !ovs_list_is_empty(&ofservice->conns)) { return true; } } @@ -1905,7 +1907,7 @@ ofservice_create(struct connmgr *mgr, const char *target, ofservice->connmgr = mgr; ofservice->target = xstrdup(target); ovs_list_init(&ofservice->conns); - ofservice->type = rconn ? OFCONN_PRIMARY : OFCONN_SERVICE; + ofservice->type = c->type; ofservice->rconn = rconn; ofservice->pvconn = pvconn; ofservice->s = *c; @@ -1962,7 +1964,7 @@ ofservice_run(struct ofservice *ofservice) rconn_connect_unreliably(rconn, vconn, name); free(name); - ofconn_create(ofservice, rconn, OFCONN_SERVICE, &ofservice->s); + ofconn_create(ofservice, rconn, &ofservice->s); } else if (retval != EAGAIN) { VLOG_WARN_RL(&rl, "accept failed (%s)", ovs_strerror(retval)); } @@ -1972,8 +1974,7 @@ ofservice_run(struct ofservice *ofservice) bool connected = rconn_is_connected(ofservice->rconn); bool has_ofconn = !ovs_list_is_empty(&ofservice->conns); if (connected && !has_ofconn) { - ofconn_create(ofservice, ofservice->rconn, OFCONN_PRIMARY, - &ofservice->s); + ofconn_create(ofservice, ofservice->rconn, &ofservice->s); } } } @@ -2287,12 +2288,6 @@ ofmonitor_wait(struct connmgr *mgr) ovs_mutex_unlock(&ofproto_mutex); } -const char * -ofconn_type_to_string(enum ofconn_type type) -{ - return type == OFCONN_PRIMARY ? "primary" : "service"; -} - void ofproto_async_msg_free(struct ofproto_async_msg *am) { diff --git a/ofproto/connmgr.h b/ofproto/connmgr.h index 11c8f9a85121..46f75b3dcf2f 100644 --- a/ofproto/connmgr.h +++ b/ofproto/connmgr.h @@ -37,27 +37,6 @@ struct rule; struct simap; struct sset; -/* ofproto supports two kinds of OpenFlow connections: - * - * - "Primary" connections to ordinary OpenFlow controllers. ofproto - * maintains persistent connections to these controllers and by default - * sends them asynchronous messages such as packet-ins. - * - * - "Service" connections, e.g. from ovs-ofctl. When these connections - * drop, it is the other side's responsibility to reconnect them if - * necessary. ofproto does not send them asynchronous messages by default. - * - * Currently, active (tcp, ssl, unix) connections are always "primary" - * connections and passive (ptcp, pssl, punix) connections are always "service" - * connections. There is no inherent reason for this, but it reflects the - * common case. - */ -enum ofconn_type { - OFCONN_PRIMARY, /* An ordinary OpenFlow controller. */ - OFCONN_SERVICE /* A service connection, e.g. "ovs-ofctl". */ -}; -const char *ofconn_type_to_string(enum ofconn_type); - /* An asynchronous message that might need to be queued between threads. */ struct ofproto_async_msg { struct ovs_list list_node; /* For queuing. */ diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 222c749940ec..29a40cd539f5 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -1892,6 +1892,12 @@ ofproto_free_ofproto_controller_info(struct shash *info) connmgr_free_controller_info(info); } +const char * +ofconn_type_to_string(enum ofconn_type type) +{ + return type == OFCONN_PRIMARY ? "primary" : "service"; +} + /* Makes a deep copy of 'old' into 'port'. */ void ofproto_port_clone(struct ofproto_port *port, const struct ofproto_port *old) diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index 595729dd61f1..50208d481862 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -207,7 +207,25 @@ enum ofproto_band { OFPROTO_OUT_OF_BAND /* Out-of-band connection to controller. */ }; +/* ofproto supports two kinds of OpenFlow connections: + * + * - "Primary" connections to ordinary OpenFlow controllers. ofproto + * maintains persistent connections to these controllers and by default + * sends them asynchronous messages such as packet-ins. + * + * - "Service" connections, e.g. from ovs-ofctl. When these connections + * drop, it is the other side's responsibility to reconnect them if + * necessary. ofproto does not send them asynchronous messages by default. + */ +enum ofconn_type { + OFCONN_PRIMARY, /* An ordinary OpenFlow controller. */ + OFCONN_SERVICE /* A service connection, e.g. "ovs-ofctl". */ +}; +const char *ofconn_type_to_string(enum ofconn_type); + +/* Configuration for an OpenFlow controller. */ struct ofproto_controller { + enum ofconn_type type; /* Primary or service controller. */ int max_backoff; /* Maximum reconnection backoff, in seconds. */ int probe_interval; /* Max idle time before probing, in seconds. */ enum ofproto_band band; /* In-band or out-of-band? */ diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index de5793dd03e4..a427b0122b49 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -46,6 +46,7 @@ #include "openvswitch/meta-flow.h" #include "openvswitch/ofp-print.h" #include "openvswitch/ofpbuf.h" +#include "openvswitch/vconn.h" #include "openvswitch/vlog.h" #include "ovs-lldp.h" #include "ovs-numa.h" @@ -3536,6 +3537,14 @@ equal_pathnames(const char *a, const char *b, size_t b_stoplen) } } +static enum ofconn_type +get_controller_ofconn_type(const char *target, const char *type) +{ + return (type + ? (!strcmp(type, "primary") ? OFCONN_PRIMARY : OFCONN_SERVICE) + : (!vconn_verify_name(target) ? OFCONN_PRIMARY : OFCONN_SERVICE)); +} + static void bridge_configure_remotes(struct bridge *br, const struct sockaddr_in *managers, size_t n_managers) @@ -3571,6 +3580,7 @@ bridge_configure_remotes(struct bridge *br, /* Add managment controller. */ struct ofproto_controller *oc = xmalloc(sizeof *oc); *oc = (struct ofproto_controller) { + .type = OFCONN_SERVICE, .probe_interval = 60, .band = OFPROTO_OUT_OF_BAND, .enable_async_msgs = true, @@ -3639,6 +3649,7 @@ bridge_configure_remotes(struct bridge *br, oc = xmalloc(sizeof *oc); *oc = (struct ofproto_controller) { + .type = get_controller_ofconn_type(c->target, c->type), .max_backoff = c->max_backoff ? *c->max_backoff / 1000 : 8, .probe_interval = (c->inactivity_probe ? *c->inactivity_probe / 1000 : 5), diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema index 1e4e342dcb96..9be4ca54ecd3 100644 --- a/vswitchd/vswitch.ovsschema +++ b/vswitchd/vswitch.ovsschema @@ -1,6 +1,6 @@ {"name": "Open_vSwitch", - "version": "7.16.1", - "cksum": "1452282319 23860", + "version": "7.17.0", + "cksum": "2073324140 24021", "tables": { "Open_vSwitch": { "columns": { @@ -548,6 +548,10 @@ "indexes": [["id", "bridge"]]}, "Controller": { "columns": { + "type": { + "type": {"key": {"type": "string", + "enum": ["set", ["primary", "service"]]}, + "min": 0, "max": 1}}, "target": { "type": "string"}, "max_backoff": { diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index 6d1fc1c1c7b0..08bec290ae18 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -967,9 +967,12 @@ avoid loops on such a bridge, configure secure mode or enable STP (see ).

-

When more than one controller is configured, - is considered only when none of the - configured controllers can be contacted.

+

+ The setting applies only to primary + controllers. When more than one primary controller is configured, + is considered only when none of the + configured controllers can be contacted. +

Changing when no primary controllers are configured clears the OpenFlow flow tables, group table, and meter @@ -4453,71 +4456,64 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \

An OpenFlow controller.

-

- Open vSwitch supports two kinds of OpenFlow controllers: -

- -
-
Primary controllers
-
+ +

- This is the kind of controller envisioned by the OpenFlow 1.0 - specification. Usually, a primary controller implements a network - policy by taking charge of the switch's flow table. + Open vSwitch supports two kinds of OpenFlow controllers. A bridge + may have any number of each kind:

-

- Open vSwitch initiates and maintains persistent connections to - primary controllers, retrying the connection each time it fails or - drops. The column in the - table applies to primary controllers. -

+
+
Primary controllers
+
+

+ This is the kind of controller envisioned by the OpenFlow + specifications. Usually, a primary controller implements a + network policy by taking charge of the switch's flow table. +

-

- Open vSwitch permits a bridge to have any number of primary - controllers. When multiple controllers are configured, Open - vSwitch connects to all of them simultaneously. Because - OpenFlow 1.0 does not specify how multiple controllers - coordinate in interacting with a single switch, more than - one primary controller should be specified only if the - controllers are themselves designed to coordinate with each - other. (The Nicira-defined NXT_ROLE OpenFlow - vendor extension may be useful for this.) -

-
-
Service controllers
-
-

- These kinds of OpenFlow controller connections are intended for - occasional support and maintenance use, e.g. with - ovs-ofctl. Usually a service controller connects only - briefly to inspect or modify some of a switch's state. -

+

+ The column in the table applies to primary controllers. +

-

- Open vSwitch listens for incoming connections from service - controllers. The service controllers initiate and, if necessary, - maintain the connections from their end. The column in the table does - not apply to service controllers. -

+

+ When multiple primary controllers are configured, Open vSwitch + connects to all of them simultaneously. OpenFlow provides few + facilities to allow multiple controllers to coordinate in + interacting with a single switch, so more than one primary + controller should be specified only if the controllers are + themselves designed to coordinate with each other. +

+
+
Service controllers
+
+

+ These kinds of OpenFlow controller connections are intended for + occasional support and maintenance use, e.g. with + ovs-ofctl. Usually a service controller connects + only briefly to inspect or modify some of a switch's state. +

+ +

+ The column in the table does not apply to service controllers. +

+
+

- Open vSwitch supports configuring any number of service controllers. + By default, Open vSwitch treats controllers with active connection + methods as primary controllers and those with passive connection + methods as service controllers. Set this column to the desired type + to override this default.

-
-
- -

- The determines the type of controller. -

+ -

Connection method for controller.

- The following connection methods are currently supported for primary - controllers: + The following active connection methods are currently supported:

ssl:host[:port]
@@ -4546,8 +4542,7 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \

- The following connection methods are currently supported for service - controllers: + The following passive connection methods are currently supported:

pssl:[port][:host]