[ovs-dev] [PATCH 2/3] mcast-snooping: Use IPv6 address for MDB

Thadeu Lima de Souza Cascardo cascardo at redhat.com
Tue Jun 23 20:03:15 UTC 2015


Use IPv6 internally for storing multicast addresses. IPv4 addresses are
translated to their IPv4-mapped equivalent.

Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo at redhat.com>
---
 lib/mcast-snooping.c         | 69 +++++++++++++++++++++++++++++++++++---------
 lib/mcast-snooping.h         | 24 +++++++++++----
 ofproto/ofproto-dpif-xlate.c |  6 ++--
 ofproto/ofproto-dpif.c       |  5 ++--
 4 files changed, 79 insertions(+), 25 deletions(-)

diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c
index 7b927aa..f2684f3 100644
--- a/lib/mcast-snooping.c
+++ b/lib/mcast-snooping.c
@@ -87,10 +87,11 @@ mcast_bundle_age(const struct mcast_snooping *ms,
 }
 
 static uint32_t
-mcast_table_hash(const struct mcast_snooping *ms, ovs_be32 grp_ip4,
-                 uint16_t vlan)
+mcast_table_hash(const struct mcast_snooping *ms,
+                 const struct in6_addr *grp_addr, uint16_t vlan)
 {
-    return hash_3words((OVS_FORCE uint32_t) grp_ip4, vlan, ms->secret);
+    return hash_words((const uint32_t *) grp_addr->s6_addr, 4,
+                      hash_2words(ms->secret, vlan));
 }
 
 static struct mcast_group_bundle *
@@ -108,8 +109,8 @@ mcast_group_from_lru_node(struct ovs_list *list)
 /* Searches 'ms' for and returns an mcast group for destination address
  * 'dip' in 'vlan'. */
 struct mcast_group *
