Thanks! I applied both of these to master. (Extra thanks to Flavio for the reviews.)
On Wed, Jun 17, 2015 at 02:12:20PM -0300, Thadeu Lima de Souza Cascardo wrote: > Support IGMPv3 messages with multiple records. Make sure all IGMPv3 > messages go through slow path, since they may carry multiple multicast > addresses, unlike IGMPv2. > > Tests done: > > * multiple addresses in IGMPv3 report are inserted in mdb; > * address is removed from IGMPv3 if record is INCLUDE_MODE; > * reports sent on a burst with same flow all go to userspace; > * IGMPv3 reports go to mrouters, i.e., ports that have issued a query. > > Signed-off-by: Thadeu Lima de Souza Cascardo <casca...@redhat.com> > --- > NEWS | 2 +- > lib/mcast-snooping.c | 52 > ++++++++++++++++++++++++++++++++++++++++++++ > lib/mcast-snooping.h | 5 +++++ > lib/packets.h | 26 ++++++++++++++++++++++ > ofproto/ofproto-dpif-xlate.c | 19 ++++++++++++---- > vswitchd/vswitch.xml | 2 +- > 6 files changed, 100 insertions(+), 6 deletions(-) > > diff --git a/NEWS b/NEWS > index 90d9a29..43461b2 100644 > --- a/NEWS > +++ b/NEWS > @@ -87,7 +87,7 @@ Post-v2.3.0 > with Docker, the wrapper script will be retired. > - Added support for DPDK Tunneling. VXLAN, GRE, and Geneve are supported > protocols. This is generic tunneling mechanism for userspace datapath. > - - Support for multicast snooping (IGMPv1 and IGMPv2) > + - Support for multicast snooping (IGMPv1, IGMPv2 and IGMPv3) > - Support for Linux kernels up to 4.0.x > - The documentation now use the term 'destination' to mean one of syslog, > console or file for vlog logging instead of the previously used term > diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c > index c3ffd6b..7b927aa 100644 > --- a/lib/mcast-snooping.c > +++ b/lib/mcast-snooping.c > @@ -69,6 +69,7 @@ mcast_snooping_is_membership(ovs_be16 igmp_type) > switch (ntohs(igmp_type)) { > case IGMP_HOST_MEMBERSHIP_REPORT: > case IGMPV2_HOST_MEMBERSHIP_REPORT: > + case IGMPV3_HOST_MEMBERSHIP_REPORT: > case IGMP_HOST_LEAVE_MESSAGE: > return true; > } > @@ -416,6 +417,57 @@ mcast_snooping_add_group(struct mcast_snooping *ms, > ovs_be32 ip4, > return learned; > } > > +int > +mcast_snooping_add_report(struct mcast_snooping *ms, > + const struct dp_packet *p, > + uint16_t vlan, void *port) > +{ > + ovs_be32 ip4; > + size_t offset; > + const struct igmpv3_header *igmpv3; > + const struct igmpv3_record *record; > + int count = 0; > + int ngrp; > + > + offset = (char *) dp_packet_l4(p) - (char *) dp_packet_data(p); > + igmpv3 = dp_packet_at(p, offset, IGMPV3_HEADER_LEN); > + if (!igmpv3) { > + return 0; > + } > + ngrp = ntohs(igmpv3->ngrp); > + offset += IGMPV3_HEADER_LEN; > + while (ngrp--) { > + bool ret; > + record = dp_packet_at(p, offset, sizeof(struct igmpv3_record)); > + if (!record) { > + break; > + } > + /* Only consider known record types. */ > + if (record->type < IGMPV3_MODE_IS_INCLUDE > + || record->type > IGMPV3_BLOCK_OLD_SOURCES) { > + continue; > + } > + ip4 = get_16aligned_be32(&record->maddr); > + /* > + * If record is INCLUDE MODE and there are no sources, it's > equivalent > + * to a LEAVE. > + */ > + 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); > + } else { > + ret = mcast_snooping_add_group(ms, ip4, vlan, port); > + } > + if (ret) { > + count++; > + } > + offset += sizeof(*record) > + + ntohs(record->nsrcs) * sizeof(ovs_be32) + > record->aux_len; > + } > + return count; > +} > + > bool > mcast_snooping_leave_group(struct mcast_snooping *ms, ovs_be32 ip4, > uint16_t vlan, void *port) > diff --git a/lib/mcast-snooping.h b/lib/mcast-snooping.h > index 979b2aa..f4bc8fb 100644 > --- a/lib/mcast-snooping.h > +++ b/lib/mcast-snooping.h > @@ -20,6 +20,7 @@ > #define MCAST_SNOOPING_H 1 > > #include <time.h> > +#include "dp-packet.h" > #include "hmap.h" > #include "list.h" > #include "ovs-atomic.h" > @@ -181,6 +182,10 @@ mcast_snooping_lookup(const struct mcast_snooping *ms, > ovs_be32 dip, > bool mcast_snooping_add_group(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, > uint16_t vlan, void *port) > OVS_REQ_WRLOCK(ms->rwlock); > diff --git a/lib/packets.h b/lib/packets.h > index e22267e..63ad2ff 100644 > --- a/lib/packets.h > +++ b/lib/packets.h > @@ -540,12 +540,38 @@ struct igmp_header { > }; > BUILD_ASSERT_DECL(IGMP_HEADER_LEN == sizeof(struct igmp_header)); > > +#define IGMPV3_HEADER_LEN 8 > +struct igmpv3_header { > + uint8_t type; > + uint8_t rsvr1; > + ovs_be16 csum; > + ovs_be16 rsvr2; > + ovs_be16 ngrp; > +}; > +BUILD_ASSERT_DECL(IGMPV3_HEADER_LEN == sizeof(struct igmpv3_header)); > + > +#define IGMPV3_RECORD_LEN 8 > +struct igmpv3_record { > + uint8_t type; > + uint8_t aux_len; > + ovs_be16 nsrcs; > + ovs_16aligned_be32 maddr; > +}; > +BUILD_ASSERT_DECL(IGMPV3_RECORD_LEN == sizeof(struct igmpv3_record)); > + > #define IGMP_HOST_MEMBERSHIP_QUERY 0x11 /* From RFC1112 */ > #define IGMP_HOST_MEMBERSHIP_REPORT 0x12 /* Ditto */ > #define IGMPV2_HOST_MEMBERSHIP_REPORT 0x16 /* V2 version of 0x12 */ > #define IGMP_HOST_LEAVE_MESSAGE 0x17 > #define IGMPV3_HOST_MEMBERSHIP_REPORT 0x22 /* V3 version of 0x12 */ > > +#define IGMPV3_MODE_IS_INCLUDE 1 > +#define IGMPV3_MODE_IS_EXCLUDE 2 > +#define IGMPV3_CHANGE_TO_INCLUDE_MODE 3 > +#define IGMPV3_CHANGE_TO_EXCLUDE_MODE 4 > +#define IGMPV3_ALLOW_NEW_SOURCES 5 > +#define IGMPV3_BLOCK_OLD_SOURCES 6 > + > #define SCTP_HEADER_LEN 12 > struct sctp_header { > ovs_be16 sctp_src; > diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c > index a0d13c2..5c1e63c 100644 > --- a/ofproto/ofproto-dpif-xlate.c > +++ b/ofproto/ofproto-dpif-xlate.c > @@ -1997,10 +1997,12 @@ update_mcast_snooping_table__(const struct xbridge > *xbridge, > const struct flow *flow, > struct mcast_snooping *ms, > ovs_be32 ip4, int vlan, > - struct xbundle *in_xbundle) > + struct xbundle *in_xbundle, > + const struct dp_packet *packet) > OVS_REQ_WRLOCK(ms->rwlock) > { > static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(60, 30); > + int count; > > switch (ntohs(flow->tp_src)) { > case IGMP_HOST_MEMBERSHIP_REPORT: > @@ -2027,6 +2029,14 @@ update_mcast_snooping_table__(const struct xbridge > *xbridge, > in_xbundle->name, vlan); > } > break; > + case IGMPV3_HOST_MEMBERSHIP_REPORT: > + if ((count = mcast_snooping_add_report(ms, packet, vlan, > + in_xbundle->ofbundle))) { > + VLOG_DBG_RL(&rl, "bridge %s: multicast snooping processed %d " > + "addresses on port %s in VLAN %d", > + xbridge->name, count, in_xbundle->name, vlan); > + } > + break; > } > } > > @@ -2035,7 +2045,8 @@ update_mcast_snooping_table__(const struct xbridge > *xbridge, > static void > update_mcast_snooping_table(const struct xbridge *xbridge, > const struct flow *flow, int vlan, > - struct xbundle *in_xbundle) > + struct xbundle *in_xbundle, > + const struct dp_packet *packet) > { > struct mcast_snooping *ms = xbridge->ms; > struct xlate_cfg *xcfg; > @@ -2060,7 +2071,7 @@ update_mcast_snooping_table(const struct xbridge > *xbridge, > > if (!mcast_xbundle || mcast_xbundle != in_xbundle) { > update_mcast_snooping_table__(xbridge, flow, ms, > flow->igmp_group_ip4, > - vlan, in_xbundle); > + vlan, in_xbundle, packet); > } > ovs_rwlock_unlock(&ms->rwlock); > } > @@ -2273,7 +2284,7 @@ xlate_normal(struct xlate_ctx *ctx) > mcast_snooping_is_query(flow->tp_src)) { > if (ctx->xin->may_learn) { > update_mcast_snooping_table(ctx->xbridge, flow, vlan, > - in_xbundle); > + in_xbundle, > ctx->xin->packet); > } > /* > * IGMP packets need to take the slow path, in order to be > diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml > index 8a60474..c43bfd1 100644 > --- a/vswitchd/vswitch.xml > +++ b/vswitchd/vswitch.xml > @@ -940,7 +940,7 @@ > Protocol (IGMP) traffic between hosts and multicast routers. The > switch uses what IGMP snooping learns to forward multicast traffic > only to interfaces that are connected to interested receivers. > - Currently it supports IGMPv1 and IGMPv2 protocols. > + Currently it supports IGMPv1, IGMPv2 and IGMPv3 protocols. > > <column name="mcast_snooping_enable"> > Enable multicast snooping on the bridge. For now, the default > -- > 2.4.2 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev