vswitchd: Add "enable-async-messages" setting for controllers.
authorBen Pfaff <blp@nicira.com>
Thu, 26 Jan 2012 22:50:41 +0000 (14:50 -0800)
committerBen Pfaff <blp@nicira.com>
Thu, 9 Feb 2012 22:07:08 +0000 (14:07 -0800)
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 <blp@nicira.com>
NEWS
ofproto/connmgr.c
ofproto/ofproto.h
vswitchd/bridge.c
vswitchd/vswitch.ovsschema
vswitchd/vswitch.xml

diff --git a/NEWS b/NEWS
index fde19f00d4d040d38caeaa683a0e97969c48d907..a9cb1af9e064cd977dab3b6646824a2d53343bac 100644 (file)
--- 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().
index a3ffb691a108de8a339e21e52c3a4f43cca8c20e..0cd7d53fa791c3410340490341609a9df5726cb2 100644 (file)
@@ -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
index 6aec062c8ecc4f4afa624b4b2356287768f79629..860c51420ed49808be857c6356c05a8652bde1be 100644 (file)
@@ -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. */
index 15fb632da077af0345a4d5fe4c55e898bdac5bdf..f6cf1196d76470b96c6c8d7f4f039c1f80d72d9f 100644 (file)
@@ -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
index c260c43d050e6df58dcba7a534321ff2a079bd8a..e4ae893c3bb732a8784e83b343bf176f4ee03a7f 100644 (file)
@@ -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": {
        "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},
index 9e38d7f2d33b99dd87feaf989c33298579fef191..a248d9fbfc90a96b26684a4f08c72b07e9b6c75a 100644 (file)
       </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