-mcast_snooping_lookup(const struct mcast_snooping *ms, ovs_be32 dip,
-                      uint16_t vlan)
+mcast_snooping_lookup(const struct mcast_snooping *ms,
+                      const struct in6_addr *dip, uint16_t vlan)
     OVS_REQ_RDLOCK(ms->rwlock)
 {
     struct mcast_group *grp;
@@ -117,13 +118,32 @@ mcast_snooping_lookup(const struct mcast_snooping *ms, ovs_be32 dip,
 
     hash = mcast_table_hash(ms, dip, vlan);
     HMAP_FOR_EACH_WITH_HASH (grp, hmap_node, hash, &ms->table) {
-        if (grp->vlan == vlan && grp->ip4 == dip) {
+        if (grp->vlan == vlan && ipv6_addr_equals(&grp->addr, dip)) {
            return grp;
         }
     }
     return NULL;
 }
 
+static inline void
+in6_addr_set_mapped_ipv4(struct in6_addr *addr, ovs_be32 ip4)
+{
+    union ovs_16aligned_in6_addr *taddr = (void *) addr;
+    memset(taddr->be16, 0, sizeof(taddr->be16));
+    taddr->be16[5] = 0xffff;
+    put_16aligned_be32(&taddr->be32[3], ip4);
+}
+
+struct mcast_group *
+mcast_snooping_lookup4(const struct mcast_snooping *ms, ovs_be32 ip4,
+                      uint16_t vlan)
+    OVS_REQ_RDLOCK(ms->rwlock)
+{
+    struct in6_addr addr;
+    in6_addr_set_mapped_ipv4(&addr, ip4);
+    return mcast_snooping_lookup(ms, &addr, vlan);
+}
+
 /* If the LRU list is not empty, stores the least-recently-used entry
  * in '*e' and returns true.  Otherwise, if the LRU list is empty,
  * stores NULL in '*e' and return false. */
@@ -376,7 +396,8 @@ mcast_snooping_prune_expired(struct mcast_snooping *ms,
  * move to the last position in the LRU list.
  */
 bool
-mcast_snooping_add_group(struct mcast_snooping *ms, ovs_be32 ip4,
+mcast_snooping_add_group(struct mcast_snooping *ms,
+                         const struct in6_addr *addr,
                          uint16_t vlan, void *port)
     OVS_REQ_WRLOCK(ms->rwlock)
 {
@@ -390,9 +411,9 @@ mcast_snooping_add_group(struct mcast_snooping *ms, ovs_be32 ip4,
     }
 
     learned = false;
-    grp = mcast_snooping_lookup(ms, ip4, vlan);
+    grp = mcast_snooping_lookup(ms, addr, vlan);
     if (!grp) {
-        uint32_t hash = mcast_table_hash(ms, ip4, vlan);
+        uint32_t hash = mcast_table_hash(ms, addr, vlan);
 
         if (hmap_count(&ms->table) >= ms->max_entries) {
             group_get_lru(ms, &grp);
@@ -401,7 +422,7 @@ mcast_snooping_add_group(struct mcast_snooping *ms, ovs_be32 ip4,
 
         grp = xmalloc(sizeof *grp);
         hmap_insert(&ms->table, &grp->hmap_node, hash);
-        grp->ip4 = ip4;
+        memcpy(grp->addr.s6_addr, addr->s6_addr, sizeof(addr->s6_addr));
         grp->vlan = vlan;
         list_init(&grp->bundle_lru);
         learned = true;
@@ -417,6 +438,16 @@ mcast_snooping_add_group(struct mcast_snooping *ms, ovs_be32 ip4,
     return learned;
 }
 
+bool
+mcast_snooping_add_group4(struct mcast_snooping *ms, ovs_be32 ip4,
+                         uint16_t vlan, void *port)
+    OVS_REQ_WRLOCK(ms->rwlock)
+{
+    struct in6_addr addr;
+    in6_addr_set_mapped_ipv4(&addr, ip4);
+    return mcast_snooping_add_group(ms, &addr, vlan, port);
+}
+
 int
 mcast_snooping_add_report(struct mcast_snooping *ms,
                           const struct dp_packet *p,
@@ -455,9 +486,9 @@ mcast_snooping_add_report(struct mcast_snooping *ms,
         if (ntohs(record->nsrcs) == 0
             && (record->type == IGMPV3_MODE_IS_INCLUDE
                 || record->type == IGMPV3_CHANGE_TO_INCLUDE_MODE)) {
-            ret = mcast_snooping_leave_group(ms, ip4, vlan, port);
+            ret = mcast_snooping_leave_group4(ms, ip4, vlan, port);
         } else {
-            ret = mcast_snooping_add_group(ms, ip4, vlan, port);
+            ret = mcast_snooping_add_group4(ms, ip4, vlan, port);
         }
         if (ret) {
             count++;
@@ -469,7 +500,8 @@ mcast_snooping_add_report(struct mcast_snooping *ms,
 }
 
 bool
-mcast_snooping_leave_group(struct mcast_snooping *ms, ovs_be32 ip4,
+mcast_snooping_leave_group(struct mcast_snooping *ms,
+                           const struct in6_addr *addr,
                            uint16_t vlan, void *port)
     OVS_REQ_WRLOCK(ms->rwlock)
 {
@@ -482,7 +514,7 @@ mcast_snooping_leave_group(struct mcast_snooping *ms, ovs_be32 ip4,
         return false;
     }
 
-    grp = mcast_snooping_lookup(ms, ip4, vlan);
+    grp = mcast_snooping_lookup(ms, addr, vlan);
     if (grp && mcast_group_delete_bundle(ms, grp, port)) {
         ms->need_revalidate = true;
         return true;
@@ -490,6 +522,15 @@ mcast_snooping_leave_group(struct mcast_snooping *ms, ovs_be32 ip4,
     return false;
 }
 
+bool
+mcast_snooping_leave_group4(struct mcast_snooping *ms, ovs_be32 ip4,
+                           uint16_t vlan, void *port)
+{
+    struct in6_addr addr;
+    in6_addr_set_mapped_ipv4(&addr, ip4);
+    return mcast_snooping_leave_group(ms, &addr, vlan, port);
+}
+
 
 /* Router ports. */
 
diff --git a/lib/mcast-snooping.h b/lib/mcast-snooping.h
index f4bc8fb..e3d15e4 100644
--- a/lib/mcast-snooping.h
+++ b/lib/mcast-snooping.h
@@ -45,8 +45,8 @@ struct mcast_group {
     /* Node in parent struct mcast_snooping hmap. */
     struct hmap_node hmap_node;
 
-    /* Multicast group IPv4 address. */
-    ovs_be32 ip4;
+    /* Multicast group IPv6/IPv4 address. */
+    struct in6_addr addr;
 
     /* VLAN tag. */
     uint16_t vlan;
@@ -174,21 +174,33 @@ void mcast_snooping_set_port_flood_reports(struct mcast_snooping *ms,
 
 /* Lookup. */
 struct mcast_group *
-mcast_snooping_lookup(const struct mcast_snooping *ms, ovs_be32 dip,
-                      uint16_t vlan)
+mcast_snooping_lookup(const struct mcast_snooping *ms,
+                      const struct in6_addr *dip, uint16_t vlan)
+    OVS_REQ_RDLOCK(ms->rwlock);
+struct mcast_group *
+mcast_snooping_lookup4(const struct mcast_snooping *ms, ovs_be32 ip4,
+                       uint16_t vlan)
     OVS_REQ_RDLOCK(ms->rwlock);
 
 /* Learning. */
-bool mcast_snooping_add_group(struct mcast_snooping *ms, ovs_be32 ip4,
+bool mcast_snooping_add_group(struct mcast_snooping *ms,
+                              const struct in6_addr *addr,
                               uint16_t vlan, void *port)
     OVS_REQ_WRLOCK(ms->rwlock);
+bool mcast_snooping_add_group4(struct mcast_snooping *ms, ovs_be32 ip4,
+                               uint16_t vlan, void *port)
+    OVS_REQ_WRLOCK(ms->rwlock);
 int mcast_snooping_add_report(struct mcast_snooping *ms,
                               const struct dp_packet *p,
                               uint16_t vlan, void *port)
     OVS_REQ_WRLOCK(ms->rwlock);
-bool mcast_snooping_leave_group(struct mcast_snooping *ms, ovs_be32 ip4,
+bool mcast_snooping_leave_group(struct mcast_snooping *ms,
+                                const struct in6_addr *addr,
                                 uint16_t vlan, void *port)
     OVS_REQ_WRLOCK(ms->rwlock);
+bool mcast_snooping_leave_group4(struct mcast_snooping *ms, ovs_be32 ip4,
+                                 uint16_t vlan, void *port)
+    OVS_REQ_WRLOCK(ms->rwlock);
 bool mcast_snooping_add_mrouter(struct mcast_snooping *ms, uint16_t vlan,
                                 void *port)
     OVS_REQ_WRLOCK(ms->rwlock);
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 8c68273..1490f0f 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -2012,14 +2012,14 @@ update_mcast_snooping_table__(const struct xbridge *xbridge,
     switch (ntohs(flow->tp_src)) {
     case IGMP_HOST_MEMBERSHIP_REPORT:
     case IGMPV2_HOST_MEMBERSHIP_REPORT:
-        if (mcast_snooping_add_group(ms, ip4, vlan, in_xbundle->ofbundle)) {
+        if (mcast_snooping_add_group4(ms, ip4, vlan, in_xbundle->ofbundle)) {
             VLOG_DBG_RL(&rl, "bridge %s: multicast snooping learned that "
                         IP_FMT" is on port %s in VLAN %d",
                         xbridge->name, IP_ARGS(ip4), in_xbundle->name, vlan);
         }
         break;
     case IGMP_HOST_LEAVE_MESSAGE:
-        if (mcast_snooping_leave_group(ms, ip4, vlan, in_xbundle->ofbundle)) {
+        if (mcast_snooping_leave_group4(ms, ip4, vlan, in_xbundle->ofbundle)) {
             VLOG_DBG_RL(&rl, "bridge %s: multicast snooping leaving "
                         IP_FMT" is on port %s in VLAN %d",
                         xbridge->name, IP_ARGS(ip4), in_xbundle->name, vlan);
@@ -2330,7 +2330,7 @@ xlate_normal(struct xlate_ctx *ctx)
 
         /* forwarding to group base ports */
         ovs_rwlock_rdlock(&ms->rwlock);
-        grp = mcast_snooping_lookup(ms, flow->nw_dst, vlan);
+        grp = mcast_snooping_lookup4(ms, flow->nw_dst, vlan);
         if (grp) {
             xlate_normal_mcast_send_group(ctx, ms, grp, in_xbundle, vlan);
             xlate_normal_mcast_send_fports(ctx, ms, in_xbundle, vlan);
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 04f6229..cb6d303 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -4429,8 +4429,9 @@ ofproto_unixctl_mcast_snooping_show(struct unixctl_conn *conn,
             bundle = b->port;
             ofputil_port_to_string(ofbundle_get_a_port(bundle)->up.ofp_port,
                                    name, sizeof name);
-            ds_put_format(&ds, "%5s  %4d  "IP_FMT"         %3d\n",
-                          name, grp->vlan, IP_ARGS(grp->ip4),
+            ds_put_format(&ds, "%5s  %4d  ", name, grp->vlan);
+            print_ipv6_addr(&ds, &grp->addr);
+            ds_put_format(&ds, "         %3d\n",
                           mcast_bundle_age(ofproto->ms, b));
         }
     }
-- 
2.4.2




More information about the dev mailing list