mac-learning: Only revalidate relevant flows upon flush.
authorEthan Jackson <ethan@nicira.com>
Wed, 25 Jan 2012 19:44:30 +0000 (11:44 -0800)
committerEthan Jackson <ethan@nicira.com>
Wed, 25 Jan 2012 21:11:07 +0000 (13:11 -0800)
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 <ethan@nicira.com>
lib/mac-learning.c
lib/mac-learning.h
ofproto/ofproto-dpif.c

index efd1dd4b8b052dfdfee62598eae7c3baa854eeff..7872e2b97e6cfa3a205b2ff92c13d57ff5a62bb4 100644 (file)
@@ -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);
index 0263e4987deba8b7c08fc0f9a6a094bbba4756d2..ab739545c975260715c9624dfd0b9ec4a506ed0b 100644 (file)
@@ -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 */
index ea5ed1ea4672df1c97e76eda29cc6645658e0c04..1e9b341c0b2a4746d247c4929985f30690c75818 100644 (file)
@@ -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);
         }
     }