From 6d95c4e857f768c9a06a42281c887417b211de90 Mon Sep 17 00:00:00 2001 From: Flavio Leitner Date: Wed, 18 Jun 2014 22:14:31 -0300 Subject: [PATCH] ofproto-dpif: Introduce multicast snooping handler It follows mac learning, but since the multicast snooping feature can be disabled, the locking is handled in the library. Signed-off-by: Flavio Leitner Signed-off-by: Ben Pfaff --- ofproto/ofproto-dpif-xlate.c | 21 ++++++++++++++++----- ofproto/ofproto-dpif-xlate.h | 2 ++ ofproto/ofproto-dpif.c | 17 ++++++++++++++++- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index d65bac888..075fc62e3 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -33,6 +33,7 @@ #include "learn.h" #include "list.h" #include "mac-learning.h" +#include "mcast-snooping.h" #include "meta-flow.h" #include "multipath.h" #include "netdev-vport.h" @@ -76,6 +77,7 @@ struct xbridge { char *name; /* Name used in log messages. */ struct dpif *dpif; /* Datapath interface. */ struct mac_learning *ml; /* Mac learning handle. */ + struct mcast_snooping *ms; /* Multicast Snooping handle. */ struct mbridge *mbridge; /* Mirroring. */ struct dpif_sflow *sflow; /* SFlow handle, or null. */ struct dpif_ipfix *ipfix; /* Ipfix handle, or null. */ @@ -347,6 +349,7 @@ static void xlate_xbridge_set(struct xbridge *xbridge, struct rule_dpif *miss_rule, struct rule_dpif *no_packet_in_rule, const struct mac_learning *ml, struct stp *stp, + const struct mcast_snooping *ms, const struct mbridge *mbridge, const struct dpif_sflow *sflow, const struct dpif_ipfix *ipfix, @@ -411,6 +414,7 @@ xlate_xbridge_set(struct xbridge *xbridge, struct rule_dpif *miss_rule, struct rule_dpif *no_packet_in_rule, const struct mac_learning *ml, struct stp *stp, + const struct mcast_snooping *ms, const struct mbridge *mbridge, const struct dpif_sflow *sflow, const struct dpif_ipfix *ipfix, @@ -425,6 +429,11 @@ xlate_xbridge_set(struct xbridge *xbridge, xbridge->ml = mac_learning_ref(ml); } + if (xbridge->ms != ms) { + mcast_snooping_unref(xbridge->ms); + xbridge->ms = mcast_snooping_ref(ms); + } + if (xbridge->mbridge != mbridge) { mbridge_unref(xbridge->mbridge); xbridge->mbridge = mbridge_ref(mbridge); @@ -530,10 +539,10 @@ xlate_xbridge_copy(struct xbridge *xbridge) xlate_xbridge_set(new_xbridge, xbridge->dpif, xbridge->miss_rule, xbridge->no_packet_in_rule, xbridge->ml, xbridge->stp, - xbridge->mbridge, xbridge->sflow, xbridge->ipfix, - xbridge->netflow, xbridge->frag, xbridge->forward_bpdu, - xbridge->has_in_band, xbridge->enable_recirc, - xbridge->variable_length_userdata, + xbridge->ms, xbridge->mbridge, xbridge->sflow, + xbridge->ipfix, xbridge->netflow, xbridge->frag, + xbridge->forward_bpdu, xbridge->has_in_band, + xbridge->enable_recirc, xbridge->variable_length_userdata, xbridge->max_mpls_depth); LIST_FOR_EACH (xbundle, list_node, &xbridge->xbundles) { xlate_xbundle_copy(new_xbridge, xbundle); @@ -680,6 +689,7 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name, struct dpif *dpif, struct rule_dpif *miss_rule, struct rule_dpif *no_packet_in_rule, const struct mac_learning *ml, struct stp *stp, + const struct mcast_snooping *ms, const struct mbridge *mbridge, const struct dpif_sflow *sflow, const struct dpif_ipfix *ipfix, @@ -705,7 +715,7 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name, xbridge->name = xstrdup(name); xlate_xbridge_set(xbridge, dpif, miss_rule, no_packet_in_rule, ml, stp, - mbridge, sflow, ipfix, netflow, frag, forward_bpdu, + ms, mbridge, sflow, ipfix, netflow, frag, forward_bpdu, has_in_band, enable_recirc, variable_length_userdata, max_mpls_depth); } @@ -730,6 +740,7 @@ xlate_xbridge_remove(struct xlate_cfg *xcfg, struct xbridge *xbridge) hmap_remove(&xcfg->xbridges, &xbridge->hmap_node); mac_learning_unref(xbridge->ml); + mcast_snooping_unref(xbridge->ms); mbridge_unref(xbridge->mbridge); dpif_sflow_unref(xbridge->sflow); dpif_ipfix_unref(xbridge->ipfix); diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h index 6065db378..4bdf2d3e8 100644 --- a/ofproto/ofproto-dpif-xlate.h +++ b/ofproto/ofproto-dpif-xlate.h @@ -31,6 +31,7 @@ struct lacp; struct dpif_ipfix; struct dpif_sflow; struct mac_learning; +struct mcast_snooping; struct xlate_cache; struct xlate_recirc { @@ -140,6 +141,7 @@ void xlate_ofproto_set(struct ofproto_dpif *, const char *name, struct dpif *, struct rule_dpif *miss_rule, struct rule_dpif *no_packet_in_rule, const struct mac_learning *, struct stp *, + const struct mcast_snooping *, const struct mbridge *, const struct dpif_sflow *, const struct dpif_ipfix *, const struct netflow *, enum ofp_config_flags, bool forward_bpdu, diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 9e4a45588..27233cb6b 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -37,6 +37,7 @@ #include "lacp.h" #include "learn.h" #include "mac-learning.h" +#include "mcast-snooping.h" #include "meta-flow.h" #include "multipath.h" #include "netdev-vport.h" @@ -227,6 +228,7 @@ enum revalidate_reason { REV_PORT_TOGGLED, /* Port enabled or disabled by CFM, LACP, ...*/ REV_FLOW_TABLE, /* Flow table changed. */ REV_MAC_LEARNING, /* Mac learning changed. */ + REV_MCAST_SNOOPING, /* Multicast snooping changed. */ }; COVERAGE_DEFINE(rev_reconfigure); COVERAGE_DEFINE(rev_stp); @@ -234,6 +236,7 @@ COVERAGE_DEFINE(rev_bond); COVERAGE_DEFINE(rev_port_toggled); COVERAGE_DEFINE(rev_flow_table); COVERAGE_DEFINE(rev_mac_learning); +COVERAGE_DEFINE(rev_mcast_snooping); /* All datapaths of a given type share a single dpif backer instance. */ struct dpif_backer { @@ -286,6 +289,7 @@ struct ofproto_dpif { struct dpif_ipfix *ipfix; struct hmap bundles; /* Contains "struct ofbundle"s. */ struct mac_learning *ml; + struct mcast_snooping *ms; bool has_bonded_bundles; bool lacp_enabled; struct mbridge *mbridge; @@ -574,6 +578,7 @@ type_run(const char *type) case REV_PORT_TOGGLED: COVERAGE_INC(rev_port_toggled); break; case REV_FLOW_TABLE: COVERAGE_INC(rev_flow_table); break; case REV_MAC_LEARNING: COVERAGE_INC(rev_mac_learning); break; + case REV_MCAST_SNOOPING: COVERAGE_INC(rev_mcast_snooping); break; } backer->need_revalidate = 0; @@ -589,7 +594,7 @@ type_run(const char *type) xlate_ofproto_set(ofproto, ofproto->up.name, ofproto->backer->dpif, ofproto->miss_rule, ofproto->no_packet_in_rule, ofproto->ml, - ofproto->stp, ofproto->mbridge, + ofproto->stp, ofproto->ms, ofproto->mbridge, ofproto->sflow, ofproto->ipfix, ofproto->netflow, ofproto->up.frag_handling, ofproto->up.forward_bpdu, @@ -1130,6 +1135,7 @@ construct(struct ofproto *ofproto_) ofproto->dump_seq = 0; hmap_init(&ofproto->bundles); ofproto->ml = mac_learning_create(MAC_ENTRY_DEFAULT_IDLE_TIME); + ofproto->ms = NULL; ofproto->mbridge = mbridge_create(); ofproto->has_bonded_bundles = false; ofproto->lacp_enabled = false; @@ -1314,6 +1320,7 @@ destruct(struct ofproto *ofproto_) dpif_sflow_unref(ofproto->sflow); hmap_destroy(&ofproto->bundles); mac_learning_unref(ofproto->ml); + mcast_snooping_unref(ofproto->ms); hmap_destroy(&ofproto->vlandev_map); hmap_destroy(&ofproto->realdev_vid_map); @@ -1341,6 +1348,7 @@ run(struct ofproto *ofproto_) ovs_rwlock_wrlock(&ofproto->ml->rwlock); mac_learning_flush(ofproto->ml); ovs_rwlock_unlock(&ofproto->ml->rwlock); + mcast_snooping_mdb_flush(ofproto->ms); } /* Always updates the ofproto->pins_seqno to avoid frequent wakeup during @@ -1399,6 +1407,10 @@ run(struct ofproto *ofproto_) } ovs_rwlock_unlock(&ofproto->ml->rwlock); + if (mcast_snooping_run(ofproto->ms)) { + ofproto->backer->need_revalidate = REV_MCAST_SNOOPING; + } + new_dump_seq = seq_read(udpif_dump_seq(ofproto->backer->udpif)); if (ofproto->dump_seq != new_dump_seq) { struct rule *rule, *next_rule; @@ -1460,6 +1472,7 @@ wait(struct ofproto *ofproto_) ovs_rwlock_rdlock(&ofproto->ml->rwlock); mac_learning_wait(ofproto->ml); ovs_rwlock_unlock(&ofproto->ml->rwlock); + mcast_snooping_wait(ofproto->ms); stp_wait(ofproto); if (ofproto->backer->need_revalidate) { /* Shouldn't happen, but if it does just go around again. */ @@ -1977,6 +1990,7 @@ update_stp_port_state(struct ofport_dpif *ofport) ovs_rwlock_wrlock(&ofproto->ml->rwlock); mac_learning_flush(ofproto->ml); ovs_rwlock_unlock(&ofproto->ml->rwlock); + mcast_snooping_mdb_flush(ofproto->ms); } fwd_change = stp_forward_in_state(ofport->stp_state) != stp_forward_in_state(state); @@ -2102,6 +2116,7 @@ stp_run(struct ofproto_dpif *ofproto) ovs_rwlock_wrlock(&ofproto->ml->rwlock); mac_learning_flush(ofproto->ml); ovs_rwlock_unlock(&ofproto->ml->rwlock); + mcast_snooping_mdb_flush(ofproto->ms); } } } -- 2.20.1