Signed-off-by: Ethan Jackson <et...@nicira.com>
---
 lib/stp.c              |   12 +++++++++++-
 lib/stp.h              |    1 +
 ofproto/ofproto-dpif.c |   11 ++++++++++-
 tests/test-stp.c       |    8 +++++++-
 4 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/lib/stp.c b/lib/stp.c
index 3e9a5b6..1f1f71c 100644
--- a/lib/stp.c
+++ b/lib/stp.c
@@ -133,6 +133,7 @@ struct stp {
     /* Interface to client. */
     struct stp_port *first_changed_port;
     void (*send_bpdu)(struct ofpbuf *bpdu, int port_no, void *aux);
+    void (*topology_change_cb)(void *aux);
     void *aux;
 };
 
@@ -211,10 +212,14 @@ static void stp_send_bpdu(struct stp_port *, const void 
*, size_t);
  * arguments to 'send_bpdu' are an STP BPDU encapsulated in 'bpdu',
  * the spanning tree port number 'port_no' that should transmit the
  * packet, and auxiliary data to be passed to the callback in 'aux'.
- */
+ *
+ * When the bridge needs to flush it's MAC table, it calls 'topology_change'.
+ * The argument to 'topology_change' is the auxillary data 'aux' provided to
+ * stp_create(). */
 struct stp *
 stp_create(const char *name, stp_identifier bridge_id,
            void (*send_bpdu)(struct ofpbuf *bpdu, int port_no, void *aux),
+           void (*topology_change)(void *aux),
            void *aux)
 {
     struct stp *stp;
@@ -246,6 +251,7 @@ stp_create(const char *name, stp_identifier bridge_id,
     stp_start_timer(&stp->hello_timer, 0);
 
     stp->send_bpdu = send_bpdu;
+    stp->topology_change_cb = topology_change;
     stp->aux = aux;
 
     stp->first_changed_port = &stp->ports[ARRAY_SIZE(stp->ports)];
@@ -1047,6 +1053,7 @@ stp_topology_change_detection(struct stp *stp)
         stp_transmit_tcn(stp);
         stp_start_timer(&stp->tcn_timer, 0);
     }
+    stp->topology_change_cb(stp->aux);
     stp->topology_change_detected = true;
 }
 
@@ -1095,6 +1102,9 @@ stp_received_config_bpdu(struct stp *stp, struct stp_port 
*p,
                 if (config->flags & STP_CONFIG_TOPOLOGY_CHANGE_ACK) {
                     stp_topology_change_acknowledged(stp);
                 }
+                if (config->flags & STP_CONFIG_TOPOLOGY_CHANGE) {
+                    stp->topology_change_cb(stp->aux);
+                }
             }
         } else if (stp_is_designated_port(p)) {
             stp_transmit_config(p);
diff --git a/lib/stp.h b/lib/stp.h
index ec29d9a..e60be01 100644
--- a/lib/stp.h
+++ b/lib/stp.h
@@ -58,6 +58,7 @@ typedef uint64_t stp_identifier;
 struct stp *stp_create(const char *name, stp_identifier bridge_id,
                        void (*send_bpdu)(struct ofpbuf *bpdu, int port_no,
                                          void *aux),
+                       void (*topology_change)(void *aux),
                        void *aux);
 void stp_destroy(struct stp *);
 void stp_tick(struct stp *, int ms);
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index d46fcf3..7809489 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -1123,6 +1123,14 @@ send_bpdu_cb(struct ofpbuf *pkt, int port_num, void 
*ofproto_)
     ofpbuf_delete(pkt);
 }
 
+static void
+topology_change_cb(void *ofproto_)
+{
+    struct ofproto_dpif *ofproto = ofproto_;
+    mac_learning_flush(ofproto->ml);
+    ofproto->need_revalidate = true;
+}
+
 /* Configures STP on 'ofproto_' using the settings defined in 's'. */
 static int
 set_stp(struct ofproto *ofproto_, const struct ofproto_stp_settings *s)
@@ -1137,7 +1145,8 @@ set_stp(struct ofproto *ofproto_, const struct 
ofproto_stp_settings *s)
     if (s) {
         if (!ofproto->stp) {
             ofproto->stp = stp_create(ofproto_->name, s->system_id,
-                                      send_bpdu_cb, ofproto);
+                                      send_bpdu_cb, topology_change_cb,
+                                      ofproto);
             ofproto->stp_last_tick = time_msec();
         }
 
diff --git a/tests/test-stp.c b/tests/test-stp.c
index fecada7..a5a6203 100644
--- a/tests/test-stp.c
+++ b/tests/test-stp.c
@@ -110,6 +110,12 @@ send_bpdu(struct ofpbuf *pkt, int port_no, void *b_)
     ofpbuf_delete(pkt);
 }
 
+static void
+topology_change(void *b OVS_UNUSED)
+{
+    /* XXX: Someday we should test topology change notifications. */
+}
+
 static struct bridge *
 new_bridge(struct test_case *tc, int id)
 {
@@ -118,7 +124,7 @@ new_bridge(struct test_case *tc, int id)
     b->tc = tc;
     b->id = id;
     snprintf(name, sizeof name, "stp%x", id);
-    b->stp = stp_create(name, id, send_bpdu, b);
+    b->stp = stp_create(name, id, send_bpdu, topology_change, b);
     assert(tc->n_bridges < ARRAY_SIZE(tc->bridges));
     b->n_ports = 0;
     b->rxq_head = b->rxq_tail = 0;
-- 
1.7.7.1

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to