-/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
struct mcast_snooping *ms = xbridge->ms;
struct xlate_cfg *xcfg;
struct xbundle *mcast_xbundle;
- struct mcast_fport_bundle *fport;
+ struct mcast_port_bundle *fport;
/* Don't learn the OFPP_NONE port. */
if (in_xbundle == &ofpp_none_bundle) {
mcast_xbundle = NULL;
ovs_rwlock_wrlock(&ms->rwlock);
xcfg = ovsrcu_get(struct xlate_cfg *, &xcfgp);
- LIST_FOR_EACH(fport, fport_node, &ms->fport_list) {
+ LIST_FOR_EACH(fport, node, &ms->fport_list) {
mcast_xbundle = xbundle_lookup(xcfg, fport->port);
if (mcast_xbundle == in_xbundle) {
break;
OVS_REQ_RDLOCK(ms->rwlock)
{
struct xlate_cfg *xcfg;
- struct mcast_fport_bundle *fport;
+ struct mcast_port_bundle *fport;
struct xbundle *mcast_xbundle;
xcfg = ovsrcu_get(struct xlate_cfg *, &xcfgp);
- LIST_FOR_EACH(fport, fport_node, &ms->fport_list) {
+ LIST_FOR_EACH(fport, node, &ms->fport_list) {
mcast_xbundle = xbundle_lookup(xcfg, fport->port);
if (mcast_xbundle && mcast_xbundle != in_xbundle) {
xlate_report(ctx, "forwarding to mcast flood port");
}
}
+/* forward the Reports to configured ports */
+static void
+xlate_normal_mcast_send_rports(struct xlate_ctx *ctx,
+ struct mcast_snooping *ms,
+ struct xbundle *in_xbundle, uint16_t vlan)
+ OVS_REQ_RDLOCK(ms->rwlock)
+{
+ struct xlate_cfg *xcfg;
+ struct mcast_port_bundle *rport;
+ struct xbundle *mcast_xbundle;
+
+ xcfg = ovsrcu_get(struct xlate_cfg *, &xcfgp);
+ LIST_FOR_EACH(rport, node, &ms->rport_list) {
+ mcast_xbundle = xbundle_lookup(xcfg, rport->port);
+ if (mcast_xbundle && mcast_xbundle != in_xbundle) {
+ xlate_report(ctx, "forwarding Report to mcast flagged port");
+ output_normal(ctx, mcast_xbundle, vlan);
+ } else if (!mcast_xbundle) {
+ xlate_report(ctx, "mcast port is unknown, dropping the Report");
+ } else {
+ xlate_report(ctx, "mcast port is input port, dropping the Report");
+ }
+ }
+}
+
static void
xlate_normal_flood(struct xlate_ctx *ctx, struct xbundle *in_xbundle,
uint16_t vlan)
if (mcast_snooping_is_membership(flow->tp_src)) {
ovs_rwlock_rdlock(&ms->rwlock);
xlate_normal_mcast_send_mrouters(ctx, ms, in_xbundle, vlan);
+ /* RFC4541: section 2.1.1, item 1: A snooping switch should
+ * forward IGMP Membership Reports only to those ports where
+ * multicast routers are attached. Alternatively stated: a
+ * snooping switch should not forward IGMP Membership Reports
+ * to ports on which only hosts are attached.
+ * An administrative control may be provided to override this
+ * restriction, allowing the report messages to be flooded to
+ * other ports. */
+ xlate_normal_mcast_send_rports(ctx, ms, in_xbundle, vlan);
ovs_rwlock_unlock(&ms->rwlock);
} else {
xlate_report(ctx, "multicast traffic, flooding");
/* If 'struct flow' gets additional metadata, we'll need to zero it out
* before traversing a patch port. */
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 29);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 30);
memset(&flow_tnl, 0, sizeof flow_tnl);
if (!xport) {
case OFPACT_SET_TUNNEL:
case OFPACT_SET_QUEUE:
case OFPACT_POP_QUEUE:
+ case OFPACT_CONJUNCTION:
case OFPACT_NOTE:
case OFPACT_OUTPUT_REG:
case OFPACT_EXIT:
xlate_learn_action(ctx, ofpact_get_LEARN(a));
break;
+ case OFPACT_CONJUNCTION: {
+ /* A flow with a "conjunction" action represents part of a special
+ * kind of "set membership match". Such a flow should not actually
+ * get executed, but it could via, say, a "packet-out", even though
+ * that wouldn't be useful. Log it to help debugging. */
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+ VLOG_INFO_RL(&rl, "executing no-op conjunction action");
+ break;
+ }
+
case OFPACT_EXIT:
ctx->exit = true;
break;