+ return sw;
+}
+
+static void
+lswitch_handshake(struct lswitch *sw)
+{
+ enum ofputil_protocol protocol;
+ enum ofp_version version;
+
+ send_features_request(sw);
+
+ version = rconn_get_version(sw->rconn);
+ protocol = ofputil_protocol_from_ofp_version(version);
+ if (version >= OFP13_VERSION) {
+ /* OpenFlow 1.3 and later by default drop packets that miss in the flow
+ * table. Set up a flow to send packets to the controller by
+ * default. */
+ struct ofpact_output output;
+ struct ofpbuf *msg;
+ int error;
+
+ ofpact_init_OUTPUT(&output);
+ output.port = OFPP_CONTROLLER;
+ output.max_len = OFP_DEFAULT_MISS_SEND_LEN;
+
+ struct ofputil_flow_mod fm = {
+ .match = MATCH_CATCHALL_INITIALIZER,
+ .priority = 0,
+ .table_id = 0,
+ .command = OFPFC_ADD,
+ .buffer_id = UINT32_MAX,
+ .out_port = OFPP_NONE,
+ .out_group = OFPG_ANY,
+ .ofpacts = &output.ofpact,
+ .ofpacts_len = sizeof output,
+ };
+
+ msg = ofputil_encode_flow_mod(&fm, protocol);
+ error = rconn_send(sw->rconn, msg, NULL);
+ if (error) {
+ VLOG_INFO_RL(&rl, "%s: failed to add default flow (%s)",
+ rconn_get_name(sw->rconn), ovs_strerror(error));
+ }
+ }
+ if (sw->default_flows) {
+ struct ofpbuf *msg = NULL;
+ int error = 0;
+ size_t i;
+
+ /* If the initial protocol isn't good enough for default_flows, then
+ * pick one that will work and encode messages to set up that
+ * protocol.
+ *
+ * This could be improved by actually negotiating a mutually acceptable
+ * flow format with the switch, but that would require an asynchronous
+ * state machine. This version ought to work fine in practice. */
+ if (!(protocol & sw->usable_protocols)) {
+ enum ofputil_protocol want = rightmost_1bit(sw->usable_protocols);
+ while (!error) {
+ msg = ofputil_encode_set_protocol(protocol, want, &protocol);
+ if (!msg) {
+ break;
+ }
+ error = rconn_send(sw->rconn, msg, NULL);
+ }
+ }
+ if (protocol & sw->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);
+ }