+static void fail_open_recover(struct fail_open *);
+
+/* Returns the number of seconds of disconnection after which fail-open mode
+ * should activate. */
+static int
+trigger_duration(const struct fail_open *fo)
+{
+ if (!connmgr_has_controllers(fo->connmgr)) {
+ /* Shouldn't ever arrive here, but if we do, never fail open. */
+ return INT_MAX;
+ } else {
+ /* Otherwise, every controller must have a chance to send an
+ * inactivity probe and reconnect before we fail open, so take the
+ * maximum probe interval and multiply by 3:
+ *
+ * - The first interval is the idle time before sending an inactivity
+ * probe.
+ *
+ * - The second interval is the time allowed for a response to the
+ * inactivity probe.
+ *
+ * - The third interval is the time allowed to reconnect after no
+ * response is received.
+ */
+ return connmgr_get_max_probe_interval(fo->connmgr) * 3;
+ }
+}
+
+/* Returns true if 'fo' is currently in fail-open mode, otherwise false. */
+bool
+fail_open_is_active(const struct fail_open *fo)
+{
+ return fo->last_disconn_secs != 0;
+}
+
+static void
+send_bogus_packet_ins(struct fail_open *fo)
+{
+ struct ofproto_packet_in pin;
+ uint8_t mac[ETH_ADDR_LEN];
+ struct ofpbuf b;
+
+ ofpbuf_init(&b, 128);
+ eth_addr_nicira_random(mac);
+ compose_rarp(&b, mac);
+
+ memset(&pin, 0, sizeof pin);
+ pin.up.packet = ofpbuf_data(&b);
+ pin.up.packet_len = ofpbuf_size(&b);
+ pin.up.reason = OFPR_NO_MATCH;
+ pin.up.fmd.in_port = OFPP_LOCAL;
+ pin.send_len = ofpbuf_size(&b);
+ pin.miss_type = OFPROTO_PACKET_IN_NO_MISS;
+ connmgr_send_packet_in(fo->connmgr, &pin);
+
+ ofpbuf_uninit(&b);
+}
+
+/* Enter fail-open mode if we should be in it. */