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 <b...@nicira.com> --- NEWS | 3 ++ ofproto/connmgr.c | 60 +++++++++++++++++++++++++++----------------- ofproto/ofproto.h | 5 ++- vswitchd/bridge.c | 3 ++ vswitchd/vswitch.ovsschema | 7 +++- vswitchd/vswitch.xml | 21 ++++++++++++++- 6 files changed, 71 insertions(+), 28 deletions(-) diff --git a/NEWS b/NEWS index 0b97149..f52f912 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,9 @@ post-v1.5.0 - Added an OpenFlow extension NXT_SET_ASYNC_CONFIG that allows controllers more precise control over which OpenFlow messages they receive asynchronously. + - 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. v1.5.0 - xx xxx xxxx diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c index 5caa6bf..12319fe 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. */ @@ -90,7 +91,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 *); @@ -122,6 +123,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 *, @@ -285,7 +287,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) { @@ -563,7 +566,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)); @@ -955,7 +958,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; @@ -964,6 +968,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); @@ -977,8 +982,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; @@ -1020,23 +1023,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 @@ -1599,6 +1612,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 2d47878..ef9ccf5 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, 2011 Nicira Networks. + * Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -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 c40bcb5..ad2ff22 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -2293,6 +2293,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'. */ @@ -2308,6 +2309,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 9d91b0f..66fc39c 100644 --- a/vswitchd/vswitch.ovsschema +++ b/vswitchd/vswitch.ovsschema @@ -1,6 +1,6 @@ {"name": "Open_vSwitch", - "version": "6.4.0", - "cksum": "923041702 15687", + "version": "6.5.0", + "cksum": "870121236 15807", "tables": { "Open_vSwitch": { "columns": { @@ -367,6 +367,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 4b99b99..097ecb6 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -2336,7 +2336,26 @@ </column> </group> - <group title="OpenFlow Rate Limiting"> + <group title="Asynchronous Message Configuration"> + <p> + 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. + </p> + + <column name="enable_async_messages"> + 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 + <code>false</code> to change Open vSwitch behavior to disable, by + default, all asynchronous messages. The controller can use the + <code>NXT_SET_ASYNC_CONFIG</code> Nicira extension to OpenFlow to turn + on any messages that it does want to receive, if any. + </column> + <column name="controller_rate_limit"> <p> The maximum rate at which the switch will forward packets to the -- 1.7.2.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev