error = rconn_send(sw->rconn, msg, NULL);
}
}
+ if (protocol & usable_protocols) {
+ for (i = 0; !error && i < sw->n_default_flows; i++) {
+ msg = ofputil_encode_flow_mod(&sw->default_flows[i], protocol);
+ error = rconn_send(sw->rconn, msg, NULL);
+ }
- for (i = 0; !error && i < sw->n_default_flows; i++) {
- msg = ofputil_encode_flow_mod(&sw->default_flows[i], protocol);
- error = rconn_send(sw->rconn, msg, NULL);
- }
-
- if (error) {
- VLOG_INFO_RL(&rl, "%s: failed to queue default flows (%s)",
- rconn_get_name(sw->rconn), strerror(error));
+ if (error) {
+ VLOG_INFO_RL(&rl, "%s: failed to queue default flows (%s)",
+ rconn_get_name(sw->rconn), strerror(error));
+ }
+ } else {
+ VLOG_INFO_RL(&rl, "%s: failed to set usable protocol",
+ rconn_get_name(sw->rconn));
}
}
sw->protocol = protocol;
* connection if the switch processes the returned message correctly. (If
* '*next != want' then the caller will have to iterate.)
*
- * If 'current == want', returns NULL and stores 'current' in '*next'. */
+ * If 'current == want', or if it is not possible to transition from 'current'
+ * to 'want' (because, for example, 'current' and 'want' use different OpenFlow
+ * protocol versions), returns NULL and stores 'current' in '*next'. */
struct ofpbuf *
ofputil_encode_set_protocol(enum ofputil_protocol current,
enum ofputil_protocol want,
enum ofputil_protocol *next)
{
+ enum ofp_version cur_version, want_version;
enum ofputil_protocol cur_base, want_base;
bool cur_tid, want_tid;
+ cur_version = ofputil_protocol_to_ofp_version(current);
+ want_version = ofputil_protocol_to_ofp_version(want);
+ if (cur_version != want_version) {
+ *next = current;
+ return NULL;
+ }
+
cur_base = ofputil_protocol_to_base(current);
want_base = ofputil_protocol_to_base(want);
if (cur_base != want_base) {
request = ofputil_encode_set_protocol(*cur, want, &next);
if (!request) {
- return true;
+ return *cur == want;
}
run(vconn_transact_noreply(vconn, request, &reply),