From d0040604727e1582abbc28fa62903a822453c99f Mon Sep 17 00:00:00 2001 From: Ethan Jackson Date: Wed, 25 Jan 2012 11:44:30 -0800 Subject: [PATCH] mac-learning: Only revalidate relevant flows upon flush. Most callers of mac_learning_flush() need to revalidate all flows anyway, but this update forces new callers of mac_learning_flush() to think about whether or not they need to explicitly handle revalidation. Also, it's theoretically more efficient when there are lots of flows but the learning table is empty, (e.g. bridges that don't use the NORMAL action). Signed-off-by: Ethan Jackson --- lib/mac-learning.c | 12 ++++++++---- lib/mac-learning.h | 2 +- ofproto/ofproto-dpif.c | 15 ++++++--------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/lib/mac-learning.c b/lib/mac-learning.c index efd1dd4b..7872e2b9 100644 --- a/lib/mac-learning.c +++ b/lib/mac-learning.c @@ -260,14 +260,18 @@ mac_learning_expire(struct mac_learning *ml, struct mac_entry *e) free(e); } -/* Expires all the mac-learning entries in 'ml'. The tags in 'ml' are - * discarded, so the client is responsible for revalidating any flows that - * depend on 'ml', if necessary. */ +/* Expires all the mac-learning entries in 'ml'. If not NULL, the tags in 'ml' + * are added to 'tags'. Otherwise the tags in 'ml' are discarded. The client + * is responsible for revalidating any flows that depend on 'ml', if + * necessary. */ void -mac_learning_flush(struct mac_learning *ml) +mac_learning_flush(struct mac_learning *ml, struct tag_set *tags) { struct mac_entry *e; while (get_lru(ml, &e)){ + if (tags) { + tag_set_add(tags, e->tag); + } mac_learning_expire(ml, e); } hmap_shrink(&ml->table); diff --git a/lib/mac-learning.h b/lib/mac-learning.h index 0263e498..ab739545 100644 --- a/lib/mac-learning.h +++ b/lib/mac-learning.h @@ -109,6 +109,6 @@ struct mac_entry *mac_learning_lookup(const struct mac_learning *, /* Flushing. */ void mac_learning_expire(struct mac_learning *, struct mac_entry *); -void mac_learning_flush(struct mac_learning *); +void mac_learning_flush(struct mac_learning *, struct tag_set *); #endif /* mac-learning.h */ diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index ea5ed1ea..1e9b341c 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -1193,7 +1193,7 @@ update_stp_port_state(struct ofport_dpif *ofport) if (stp_learn_in_state(ofport->stp_state) != stp_learn_in_state(state)) { /* xxx Learning action flows should also be flushed. */ - mac_learning_flush(ofproto->ml); + mac_learning_flush(ofproto->ml, &ofproto->revalidate_set); } fwd_change = stp_forward_in_state(ofport->stp_state) != stp_forward_in_state(state); @@ -2064,7 +2064,7 @@ mirror_set(struct ofproto *ofproto_, void *aux, } ofproto->need_revalidate = true; - mac_learning_flush(ofproto->ml); + mac_learning_flush(ofproto->ml, &ofproto->revalidate_set); mirror_update_dups(ofproto); return 0; @@ -2083,7 +2083,7 @@ mirror_destroy(struct ofmirror *mirror) ofproto = mirror->ofproto; ofproto->need_revalidate = true; - mac_learning_flush(ofproto->ml); + mac_learning_flush(ofproto->ml, &ofproto->revalidate_set); mirror_bit = MIRROR_MASK_C(1) << mirror->idx; HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) { @@ -2126,8 +2126,7 @@ set_flood_vlans(struct ofproto *ofproto_, unsigned long *flood_vlans) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); if (mac_learning_set_flood_vlans(ofproto->ml, flood_vlans)) { - ofproto->need_revalidate = true; - mac_learning_flush(ofproto->ml); + mac_learning_flush(ofproto->ml, &ofproto->revalidate_set); } return 0; } @@ -5823,12 +5822,10 @@ ofproto_unixctl_fdb_flush(struct unixctl_conn *conn, int argc, unixctl_command_reply(conn, 501, "no such bridge"); return; } - mac_learning_flush(ofproto->ml); - ofproto->need_revalidate = true; + mac_learning_flush(ofproto->ml, &ofproto->revalidate_set); } else { HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) { - mac_learning_flush(ofproto->ml); - ofproto->need_revalidate = true; + mac_learning_flush(ofproto->ml, &ofproto->revalidate_set); } } -- 2.30.2