With this commit, RSTP is able to flush from the MAC learning table
entries pertaining to a single port. Before this commit the whole table
was flushed every time a port requested flushing actions.
Signed-off-by: Daniele Venturino <[email protected]>
---
lib/rstp.c | 52 +++++++++++++++++++++++++++++++++-----------------
lib/rstp.h | 2 +-
ofproto/ofproto-dpif.c | 18 ++++++++---------
3 files changed, 44 insertions(+), 28 deletions(-)
diff --git a/lib/rstp.c b/lib/rstp.c
index 55c43c0..1ab4938 100644
--- a/lib/rstp.c
+++ b/lib/rstp.c
@@ -775,31 +775,49 @@ rstp_get_root_path_cost(const struct rstp *rstp)
return cost;
}
-/* Returns true if something has happened to 'rstp' which necessitates
- * flushing the client's MAC learning table.
+/* Finds a port which needs to flush its own MAC learning table. A NULL pointer
+ * is returned if no port needs to flush its MAC learning table.
*/
-bool
-rstp_check_and_reset_fdb_flush(struct rstp *rstp)
+void *
+rstp_check_and_reset_fdb_flush(struct rstp *rstp, struct rstp_port **port)
OVS_EXCLUDED(rstp_mutex)
{
- bool needs_flush;
- struct rstp_port *p;
-
- needs_flush = false;
+ void *aux = NULL;
ovs_mutex_lock(&rstp_mutex);
- HMAP_FOR_EACH (p, node, &rstp->ports) {
- if (p->fdb_flush) {
- needs_flush = true;
- /* fdb_flush should be reset by the filtering database
- * once the entries are removed if rstp_version is TRUE, and
- * immediately if stp_version is TRUE.*/
- p->fdb_flush = false;
+ if (*port == NULL) {
+ struct rstp_port *p;
+
+ HMAP_FOR_EACH (p, node, &rstp->ports) {
+ if (p->fdb_flush) {
+ aux = p->aux;
+ *port = p;
+ goto out;
+ }
}
+ } else { /* continue */
+ struct rstp_port *p = *port;
+
+ HMAP_FOR_EACH_CONTINUE (p, node, &rstp->ports) {
+ if (p->fdb_flush) {
+ aux = p->aux;
+ *port = p;
+ goto out;
+ }
+ }
+ }
+ /* No port needs flushing. */
+ *port = NULL;
+out:
+ /* fdb_flush should be reset by the filtering database
+ * once the entries are removed if rstp_version is TRUE, and
+ * immediately if stp_version is TRUE.*/
+ if (*port != NULL) {
+ (*port)->fdb_flush = false;
}
ovs_mutex_unlock(&rstp_mutex);
- return needs_flush;
-}
+ return aux;
+ }
/* Finds a port whose state has changed, and returns the aux pointer set for
* the port. A NULL pointer is returned when no changed port is found. On
diff --git a/lib/rstp.h b/lib/rstp.h
index b429e35..b05cdf2 100644
--- a/lib/rstp.h
+++ b/lib/rstp.h
@@ -157,7 +157,7 @@ void rstp_tick_timers(struct rstp *)
void rstp_port_received_bpdu(struct rstp_port *, const void *bpdu,
size_t bpdu_size)
OVS_EXCLUDED(rstp_mutex);
-bool rstp_check_and_reset_fdb_flush(struct rstp *)
+void *rstp_check_and_reset_fdb_flush(struct rstp *, struct rstp_port **)
OVS_EXCLUDED(rstp_mutex);
void *rstp_get_next_changed_port_aux(struct rstp *, struct rstp_port **)
OVS_EXCLUDED(rstp_mutex);
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index dc0ecdf..2fd9896 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -140,6 +140,7 @@ static void bundle_destroy(struct ofbundle *);
static void bundle_del_port(struct ofport_dpif *);
static void bundle_run(struct ofbundle *);
static void bundle_wait(struct ofbundle *);
+static void bundle_flush_macs(struct ofbundle *, bool);
static void stp_run(struct ofproto_dpif *ofproto);
static void stp_wait(struct ofproto_dpif *ofproto);
@@ -2098,9 +2099,9 @@ update_rstp_port_state(struct ofport_dpif *ofport)
if (rstp_learn_in_state(ofport->rstp_state)
!= rstp_learn_in_state(state)) {
/* xxx Learning action flows should also be flushed. */
- ovs_rwlock_wrlock(&ofproto->ml->rwlock);
- mac_learning_flush(ofproto->ml);
- ovs_rwlock_unlock(&ofproto->ml->rwlock);
+ if (ofport->bundle) {
+ bundle_flush_macs(ofport->bundle, false);
+ }
}
fwd_change = rstp_forward_in_state(ofport->rstp_state)
!= rstp_forward_in_state(state);
@@ -2140,16 +2141,13 @@ rstp_run(struct ofproto_dpif *ofproto)
while ((ofport = rstp_get_next_changed_port_aux(ofproto->rstp, &rp))) {
update_rstp_port_state(ofport);
}
+ rp = NULL;
+ ofport = NULL;
/* FIXME: This check should be done on-event (i.e., when setting
* p->fdb_flush) and not periodically.
*/
- if (rstp_check_and_reset_fdb_flush(ofproto->rstp)) {
- ovs_rwlock_wrlock(&ofproto->ml->rwlock);
- /* FIXME: RSTP should be able to flush the entries pertaining to a
- * single port, not the whole table.
- */
- mac_learning_flush(ofproto->ml);
- ovs_rwlock_unlock(&ofproto->ml->rwlock);
+ while ((ofport = rstp_check_and_reset_fdb_flush(ofproto->rstp, &rp))) {
+ bundle_flush_macs(ofport->bundle, false);
}
}
}
--
1.8.1.2
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev