+/* Takes care of necessary 'sw' activity, except for receiving packets (which
+ * the caller must do). */
+void
+lswitch_run(struct lswitch *sw, struct rconn *rconn)
+{
+ long long int now = time_msec();
+
+ /* If we're waiting for more replies, keeping waiting for up to 10 s. */
+ if (sw->last_reply != LLONG_MIN) {
+ if (now - sw->last_reply > 10000) {
+ VLOG_ERR_RL(&rl, "%012llx: No more flow stat replies last 10 s",
+ sw->datapath_id);
+ sw->last_reply = LLONG_MIN;
+ sw->last_query = LLONG_MIN;
+ schedule_query(sw, 0);
+ } else {
+ return;
+ }
+ }
+
+ /* If we're waiting for any reply at all, keep waiting for up to 10 s. */
+ if (sw->last_query != LLONG_MIN) {
+ if (now - sw->last_query > 10000) {
+ VLOG_ERR_RL(&rl, "%012llx: No flow stat replies in last 10 s",
+ sw->datapath_id);
+ sw->last_query = LLONG_MIN;
+ schedule_query(sw, 0);
+ } else {
+ return;
+ }
+ }
+
+ /* If it's time to send another query, do so. */
+ if (sw->next_query != LLONG_MIN && now >= sw->next_query) {
+ sw->next_query = LLONG_MIN;
+ if (!rconn_is_connected(rconn)) {
+ schedule_query(sw, 1000);
+ } else {
+ struct ofp_stats_request *osr;
+ struct ofp_flow_stats_request *ofsr;
+ struct ofpbuf *b;
+ int error;
+
+ VLOG_DBG("%012llx: Sending flow stats request to implement STP",
+ sw->datapath_id);
+
+ sw->last_query = now;
+ sw->query_xid = random_uint32();
+ sw->n_flows = 0;
+ sw->n_no_recv = 0;
+ sw->n_no_send = 0;
+ osr = make_openflow_xid(sizeof *osr + sizeof *ofsr,
+ OFPT_STATS_REQUEST, sw->query_xid, &b);
+ osr->type = htons(OFPST_FLOW);
+ osr->flags = htons(0);
+ ofsr = (struct ofp_flow_stats_request *) osr->body;
+ ofsr->match.wildcards = htonl(OFPFW_ALL);
+ ofsr->table_id = 0xff;
+
+ error = rconn_send(rconn, b, NULL);
+ if (error) {
+ VLOG_WARN_RL(&rl, "%012llx: sending flow stats request "
+ "failed: %s", sw->datapath_id, strerror(error));
+ ofpbuf_delete(b);
+ schedule_query(sw, 1000);
+ }
+ }
+ }
+}
+
+static void
+wait_timeout(long long int started)
+{
+ long long int now = time_msec();
+ long long int timeout = 10000 - (now - started);
+ if (timeout <= 0) {
+ poll_immediate_wake();
+ } else {
+ poll_timer_wait(timeout);
+ }
+}
+
+void
+lswitch_wait(struct lswitch *sw)