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 fde19f0..a9cb1af 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 a3ffb69..0cd7d53 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 6aec062..860c514 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 15fb632..f6cf119 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 c260c43..e4ae893 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 9e38d7f..a248d9f 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