+static bool
+fail_open_hook(struct relay *r)
+{
+ struct buffer *msg = r->halves[HALF_LOCAL].rxbuf;
+ struct rconn *local = r->halves[HALF_LOCAL].rconn;
+ struct rconn *remote = r->halves[HALF_REMOTE].rconn;
+ int disconnected_duration;
+
+ if (fail_mode == FAIL_CLOSED) {
+ /* We fail closed, so there's never anything to do. */
+ return false;
+ }
+
+ disconnected_duration = rconn_disconnected_duration(remote);
+ if (disconnected_duration < fail_open_delay) {
+ /* It's not time to fail open yet. */
+ if (r->lswitch && rconn_is_connected(remote)) {
+ /* We're connected, so drop the learning switch. */
+ VLOG_WARN("No longer in fail-open mode");
+ lswitch_destroy(r->lswitch);
+ r->lswitch = NULL;
+ }
+ return false;
+ }
+
+ if (!r->lswitch) {
+ VLOG_WARN("Could not connect to controller for %d seconds, "
+ "failing open", disconnected_duration);
+ r->lswitch = lswitch_create(local, true, true);
+ }
+
+ /* Do switching. */
+ lswitch_process_packet(r->lswitch, local, msg);
+ rconn_run(local);
+ return true;
+}
+