Use IPv6 internally for storing multicast addresses. IPv4 addresses are translated to their IPv4-mapped equivalent.
Signed-off-by: Thadeu Lima de Souza Cascardo <casca...@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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev