[ovs-dev] [PATCH 16/18] dpif-xlate: Enable multicast snooping to handle its traffic

Flavio Leitner fbl at redhat.com
Fri Apr 11 21:34:21 UTC 2014


First check if the packet is a multicast and if the multicast
snooping feature is enabled.  If so, then update the multicast
snooping database accordingly and send it to the correct ports.

If the packet is not multicast, let the MAC learning handle the
packet as before.

This patch also removes OVS_UNUSED from all previous functions.

Signed-off-by: Flavio Leitner <fbl at redhat.com>
---
 ofproto/ofproto-dpif-xlate.c | 91 ++++++++++++++++++++++++++++++++++----------
 1 file changed, 71 insertions(+), 20 deletions(-)

diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 427958c..c918c4b 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -1403,7 +1403,7 @@ update_learning_table(const struct xbridge *xbridge,
 
 /* Updates multicast snooping table 'ms' given that a packet matching 'flow'
  * was received on 'in_xbundle' in 'vlan' and is Report or Query. */
-OVS_UNUSED static void
+static void
 update_mcast_snooping_table__(const struct xbridge *xbridge,
                               const struct flow *flow,
                               const struct mcast_ip *grp, int vlan,
@@ -1446,7 +1446,7 @@ OVS_REQ_WRLOCK(xbridge->ms->rwlock)
 
 /* Updates multicast snooping table 'ms' given that a packet matching 'flow'
  * was received on 'in_xbundle' in 'vlan'. */
-OVS_UNUSED static void
+static void
 update_mcast_snooping_table(const struct xbridge *xbridge,
                             const struct flow *flow, int vlan,
                             struct xbundle *in_xbundle)
@@ -1482,7 +1482,7 @@ update_mcast_snooping_table(const struct xbridge *xbridge,
 }
 
 /* send the packet to ports having the multicast group learned */
-OVS_UNUSED static void
+static void
 xlate_normal_mcast_send_group(struct xlate_ctx *ctx, struct mcast_entry *mcast,
                               struct xbundle *in_xbundle, uint16_t vlan)
 {
@@ -1503,7 +1503,7 @@ xlate_normal_mcast_send_group(struct xlate_ctx *ctx, struct mcast_entry *mcast,
 }
 
 /* send the packet to ports connected to multicast routers */
-OVS_UNUSED static void
+static void
 xlate_normal_mcast_send_mrouters(struct xlate_ctx *ctx,
                                  struct mcast_snooping *ms,
                                  struct xbundle *in_xbundle, uint16_t vlan)
@@ -1525,7 +1525,7 @@ xlate_normal_mcast_send_mrouters(struct xlate_ctx *ctx,
 }
 
 /* send the packet to ports flagged to be flooded */
-OVS_UNUSED static void
+static void
 xlate_normal_mcast_send_fports(struct xlate_ctx *ctx,
                                struct mcast_snooping *ms,
                                struct xbundle *in_xbundle, uint16_t vlan)
@@ -1632,24 +1632,75 @@ xlate_normal(struct xlate_ctx *ctx)
     }
 
     /* Determine output bundle. */
-    ovs_rwlock_rdlock(&ctx->xbridge->ml->rwlock);
-    mac = mac_learning_lookup(ctx->xbridge->ml, flow->dl_dst, vlan);
-    mac_port = mac ? mac->port.p : NULL;
-    ovs_rwlock_unlock(&ctx->xbridge->ml->rwlock);
-
-    if (mac_port) {
-        struct xbundle *mac_xbundle = xbundle_lookup(mac_port);
-        if (mac_xbundle && mac_xbundle != in_xbundle) {
-            xlate_report(ctx, "forwarding to learned port");
-            output_normal(ctx, mac_xbundle, vlan);
-        } else if (!mac_xbundle) {
-            xlate_report(ctx, "learned port is unknown, dropping");
+    if (mcast_snooping_enabled(ctx->xbridge->ms)
+        &&!eth_addr_is_broadcast(flow->dl_dst)
+        && eth_addr_is_multicast(flow->dl_dst)
+        && flow->dl_type == htons(ETH_TYPE_IP)) {
+        struct mcast_entry *mcast;
+
+        if (flow->nw_proto == IPPROTO_IGMP) {
+            if (ctx->xin->may_learn) {
+                update_mcast_snooping_table(ctx->xbridge, flow, vlan,
+                                            in_xbundle);
+            }
+
+            if (mcast_snooping_is_membership(flow->igmp_type)) {
+                xlate_normal_mcast_send_mrouters(ctx, ctx->xbridge->ms,
+                                                 in_xbundle, vlan);
+            } else {
+                xlate_normal_flood(ctx, in_xbundle, vlan);
+            }
+            return;
         } else {
-            xlate_report(ctx, "learned port is input port, dropping");
+            if (ip_is_local_multicast(flow->nw_dst)) {
+                /* RFC4541: section 2.1.2, item 2: Packets with a dst IP
+                 * address in the 224.0.0.x range which are not IGMP must
+                 * be forwarded on all ports */
+                xlate_normal_flood(ctx, in_xbundle, vlan);
+                return;
+            }
+        }
+
+        /* forwarding to group base ports */
+        ovs_rwlock_rdlock(&ctx->xbridge->ms->rwlock);
+        mcast = mcast_snooping_lookup4(ctx->xbridge->ms, flow->nw_dst, vlan);
+        if (mcast) {
+            xlate_normal_mcast_send_group(ctx, mcast, in_xbundle, vlan);
+            xlate_normal_mcast_send_fports(ctx, ctx->xbridge->ms, in_xbundle,
+                                           vlan);
+            xlate_normal_mcast_send_mrouters(ctx, ctx->xbridge->ms, in_xbundle,
+                                             vlan);
+        } else {
+            if (mcast_snooping_flood_unreg(ctx->xbridge->ms)) {
+                xlate_normal_flood(ctx, in_xbundle, vlan);
+            } else {
+                xlate_normal_mcast_send_mrouters(ctx, ctx->xbridge->ms,
+                                                 in_xbundle, vlan);
+                xlate_normal_mcast_send_fports(ctx, ctx->xbridge->ms,
+                                               in_xbundle, vlan);
+            }
         }
+        ovs_rwlock_unlock(&ctx->xbridge->ms->rwlock);
     } else {
-        xlate_report(ctx, "no learned MAC for destination, flooding");
-        xlate_normal_flood(ctx, in_xbundle, vlan);
+        ovs_rwlock_rdlock(&ctx->xbridge->ml->rwlock);
+        mac = mac_learning_lookup(ctx->xbridge->ml, flow->dl_dst, vlan);
+        mac_port = mac ? mac->port.p : NULL;
+        ovs_rwlock_unlock(&ctx->xbridge->ml->rwlock);
+
+        if (mac_port) {
+            struct xbundle *mac_xbundle = xbundle_lookup(mac_port);
+            if (mac_xbundle && mac_xbundle != in_xbundle) {
+                xlate_report(ctx, "forwarding to learned port");
+                output_normal(ctx, mac_xbundle, vlan);
+            } else if (!mac_xbundle) {
+                xlate_report(ctx, "learned port is unknown, dropping");
+            } else {
+                xlate_report(ctx, "learned port is input port, dropping");
+            }
+        } else {
+            xlate_normal_flood(ctx, in_xbundle, vlan);
+            xlate_report(ctx, "no learned MAC for destination, flooding");
+        }
     }
 }
 
-- 
1.9.0




More information about the dev mailing list