From 9886b6620ea710a4a8afd0a88271e563a64e7ea2 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 26 Jan 2012 14:50:41 -0800 Subject: [PATCH] vswitchd: Add "enable-async-messages" setting for controllers. An OpenFlow connection can start receiving asynchronous messages such as "packet-ins" immediately at connect time. If there is a lot of traffic on the network then this can swamp the controller before it gets a chance to set up an initial flow table. This setting overrides this OpenFlow behavior, changing it so that the connection initially enables no asynchronous messages at all. The controller can enable any messages that it actually wants when it is ready for them. Feature #7086. Signed-off-by: Ben Pfaff --- NEWS | 3 ++ ofproto/connmgr.c | 60 +++++++++++++++++++++++--------------- ofproto/ofproto.h | 3 +- vswitchd/bridge.c | 3 ++ vswitchd/vswitch.ovsschema | 7 +++-- vswitchd/vswitch.xml | 21 ++++++++++++- 6 files changed, 70 insertions(+), 27 deletions(-) diff --git a/NEWS b/NEWS index fde19f00d..a9cb1af9e 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,9 @@ post-v1.5.0 table, with configurable policy for evicting flows upon overflow. See the Flow_Table table in ovs-vswitch.conf.db(5) for more information. + - New "enable-async-messages" column in the Controller table. If set to + false, OpenFlow connections to the controller will initially have all + asynchronous messages disabled, overriding normal OpenFlow behavior. - ofproto-provider interface: - "struct rule" has a new member "used" that ofproto implementations should maintain by updating with ofproto_rule_update_used(). diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c index a3ffb691a..0cd7d53fa 100644 --- a/ofproto/connmgr.c +++ b/ofproto/connmgr.c @@ -52,6 +52,7 @@ struct ofconn { struct rconn *rconn; /* OpenFlow connection. */ enum ofconn_type type; /* Type. */ enum ofproto_band band; /* In-band or out-of-band? */ + bool enable_async_msgs; /* Initially enable async messages? */ /* State that should be cleared from one connection to the next. */ @@ -88,7 +89,7 @@ struct ofconn { }; static struct ofconn *ofconn_create(struct connmgr *, struct rconn *, - enum ofconn_type); + enum ofconn_type, bool enable_async_msgs); static void ofconn_destroy(struct ofconn *); static void ofconn_flush(struct ofconn *); @@ -120,6 +121,7 @@ struct ofservice { int probe_interval; /* Max idle time before probing, in seconds. */ int rate_limit; /* Max packet-in rate in packets per second. */ int burst_limit; /* Limit on accumulating packet credits. */ + bool enable_async_msgs; /* Initially enable async messages? */ }; static void ofservice_reconfigure(struct ofservice *, @@ -283,7 +285,8 @@ connmgr_run(struct connmgr *mgr, rconn_connect_unreliably(rconn, vconn, name); free(name); - ofconn = ofconn_create(mgr, rconn, OFCONN_SERVICE); + ofconn = ofconn_create(mgr, rconn, OFCONN_SERVICE, + ofservice->enable_async_msgs); ofconn_set_rate_limit(ofconn, ofservice->rate_limit, ofservice->burst_limit); } else if (retval != EAGAIN) { @@ -561,7 +564,7 @@ add_controller(struct connmgr *mgr, const char *target) char *name = ofconn_make_name(mgr, target); struct ofconn *ofconn; - ofconn = ofconn_create(mgr, rconn_create(5, 8), OFCONN_PRIMARY); + ofconn = ofconn_create(mgr, rconn_create(5, 8), OFCONN_PRIMARY, true); ofconn->pktbuf = pktbuf_create(); rconn_connect(ofconn->rconn, target, name); hmap_insert(&mgr->controllers, &ofconn->hmap_node, hash_string(target, 0)); @@ -953,7 +956,8 @@ ofconn_get_target(const struct ofconn *ofconn) } static struct ofconn * -ofconn_create(struct connmgr *mgr, struct rconn *rconn, enum ofconn_type type) +ofconn_create(struct connmgr *mgr, struct rconn *rconn, enum ofconn_type type, + bool enable_async_msgs) { struct ofconn *ofconn; @@ -962,6 +966,7 @@ ofconn_create(struct connmgr *mgr, struct rconn *rconn, enum ofconn_type type) list_push_back(&mgr->all_conns, &ofconn->node); ofconn->rconn = rconn; ofconn->type = type; + ofconn->enable_async_msgs = enable_async_msgs; list_init(&ofconn->opgroups); @@ -975,8 +980,6 @@ ofconn_create(struct connmgr *mgr, struct rconn *rconn, enum ofconn_type type) static void ofconn_flush(struct ofconn *ofconn) { - uint32_t *master = ofconn->master_async_config; - uint32_t *slave = ofconn->slave_async_config; int i; ofconn->role = NX_ROLE_OTHER; @@ -1018,23 +1021,33 @@ ofconn_flush(struct ofconn *ofconn) rconn_packet_counter_destroy(ofconn->reply_counter); ofconn->reply_counter = rconn_packet_counter_create(); - /* "master" and "other" roles get all asynchronous messages by default, - * except that the controller needs to enable nonstandard "packet-in" - * reasons itself. */ - master[OAM_PACKET_IN] = (1u << OFPR_NO_MATCH) | (1u << OFPR_ACTION); - master[OAM_PORT_STATUS] = ((1u << OFPPR_ADD) - | (1u << OFPPR_DELETE) - | (1u << OFPPR_MODIFY)); - master[OAM_FLOW_REMOVED] = ((1u << OFPRR_IDLE_TIMEOUT) - | (1u << OFPRR_HARD_TIMEOUT) - | (1u << OFPRR_DELETE)); - - /* "slave" role gets port status updates by default. */ - slave[OAM_PACKET_IN] = 0; - slave[OAM_PORT_STATUS] = ((1u << OFPPR_ADD) - | (1u << OFPPR_DELETE) - | (1u << OFPPR_MODIFY)); - slave[OAM_FLOW_REMOVED] = 0; + if (ofconn->enable_async_msgs) { + uint32_t *master = ofconn->master_async_config; + uint32_t *slave = ofconn->slave_async_config; + + /* "master" and "other" roles get all asynchronous messages by default, + * except that the controller needs to enable nonstandard "packet-in" + * reasons itself. */ + master[OAM_PACKET_IN] = (1u << OFPR_NO_MATCH) | (1u << OFPR_ACTION); + master[OAM_PORT_STATUS] = ((1u << OFPPR_ADD) + | (1u << OFPPR_DELETE) + | (1u << OFPPR_MODIFY)); + master[OAM_FLOW_REMOVED] = ((1u << OFPRR_IDLE_TIMEOUT) + | (1u << OFPRR_HARD_TIMEOUT) + | (1u << OFPRR_DELETE)); + + /* "slave" role gets port status updates by default. */ + slave[OAM_PACKET_IN] = 0; + slave[OAM_PORT_STATUS] = ((1u << OFPPR_ADD) + | (1u << OFPPR_DELETE) + | (1u << OFPPR_MODIFY)); + slave[OAM_FLOW_REMOVED] = 0; + } else { + memset(ofconn->master_async_config, 0, + sizeof ofconn->master_async_config); + memset(ofconn->slave_async_config, 0, + sizeof ofconn->slave_async_config); + } } static void @@ -1597,6 +1610,7 @@ ofservice_reconfigure(struct ofservice *ofservice, ofservice->probe_interval = c->probe_interval; ofservice->rate_limit = c->rate_limit; ofservice->burst_limit = c->burst_limit; + ofservice->enable_async_msgs = c->enable_async_msgs; } /* Finds and returns the ofservice within 'mgr' that has the given diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index 6aec062c8..860c51420 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -121,7 +121,8 @@ struct ofproto_controller { char *target; /* e.g. "tcp:127.0.0.1" */ 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? */ + enum ofproto_band band; /* In-band or out-of-band? */ + bool enable_async_msgs; /* Initially enable asynchronous messages? */ /* OpenFlow packet-in rate-limiting. */ int rate_limit; /* Max packet-in rate in packets per second. */ diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 15fb632da..f6cf1196d 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -2328,6 +2328,7 @@ bridge_ofproto_controller_for_mgmt(const struct bridge *br, oc->band = OFPROTO_OUT_OF_BAND; oc->rate_limit = 0; oc->burst_limit = 0; + oc->enable_async_msgs = true; } /* Converts ovsrec_controller 'c' into an ofproto_controller in 'oc'. */ @@ -2343,6 +2344,8 @@ bridge_ofproto_controller_from_ovsrec(const struct ovsrec_controller *c, oc->rate_limit = c->controller_rate_limit ? *c->controller_rate_limit : 0; oc->burst_limit = (c->controller_burst_limit ? *c->controller_burst_limit : 0); + oc->enable_async_msgs = (!c->enable_async_messages + || *c->enable_async_messages); } /* Configures the IP stack for 'br''s local interface properly according to the diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema index c260c43d0..e4ae893c3 100644 --- a/vswitchd/vswitch.ovsschema +++ b/vswitchd/vswitch.ovsschema @@ -1,6 +1,6 @@ {"name": "Open_vSwitch", - "version": "6.6.0", - "cksum": "3676036878 16515", + "version": "6.7.0", + "cksum": "1451320369 16635", "tables": { "Open_vSwitch": { "columns": { @@ -389,6 +389,9 @@ "local_gateway": { "type": {"key": {"type": "string"}, "min": 0, "max": 1}}, + "enable_async_messages": { + "type": {"key": {"type": "boolean"}, + "min": 0, "max": 1}}, "controller_rate_limit": { "type": {"key": {"type": "integer", "minInteger": 100}, diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index 9e38d7f2d..a248d9fbf 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -2489,7 +2489,26 @@ - + +

+ OpenFlow switches send certain messages to controllers spontanenously, + that is, not in response to any request from the controller. These + messages are called ``asynchronous messages.'' These columns allow + asynchronous messages to be limited or disabled to ensure the best use + of network resources. +

+ + + The OpenFlow protocol enables asynchronous messages at time of + connection establishment, which means that a controller can receive + asynchronous messages, potentially many of them, even if it turns them + off immediately after connecting. Set this column to + false to change Open vSwitch behavior to disable, by + default, all asynchronous messages. The controller can use the + NXT_SET_ASYNC_CONFIG Nicira extension to OpenFlow to turn + on any messages that it does want to receive, if any. + +

The maximum rate at which the switch will forward packets to the -- 2.20.1