From b1da6250481f6879d0727710eea87d5f61d6a24c Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 2 Nov 2010 10:45:33 -0700 Subject: [PATCH] vswitch: Add other-config:in-band-queue to set queue for in-band control. 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 | 50 ++++++++++++++++++++++++++++++++++++-------- ofproto/in-band.h | 1 + ofproto/ofproto.c | 19 ++++++++++++++++- ofproto/ofproto.h | 1 + vswitchd/bridge.c | 12 ++++++++--- vswitchd/vswitch.xml | 8 +++++++ 6 files changed, 78 insertions(+), 13 deletions(-) diff --git a/ofproto/in-band.c b/ofproto/in-band.c index 9605b50f..aebdb7e4 100644 --- a/ofproto/in-band.c +++ b/ofproto/in-band.c @@ -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; +} + diff --git a/ofproto/in-band.h b/ofproto/in-band.h index 27a5fe51..23a30ced 100644 --- a/ofproto/in-band.h +++ b/ofproto/in-band.h @@ -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); diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 4e49cb63..897429f8 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -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, diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index a3cc8255..fd089c5e 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -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, diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 9ddafe1e..ff9ddfdf 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -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 { diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index 2edb35e0..7cfba180 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -369,6 +369,14 @@ xx:xx:xx:xx:xx:xx to set the hardware address of the local port and influence the datapath ID. +
in-band-queue
+
+ 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. +
-- 2.30.2