reconfigure(ofproto, s.br_name);
}
- /* Do work. */
- ofproto_run(ofproto);
+ error = ofproto_run(ofproto);
+ if (error) {
+ ofp_fatal(error, "unrecoverable datapath error");
+ }
- /* Wait for something to happen. */
ofproto_wait(ofproto);
signal_wait(sighup);
poll_block();
free(p);
}
-void
+int
ofproto_run(struct ofproto *p)
{
struct ofconn *ofconn, *next_ofconn;
error = dpif_recv(&p->dpif, &buf);
if (error) {
+ if (error == ENODEV) {
+ /* Someone destroyed the datapath behind our back. The caller
+ * better destroy us and give up, because we're just going to
+ * spin from here on out. */
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+ VLOG_ERR_RL(&rl, "dp%u: datapath was destroyed externally",
+ p->dpif.minor);
+ return ENODEV;
+ }
break;
}
classifier_for_each(&p->cls, CLS_INC_EXACT, revalidate_subrule_cb, p);
p->need_revalidate = false;
}
+
+ return 0;
}
void
int ofproto_create(const char *datapath, struct ofproto **ofprotop);
void ofproto_destroy(struct ofproto *);
-void ofproto_run(struct ofproto *);
+int ofproto_run(struct ofproto *);
void ofproto_wait(struct ofproto *);
bool ofproto_is_alive(const struct ofproto *);
static void bridge_destroy(struct bridge *);
static struct bridge *bridge_lookup(const char *name);
static int if_up(const char *netdev_name);
-static void bridge_run_one(struct bridge *);
+static int bridge_run_one(struct bridge *);
static void bridge_reconfigure_one(struct bridge *);
static void bridge_get_all_ifaces(const struct bridge *, struct svec *ifaces);
static bool bridge_is_backlogged(const struct bridge *);
bridge_set_local_hw_addr(br, local_iface, ea);
}
-void
+int
bridge_run(void)
{
struct bridge *br, *next;
+ int retval;
+ retval = 0;
LIST_FOR_EACH_SAFE (br, next, struct bridge, node, &all_bridges) {
- bridge_run_one(br);
+ int error = bridge_run_one(br);
+ if (error) {
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+ VLOG_ERR_RL(&rl, "bridge %s: datapath was destroyed externally, "
+ "forcing reconfiguration", br->name);
+ if (!retval) {
+ retval = error;
+ }
+ }
}
+ return retval;
}
void
}
}
-static void
+static int
bridge_run_one(struct bridge *br)
{
int iteration;
+ int error;
if (br->controller) {
- ofproto_run(br->ofproto);
- return;
+ return ofproto_run(br->ofproto);
}
rconn_run(br->rconn);
/* Start or restart switch if necessary. */
connect_ofproto(br);
- ofproto_run(br->ofproto);
+ error = ofproto_run(br->ofproto);
/* Now revalidate any flows that need it. */
if (br->flush || !tag_set_is_empty(&br->revalidate_set)) {
}
tag_set_init(&br->revalidate_set);
br->flush = false;
+
+ return error;
}
static void
void bridge_init(void);
void bridge_reconfigure(void);
-void bridge_run(void);
+int bridge_run(void);
void bridge_wait(void);
bool bridge_exists(const char *);
main(int argc, char *argv[])
{
struct signal *sighup;
+ bool need_reconfigure;
int retval;
set_program_name(argv[0]);
cfg_read();
bridge_init();
+ need_reconfigure = false;
for (;;) {
- if (signal_poll(sighup)) {
+ if (need_reconfigure || signal_poll(sighup)) {
+ need_reconfigure = false;
vlog_reopen_log_file();
reconfigure();
}
- bridge_run();
+ if (bridge_run()) {
+ need_reconfigure = true;
+ }
if (brc_enabled) {
brc_run();