[ovs-dev] [PATCH] ofproto: fix interactions between flow monitors and barriers
YAMAMOTO Takashi
yamamoto at valinux.co.jp
Wed Jan 8 10:31:23 UTC 2014
Following OpenFlow 1.4 semantics, make barriers wait for
flow monitor replies. This should fix a race in
"ofproto - flow monitoring pause and resume" test.
Signed-off-by: YAMAMOTO Takashi <yamamoto at valinux.co.jp>
---
ofproto/connmgr.c | 27 +++++++++++++++++++++++++++
ofproto/connmgr.h | 1 +
ofproto/ofproto.c | 16 +++++++++++++++-
3 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
index ea79795..aa9b54c 100644
--- a/ofproto/connmgr.c
+++ b/ofproto/connmgr.c
@@ -1118,6 +1118,13 @@ ofconn_pktbuf_retrieve(struct ofconn *ofconn, uint32_t id,
return pktbuf_retrieve(ofconn->pktbuf, id, bufferp, in_port);
}
+/* Returns true if 'ofconn' has any pending flow monitor updates. */
+bool
+ofconn_has_pending_monitor(const struct ofconn *ofconn)
+{
+ return !list_is_empty(&ofconn->updates) || ofconn->monitor_paused;
+}
+
/* Returns true if 'ofconn' has any pending opgroups. */
bool
ofconn_has_pending_opgroups(const struct ofconn *ofconn)
@@ -2040,6 +2047,20 @@ ofmonitor_report(struct connmgr *mgr, struct rule *rule,
}
}
+static bool
+ofmonitor_has_pending(struct connmgr *mgr)
+ OVS_REQUIRES(ofproto_mutex)
+{
+ struct ofconn *ofconn;
+
+ LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {
+ if (ofconn_has_pending_monitor(ofconn)) {
+ return true;
+ }
+ }
+ return false;
+}
+
void
ofmonitor_flush(struct connmgr *mgr)
OVS_REQUIRES(ofproto_mutex)
@@ -2066,6 +2087,9 @@ ofmonitor_flush(struct connmgr *mgr)
}
}
}
+ if (!ofmonitor_has_pending(mgr)) {
+ connmgr_retry(mgr);
+ }
}
static void
@@ -2091,6 +2115,9 @@ ofmonitor_resume(struct ofconn *ofconn)
ofconn_send_replies(ofconn, &msgs);
ofconn->monitor_paused = 0;
+ if (!ofmonitor_has_pending(ofconn->connmgr)) {
+ connmgr_retry(ofconn->connmgr);
+ }
}
static bool
diff --git a/ofproto/connmgr.h b/ofproto/connmgr.h
index 170d872..40b3ff6 100644
--- a/ofproto/connmgr.h
+++ b/ofproto/connmgr.h
@@ -142,6 +142,7 @@ enum ofperr ofconn_pktbuf_retrieve(struct ofconn *, uint32_t id,
struct ofpbuf **bufferp, ofp_port_t *in_port);
bool ofconn_has_pending_opgroups(const struct ofconn *);
+bool ofconn_has_pending_monitor(const struct ofconn *);
void ofconn_add_opgroup(struct ofconn *, struct list *);
void ofconn_remove_opgroup(struct ofconn *, struct list *,
const struct ofp_header *request, int error);
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 676a6cb..1b59a28 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -4678,7 +4678,21 @@ handle_barrier_request(struct ofconn *ofconn, const struct ofp_header *oh)
{
struct ofpbuf *buf;
- if (ofconn_has_pending_opgroups(ofconn)) {
+ /*
+ * OpenFlow 1.4.0 p.110:
+ * A OFPMP_FLOW_MONITOR multipart reply can not cross a barrier
+ * handshake. The switch must always send the OFPMP_FLOW_MONITOR
+ * multipart reply for a given flow table change before the reply
+ * to a OFPT_BARRIER_REQUEST request that follows the request
+ * responsible for the flow table change.
+ *
+ * The spec seems unclear what to do for multiple connections, though.
+ * We serialize only flow monitor replies on our connection.
+ * We don't care which connection has made flow modifications triggering
+ * the flow monitor replies.
+ */
+ if (ofconn_has_pending_opgroups(ofconn) ||
+ ofconn_has_pending_monitor(ofconn)) {
return OFPROTO_POSTPONE;
}
--
1.8.3.1
More information about the dev
mailing list