vswitch: Add other-config:in-band-queue to set queue for in-band control.
authorBen Pfaff <blp@nicira.com>
Tue, 2 Nov 2010 17:45:33 +0000 (10:45 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 15 Nov 2010 17:36:15 +0000 (09:36 -0800)
Until now, in-band control traffic has always gone to the default queue,
typically queue 0.  It makes sense to be able to assing control traffic to
its own queue, so this commit enables that.

Bug #3653.

ofproto/in-band.c
ofproto/in-band.h
ofproto/ofproto.c
ofproto/ofproto.h
vswitchd/bridge.c
vswitchd/vswitch.xml

index 9605b50f38894326e9dbb081f6e4374fdd051773..aebdb7e4b226aaa47733edacb927d7245bd6c218 100644 (file)
@@ -235,6 +235,7 @@ struct in_band_remote {
 struct in_band {
     struct ofproto *ofproto;
     struct status_category *ss_cat;
+    int queue_id, prev_queue_id;
 
     /* Remote information. */
     time_t next_remote_refresh; /* Refresh timer. */
@@ -585,13 +586,31 @@ drop_rules(struct in_band *ib)
 static void
 add_rule(struct in_band *ib, const struct cls_rule *rule)
 {
-    union ofp_action action;
-
-    action.type = htons(OFPAT_OUTPUT);
-    action.output.len = htons(sizeof action);
-    action.output.port = htons(OFPP_NORMAL);
-    action.output.max_len = htons(0);
-    ofproto_add_flow(ib->ofproto, rule, &action, 1);
+    struct {
+        struct nx_action_set_queue nxsq;
+        struct ofp_action_output oao;
+    } actions;
+
+    memset(&actions, 0, sizeof actions);
+
+    actions.oao.type = htons(OFPAT_OUTPUT);
+    actions.oao.len = htons(sizeof actions.oao);
+    actions.oao.port = htons(OFPP_NORMAL);
+    actions.oao.max_len = htons(0);
+
+    if (ib->queue_id < 0) {
+        ofproto_add_flow(ib->ofproto, rule,
+                         (union ofp_action *) &actions.oao, 1);
+    } else {
+        actions.nxsq.type = htons(OFPAT_VENDOR);
+        actions.nxsq.len = htons(sizeof actions.nxsq);
+        actions.nxsq.vendor = htonl(NX_VENDOR_ID);
+        actions.nxsq.subtype = htons(NXAST_SET_QUEUE);
+        actions.nxsq.queue_id = htonl(ib->queue_id);
+
+        ofproto_add_flow(ib->ofproto, rule, (union ofp_action *) &actions,
+                         sizeof actions / sizeof(union ofp_action));
+    }
 }
 
 /* Inserts flows into the flow table for the current state of 'ib'. */
@@ -626,15 +645,17 @@ compare_macs(const void *a, const void *b)
 void
 in_band_run(struct in_band *ib)
 {
+    bool local_change, remote_change, queue_id_change;
     struct in_band_remote *r;
-    bool local_change, remote_change;
 
     local_change = refresh_local(ib);
     remote_change = refresh_remotes(ib);
-    if (!local_change && !remote_change) {
+    queue_id_change = ib->queue_id != ib->prev_queue_id;
+    if (!local_change && !remote_change && !queue_id_change) {
         /* Nothing changed, nothing to do. */
         return;
     }
+    ib->prev_queue_id = ib->queue_id;
 
     /* Drop old rules. */
     drop_rules(ib);
@@ -708,6 +729,7 @@ in_band_create(struct ofproto *ofproto, struct dpif *dpif,
     in_band->ofproto = ofproto;
     in_band->ss_cat = switch_status_register(ss, "in-band",
                                              in_band_status_cb, in_band);
+    in_band->queue_id = in_band->prev_queue_id = -1;
     in_band->next_remote_refresh = TIME_MIN;
     in_band->next_local_refresh = TIME_MIN;
     in_band->local_netdev = local_netdev;
@@ -778,3 +800,13 @@ in_band_set_remotes(struct in_band *ib,
     /* Force refresh in next call to in_band_run(). */
     ib->next_remote_refresh = TIME_MIN;
 }
+
+/* Sets the OpenFlow queue used by flows set up by 'ib' to 'queue_id'.  If
+ * 'queue_id' is negative, 'ib' will not set any queue (which is also the
+ * default). */
+void
+in_band_set_queue(struct in_band *ib, int queue_id)
+{
+    ib->queue_id = queue_id;
+}
+
index 27a5fe51d598db301e92658721db59c3526a4d11..23a30cedb5edb4c4440e118b3a6938309db24b78 100644 (file)
@@ -31,6 +31,7 @@ int in_band_create(struct ofproto *, struct dpif *, struct switch_status *,
                    struct in_band **);
 void in_band_destroy(struct in_band *);
 
+void in_band_set_queue(struct in_band *, int queue_id);
 void in_band_set_remotes(struct in_band *,
                          const struct sockaddr_in *, size_t n);
 
index 4e49cb63cb70299a263e546e5cbec2969f99e0bf..897429f84cf11a0667d1e230c72ee3b850c1585c 100644 (file)
@@ -305,6 +305,7 @@ struct ofproto {
     long long int next_in_band_update;
     struct sockaddr_in *extra_in_band_remotes;
     size_t n_extra_remotes;
+    int in_band_queue;
 
     /* Flow table. */
     struct classifier cls;
@@ -405,11 +406,14 @@ ofproto_create(const char *datapath, const char *datapath_type,
 
     /* Initialize submodules. */
     p->switch_status = switch_status_create(p);
-    p->in_band = NULL;
     p->fail_open = NULL;
     p->netflow = NULL;
     p->sflow = NULL;
 
+    /* Initialize in-band control. */
+    p->in_band = NULL;
+    p->in_band_queue = -1;
+
     /* Initialize flow table. */
     classifier_init(&p->cls);
     p->next_expiration = time_msec() + 1000;
@@ -600,6 +604,7 @@ update_in_band_remotes(struct ofproto *ofproto)
         if (ofproto->in_band) {
             in_band_set_remotes(ofproto->in_band, addrs, n_addrs);
         }
+        in_band_set_queue(ofproto->in_band, ofproto->in_band_queue);
         ofproto->next_in_band_update = time_msec() + 1000;
     } else {
         in_band_destroy(ofproto->in_band);
@@ -776,6 +781,18 @@ ofproto_set_extra_in_band_remotes(struct ofproto *ofproto,
     update_in_band_remotes(ofproto);
 }
 
+/* Sets the OpenFlow queue used by flows set up by in-band control on
+ * 'ofproto' to 'queue_id'.  If 'queue_id' is negative, then in-band control
+ * flows will use the default queue. */
+void
+ofproto_set_in_band_queue(struct ofproto *ofproto, int queue_id)
+{
+    if (queue_id != ofproto->in_band_queue) {
+        ofproto->in_band_queue = queue_id;
+        update_in_band_remotes(ofproto);
+    }
+}
+
 void
 ofproto_set_desc(struct ofproto *p,
                  const char *mfr_desc, const char *hw_desc,
index a3cc8255638c2a45693d2f2093c9b3d473595b6d..fd089c5ef9690586bf8025a1d116534ae57dc413 100644 (file)
@@ -106,6 +106,7 @@ void ofproto_set_fail_mode(struct ofproto *, enum ofproto_fail_mode fail_mode);
 void ofproto_reconnect_controllers(struct ofproto *);
 void ofproto_set_extra_in_band_remotes(struct ofproto *,
                                        const struct sockaddr_in *, size_t n);
+void ofproto_set_in_band_queue(struct ofproto *, int queue_id);
 void ofproto_set_desc(struct ofproto *,
                       const char *mfr_desc, const char *hw_desc,
                       const char *sw_desc, const char *serial_desc,
index 9ddafe1ef634b6938ea294824d4ac04be42445c5..ff9ddfdf5dbf5b7c9e39cce97fdb7078bb7359aa 100644 (file)
@@ -1724,23 +1724,29 @@ bridge_reconfigure_remotes(struct bridge *br,
                            const struct sockaddr_in *managers,
                            size_t n_managers)
 {
+    const char *disable_ib_str, *queue_id_str;
+    bool disable_in_band = false;
+    int queue_id;
+
     struct ovsrec_controller **controllers;
     size_t n_controllers;
     bool had_primary;
-    const char *disable_ib_str;
-    bool disable_in_band = false;
 
     struct ofproto_controller *ocs;
     size_t n_ocs;
     size_t i;
 
-
     /* Check if we should disable in-band control on this bridge. */
     disable_ib_str = bridge_get_other_config(br->cfg, "disable-in-band");
     if (disable_ib_str && !strcmp(disable_ib_str, "true")) {
         disable_in_band = true;
     }
 
+    /* Set OpenFlow queue ID for in-band control. */
+    queue_id_str = bridge_get_other_config(br->cfg, "in-band-queue");
+    queue_id = queue_id_str ? strtol(queue_id_str, NULL, 10) : -1;
+    ofproto_set_in_band_queue(br->ofproto, queue_id);
+
     if (disable_in_band) {
         ofproto_set_extra_in_band_remotes(br->ofproto, NULL, 0);
     } else {
index 2edb35e0d45df0034ef05596af2f86199910cacd..7cfba180cb899151599b59b67094ca1cd5a9a5b1 100644 (file)
             <var>xx</var>:<var>xx</var>:<var>xx</var>:<var>xx</var>:<var>xx</var>:<var>xx</var>
             to set the hardware address of the local port and influence the
             datapath ID.</dd>
+          <dt><code>in-band-queue</code></dt>
+          <dd>
+            A queue ID as a nonnegative integer.  This sets the OpenFlow queue
+            ID that will be used by flows set up by in-band control on this
+            bridge.  If unset, or if the port used by an in-band control flow
+            does not have QoS configured, or if the port does not have a queue
+            with the specified ID, the default queue is used instead.
+          </dd>
         </dl>
       </column>
     </group>