#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"
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. */
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,
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,
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);
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);
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,
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);
}
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);
#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"
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);
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 {
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;
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;
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,
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;
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);
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
}
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;
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. */
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);
ovs_rwlock_wrlock(&ofproto->ml->rwlock);
mac_learning_flush(ofproto->ml);
ovs_rwlock_unlock(&ofproto->ml->rwlock);
+ mcast_snooping_mdb_flush(ofproto->ms);
}
}
}