summaryrefslogtreecommitdiff
path: root/ovn/controller/ofctrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'ovn/controller/ofctrl.c')
-rw-r--r--ovn/controller/ofctrl.c56
1 files changed, 32 insertions, 24 deletions
diff --git a/ovn/controller/ofctrl.c b/ovn/controller/ofctrl.c
index 184e86fba..f0451b7c1 100644
--- a/ovn/controller/ofctrl.c
+++ b/ovn/controller/ofctrl.c
@@ -35,6 +35,7 @@
#include "openvswitch/vlog.h"
#include "ovn-controller.h"
#include "ovn/lib/actions.h"
+#include "poll-loop.h"
#include "physical.h"
#include "rconn.h"
#include "socket-util.h"
@@ -409,9 +410,10 @@ ofctrl_run(const struct ovsrec_bridge *br_int)
state = S_NEW;
}
- enum ofctrl_state old_state;
- do {
- old_state = state;
+ bool progress = true;
+ for (int i = 0; progress && i < 50; i++) {
+ /* Allow the state machine to run. */
+ enum ofctrl_state old_state = state;
switch (state) {
#define STATE(NAME) case NAME: run_##NAME(); break;
STATES
@@ -419,35 +421,41 @@ ofctrl_run(const struct ovsrec_bridge *br_int)
default:
OVS_NOT_REACHED();
}
- } while (state != old_state);
- for (int i = 0; state == old_state && i < 50; i++) {
+ /* Try to process a received packet. */
struct ofpbuf *msg = rconn_recv(swconn);
- if (!msg) {
- break;
- }
-
- const struct ofp_header *oh = msg->data;
- enum ofptype type;
- enum ofperr error;
+ if (msg) {
+ const struct ofp_header *oh = msg->data;
+ enum ofptype type;
+ enum ofperr error;
- error = ofptype_decode(&type, oh);
- if (!error) {
- switch (state) {
+ error = ofptype_decode(&type, oh);
+ if (!error) {
+ switch (state) {
#define STATE(NAME) case NAME: recv_##NAME(oh, type); break;
- STATES
+ STATES
#undef STATE
- default:
- OVS_NOT_REACHED();
+ default:
+ OVS_NOT_REACHED();
+ }
+ } else {
+ char *s = ofp_to_string(oh, ntohs(oh->length), 1);
+ VLOG_WARN("could not decode OpenFlow message (%s): %s",
+ ofperr_to_string(error), s);
+ free(s);
}
- } else {
- char *s = ofp_to_string(oh, ntohs(oh->length), 1);
- VLOG_WARN("could not decode OpenFlow message (%s): %s",
- ofperr_to_string(error), s);
- free(s);
+
+ ofpbuf_delete(msg);
}
- ofpbuf_delete(msg);
+ /* If we did some work, plan to go around again. */
+ progress = old_state != state || msg;
+ }
+ if (progress) {
+ /* We bailed out to limit the amount of work we do in one go, to allow
+ * other code a chance to run. We were still making progress at that
+ * point, so ensure that we come back again without waiting. */
+ poll_immediate_wake();
}
return (state == S_CLEAR_FLOWS || state == S_UPDATE_FLOWS