On Tue, Sep 21, 2021 at 1:50 PM Han Zhou <hz...@ovn.org> wrote: > > On Tue, Sep 21, 2021 at 6:50 AM Dumitru Ceara <dce...@redhat.com> wrote: > > > > IP multicast relay didn't work properly if traffic had to be forwarded > > across a distributed gateway port in the router pipeline. That is > > because the multicast_group used as output logical port is expanded in > > the egress pipeline, way after 'lr_in_gw_redirect' where unicast traffic > > would normally be forwarded to the chassis-redirect port. > > > > In order to achieve the same behavior for IP multicast routed traffic we > > now store the chassis-redirect port binding in the multicast_group on > > which IP multicast is routed. On the remote hypervisor, to make sure > > traffic is delivered to the correct destination switch pipeline, we make > > sure that ovn-controller translates chassis-redirect ports from > > multicast groups to the logical patch ports they were created from. > > > > This patch also adds a test to simulate the ovn-kubernetes IP multicast > > use case (where this issue was first observed). > > > > Fixes: 5d1527b11e94 ("ovn-northd: Add IGMP Relay support") > > Reported-by: Alexander Constantinescu <acons...@redhat.com> > > Reported-at: https://bugzilla.redhat.com/2006306 > > Signed-off-by: Dumitru Ceara <dce...@redhat.com> > > --- > > controller/physical.c | 28 ++++- > > northd/lrouter.dl | 14 ++- > > northd/multicast.dl | 23 +++- > > northd/northd.c | 7 +- > > northd/ovn_northd.dl | 12 +- > > tests/ovn.at | 248 ++++++++++++++++++++++++++++++++++++++++++ > > 6 files changed, 314 insertions(+), 18 deletions(-) > > > > diff --git a/controller/physical.c b/controller/physical.c > > index ffb9f9952..0cfb158c8 100644 > > --- a/controller/physical.c > > +++ b/controller/physical.c > > @@ -1373,7 +1373,8 @@ out: > > } > > > > static void > > -consider_mc_group(enum mf_field_id mff_ovn_geneve, > > +consider_mc_group(struct ovsdb_idl_index *sbrec_port_binding_by_name, > > + enum mf_field_id mff_ovn_geneve, > > const struct simap *ct_zones, > > const struct hmap *local_datapaths, > > struct shash *local_bindings, > > @@ -1406,6 +1407,10 @@ consider_mc_group(enum mf_field_id mff_ovn_geneve, > > * instead. (If we put them in 'ofpacts', then the output > > * would happen on every hypervisor in the multicast group, > > * effectively duplicating the packet.) > > + * > > + * - For chassisredirect ports, add actions to 'ofpacts' to > > + * set the output port to be the router patch port for which > > + * the redirect port was added. > > */ > > struct ofpbuf ofpacts; > > ofpbuf_init(&ofpacts, 0); > > @@ -1440,6 +1445,21 @@ consider_mc_group(enum mf_field_id mff_ovn_geneve, > > && port->chassis == chassis)) { > > put_load(port->tunnel_key, MFF_LOG_OUTPORT, 0, 32, &ofpacts); > > put_resubmit(OFTABLE_CHECK_LOOPBACK, &ofpacts); > > + } else if (!strcmp(port->type, "chassisredirect") > > + && port->chassis == chassis) { > > + const char *distributed_port = smap_get(&port->options, > > + "distributed-port"); > > + if (distributed_port) { > > + const struct sbrec_port_binding *distributed_binding > > + = lport_lookup_by_name(sbrec_port_binding_by_name, > > + distributed_port); > > + if (distributed_binding > > + && port->datapath == distributed_binding->datapath) { > > + put_load(distributed_binding->tunnel_key, > MFF_LOG_OUTPORT, > > + 0, 32, &ofpacts); > > + put_resubmit(OFTABLE_CHECK_LOOPBACK, &ofpacts); > > + } > > + } > > } else if (port->chassis && !get_localnet_port( > > local_datapaths, mc->datapath->tunnel_key)) { > > /* Add remote chassis only when localnet port not exist, > > @@ -1574,7 +1594,8 @@ physical_handle_mc_group_changes(struct > physical_ctx *p_ctx, > > if (!sbrec_multicast_group_is_new(mc)) { > > ofctrl_remove_flows(flow_table, &mc->header_.uuid); > > } > > - consider_mc_group(p_ctx->mff_ovn_geneve, p_ctx->ct_zones, > > + consider_mc_group(p_ctx->sbrec_port_binding_by_name, > > + p_ctx->mff_ovn_geneve, p_ctx->ct_zones, > > p_ctx->local_datapaths, > p_ctx->local_bindings, > > p_ctx->patch_ofports, > > p_ctx->chassis, mc, > > @@ -1617,7 +1638,8 @@ physical_run(struct physical_ctx *p_ctx, > > /* Handle output to multicast groups, in tables 32 and 33. */ > > const struct sbrec_multicast_group *mc; > > SBREC_MULTICAST_GROUP_TABLE_FOR_EACH (mc, p_ctx->mc_group_table) { > > - consider_mc_group(p_ctx->mff_ovn_geneve, p_ctx->ct_zones, > > + consider_mc_group(p_ctx->sbrec_port_binding_by_name, > > + p_ctx->mff_ovn_geneve, p_ctx->ct_zones, > > p_ctx->local_datapaths, p_ctx->local_bindings, > > p_ctx->patch_ofports, p_ctx->chassis, > > mc, p_ctx->chassis_tunnels, > > diff --git a/northd/lrouter.dl b/northd/lrouter.dl > > index 3029ba67d..0e4308eb5 100644 > > --- a/northd/lrouter.dl > > +++ b/northd/lrouter.dl > > @@ -145,8 +145,10 @@ Warning[message] :- > > * > > * A logical router can have multiple distributed gateway ports. */ > > relation DistributedGatewayPort(lrp: Intern<nb::Logical_Router_Port>, > > - lr_uuid: uuid) > > -DistributedGatewayPort(lrp, lr_uuid) :- > > + lr_uuid: uuid, cr_lrp_uuid: uuid) > > + > > +// lrp._uuid is already in use; generate a new UUID by hashing it. > > +DistributedGatewayPort(lrp, lr_uuid, hash128(lrp_uuid)) :- > > lr in nb::Logical_Router(._uuid = lr_uuid), > > LogicalRouterPort(lrp_uuid, lr._uuid), > > lrp in &nb::Logical_Router_Port(._uuid = lrp_uuid), > > @@ -237,10 +239,10 @@ DistributedGatewayPortHAChassisGroup(lrp, > > > > /* For each router port, tracks whether it's a redirect port of its > router */ > > relation RouterPortIsRedirect(lrp: uuid, is_redirect: bool) > > -RouterPortIsRedirect(lrp, true) :- > DistributedGatewayPort(&nb::Logical_Router_Port{._uuid = lrp}, _). > > +RouterPortIsRedirect(lrp, true) :- > DistributedGatewayPort(&nb::Logical_Router_Port{._uuid = lrp}, _, _). > > RouterPortIsRedirect(lrp, false) :- > > &nb::Logical_Router_Port(._uuid = lrp), > > - not DistributedGatewayPort(&nb::Logical_Router_Port{._uuid = lrp}, > _). > > + not DistributedGatewayPort(&nb::Logical_Router_Port{._uuid = lrp}, > _, _). > > > > /* > > * LogicalRouterDGWPorts maps from each logical router UUID > > @@ -249,12 +251,12 @@ relation LogicalRouterDGWPorts( > > lr_uuid: uuid, > > l3dgw_ports: Vec<Intern<nb::Logical_Router_Port>>) > > LogicalRouterDGWPorts(lr_uuid, l3dgw_ports) :- > > - DistributedGatewayPort(lrp, lr_uuid), > > + DistributedGatewayPort(lrp, lr_uuid, _), > > var l3dgw_ports = lrp.group_by(lr_uuid).to_vec(). > > LogicalRouterDGWPorts(lr_uuid, vec_empty()) :- > > lr in nb::Logical_Router(), > > var lr_uuid = lr._uuid, > > - not DistributedGatewayPort(_, lr_uuid). > > + not DistributedGatewayPort(_, lr_uuid, _). > > > > typedef ExceptionalExtIps = AllowedExtIps{ips: Intern<nb::Address_Set>} > > | ExemptedExtIps{ips: Intern<nb::Address_Set>} > > diff --git a/northd/multicast.dl b/northd/multicast.dl > > index 074caf654..56bfa0c63 100644 > > --- a/northd/multicast.dl > > +++ b/northd/multicast.dl > > @@ -236,7 +236,28 @@ IgmpRouterGroupPort(address, rtr_port.router, > rtr_port.lrp._uuid) :- > > }, > > var flood_port = FlatMap(sw_flood_ports), > > &SwitchPort(.lsp = &nb::Logical_Switch_Port{._uuid = flood_port}, > > - .peer = Some{rtr_port}). > > + .peer = Some{rtr_port}), > > + RouterPortIsRedirect(rtr_port.lrp._uuid, false). > > + > > +/* Store the chassis redirect port uuid for redirect ports, otherwise > traffic > > + * will not be tunneled properly. This will be translated back to the > patch > > + * port on the remote hypervisor. > > + */ > > +IgmpRouterGroupPort(address, rtr_port.router, cr_lrp_uuid) :- > > + SwitchMcastFloodRelayPorts(switch, sw_flood_ports), > > + IgmpSwitchMulticastGroup(address, switch, _), > > + /* For IPv6 only relay routable multicast groups > > + * (RFC 4291 2.7). > > + */ > > + match (ipv6_parse(address.ival())) { > > + Some{ipv6} -> ipv6.is_routable_multicast(), > > + None -> true > > + }, > > + var flood_port = FlatMap(sw_flood_ports), > > + &SwitchPort(.lsp = &nb::Logical_Switch_Port{._uuid = flood_port}, > > + .peer = Some{rtr_port}), > > + RouterPortIsRedirect(rtr_port.lrp._uuid, true), > > + DistributedGatewayPort(rtr_port.lrp, _, cr_lrp_uuid). > > > > /* Aggregated IGMP group for routers: merges all IgmpRouterGroupPort for > > * a given address-router tuple from all connected switches. > > diff --git a/northd/northd.c b/northd/northd.c > > index d1b87891c..e021e146b 100644 > > --- a/northd/northd.c > > +++ b/northd/northd.c > > @@ -14169,7 +14169,12 @@ build_mcast_groups(struct northd_context *ctx, > > address, igmp_group->mcgroup.name > ); > > struct ovn_port **router_igmp_ports = > > xmalloc(sizeof *router_igmp_ports); > > - router_igmp_ports[0] = router_port; > > + /* Store the chassis redirect port otherwise traffic > will not > > + * be tunneled properly. > > + */ > > + router_igmp_ports[0] = router_port->cr_port > > + ? router_port->cr_port > > + : router_port; > > ovn_igmp_group_add_entry(igmp_group_rtr, > router_igmp_ports, 1); > > } > > } > > diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl > > index 0202af5dc..22913f05a 100644 > > --- a/northd/ovn_northd.dl > > +++ b/northd/ovn_northd.dl > > @@ -464,9 +464,7 @@ function has_distributed_nat(nats: Vec<NAT>): bool { > > */ > > > > /* Create derived ports */ > > -OutProxy_Port_Binding(// lrp._uuid is already in use; generate a new > UUID by > > - // hashing it. > > - ._uuid = hash128(lrp._uuid), > > +OutProxy_Port_Binding(._uuid = cr_lrp_uuid, > > .logical_port = chassis_redirect_name( > lrp.name).intern(), > > .__type = i"chassisredirect", > > .gateway_chassis = set_empty(), > > @@ -478,7 +476,7 @@ OutProxy_Port_Binding(// lrp._uuid is already in use; > generate a new UUID by > > .mac = set_singleton(i"${lrp.mac} > ${lrp.networks.map(ival).to_vec().join(\" \")}"), > > .nat_addresses = set_empty(), > > .external_ids = lrp.external_ids) :- > > - DistributedGatewayPort(lrp, lr_uuid), > > + DistributedGatewayPort(lrp, lr_uuid, cr_lrp_uuid), > > DistributedGatewayPortHAChassisGroup(lrp, hacg_uuid), > > var redirect_type = match (lrp.options.get(i"redirect-type")) { > > Some{var value} -> [i"redirect-type" -> value], > > @@ -549,7 +547,7 @@ RefChassis(lr_uuid, chassis_uuid) :- > > HAChassis(.hacg_uuid = hacg_uuid, .hac_uuid = hac_uuid), > > var hacg_size = hac_uuid.group_by(hacg_uuid).to_set().size(), > > hacg_size > 1, > > - DistributedGatewayPort(lrp, lr_uuid), > > + DistributedGatewayPort(lrp, lr_uuid, _), > > ConnectedLogicalRouter[(lr_uuid, set_uuid)], > > ConnectedLogicalRouter[(lr2_uuid, set_uuid)], > > FirstHopLogicalRouter(lr2_uuid, ls_uuid), > > @@ -577,7 +575,7 @@ relation HAChassisGroupRefChassisSet(hacg_uuid: uuid, > > chassis_uuids: Set<uuid>) > > HAChassisGroupRefChassisSet(hacg_uuid, chassis_uuids) :- > > DistributedGatewayPortHAChassisGroup(lrp, hacg_uuid), > > - DistributedGatewayPort(lrp, lr_uuid), > > + DistributedGatewayPort(lrp, lr_uuid, _), > > RefChassisSet(lr_uuid, chassis_uuids), > > var chassis_uuids = chassis_uuids.group_by(hacg_uuid).union(). > > > > @@ -8198,7 +8196,7 @@ for (&Router(._uuid = lr_uuid)) > > * packet did not match any higher priority redirect > > * rule, then the traffic is redirected to the central > > * instance of the l3dgw_port. */ > > - for (DistributedGatewayPort(lrp, lr_uuid)) { > > + for (DistributedGatewayPort(lrp, lr_uuid, _)) { > > Flow(.logical_datapath = lr_uuid, > > .stage = s_ROUTER_IN_GW_REDIRECT(), > > .priority = 50, > > diff --git a/tests/ovn.at b/tests/ovn.at > > index d76f4ba86..172b5c713 100644 > > --- a/tests/ovn.at > > +++ b/tests/ovn.at > > @@ -19247,6 +19247,254 @@ OVN_CLEANUP([hv1], [hv2], [hv3]) > > AT_CLEANUP > > ]) > > > > +OVN_FOR_EACH_NORTHD([ > > +AT_SETUP([IGMP relay - distributed gateway port]) > > +AT_KEYWORDS([snoop relay]) > > + > > +ovn_start > > + > > +# Logical network: > > +# Two logical switches (sw1-sw2) connected to a logical router (rtr). > > +# sw1: > > +# - subnet 10.0.0.0/8 > > +# - 1 ports bound on hv1 (sw1-p1) > > +# sw2: > > +# - subnet 20.0.0.0/8 > > +# - 1 port bound on hv2 (sw2-p2) > > +# - IGMP Querier from 20.0.0.254 > > + > > +reset_pcap_file() { > > + local iface=$1 > > + local pcap_file=$2 > > + check ovs-vsctl -- set Interface $iface > options:tx_pcap=dummy-tx.pcap \ > > +options:rxq_pcap=dummy-rx.pcap > > + rm -f ${pcap_file}*.pcap > > + check ovs-vsctl -- set Interface $iface > options:tx_pcap=${pcap_file}-tx.pcap \ > > +options:rxq_pcap=${pcap_file}-rx.pcap > > +} > > + > > +# > > +# send_igmp_v3_report INPORT HV ETH_SRC IP_SRC IP_CSUM GROUP REC_TYPE > > +# IGMP_CSUM OUTFILE > > +# > > +# This shell function causes an IGMPv3 report to be received on INPORT > of HV. > > +# The packet's content has Ethernet destination 01:00:5E:00:00:22 and > source > > +# ETH_SRC (exactly 12 hex digits). Ethernet type is set to IP. > > +# GROUP is the IP multicast group to be joined/to leave (based on > REC_TYPE). > > +# REC_TYPE == 04: join GROUP > > +# REC_TYPE == 03: leave GROUP > > +# The packet hexdump is also stored in OUTFILE. > > +# > > +send_igmp_v3_report() { > > + local inport=$1 hv=$2 eth_src=$3 ip_src=$4 ip_chksum=$5 group=$6 > > + local rec_type=$7 igmp_chksum=$8 outfile=$9 > > + > > + local eth_dst=01005e000016 > > + local ip_dst=$(ip_to_hex 224 0 0 22) > > + local ip_ttl=01 > > + local ip_ra_opt=94040000 > > + > > + local igmp_type=2200 > > + local num_rec=00000001 > > + local aux_dlen=00 > > + local num_src=0000 > > + > > + local eth=${eth_dst}${eth_src}0800 > > + local > ip=46c0002800004000${ip_ttl}02${ip_chksum}${ip_src}${ip_dst}${ip_ra_opt} > > + local > igmp=${igmp_type}${igmp_chksum}${num_rec}${rec_type}${aux_dlen}${num_src}${group} > > + local packet=${eth}${ip}${igmp} > > + > > + echo ${packet} >> ${outfile} > > + check as $hv ovs-appctl netdev-dummy/receive ${inport} ${packet} > > +} > > + > > +# > > +# store_igmp_v3_query ETH_SRC IP_SRC IP_CSUM OUTFILE > > +# > > +# This shell function builds an IGMPv3 general query from ETH_SRC and > IP_SRC > > +# and stores the hexdump of the packet in OUTFILE. > > +# > > +store_igmp_v3_query() { > > + local eth_src=$1 ip_src=$2 ip_chksum=$3 outfile=$4 > > + > > + local eth_dst=01005e000001 > > + local ip_dst=$(ip_to_hex 224 0 0 1) > > + local ip_ttl=01 > > + local igmp_type=11 > > + local max_resp=0a > > + local igmp_chksum=eeeb > > + local addr=00000000 > > + > > + local eth=${eth_dst}${eth_src}0800 > > + local ip=4500002000004000${ip_ttl}02${ip_chksum}${ip_src}${ip_dst} > > + local igmp=${igmp_type}${max_resp}${igmp_chksum}${addr}000a0000 > > + local packet=${eth}${ip}${igmp} > > + > > + echo ${packet} >> ${outfile} > > +} > > + > > +# > > +# send_ip_multicast_pkt INPORT HV ETH_SRC ETH_DST IP_SRC IP_DST IP_LEN > TTL > > +# IP_CHKSUM IP_PROTO DATA > > +# > > +# This shell function causes an IP multicast packet to be received on > INPORT > > +# of HV. > > +# The hexdump of the packet is stored in OUTFILE. > > +# > > +send_ip_multicast_pkt() { > > + local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 > > + local ip_src=$5 ip_dst=$6 ip_len=$7 ip_ttl=$8 ip_chksum=$9 > proto=${10} > > + local data=${11} > > + > > + local eth=${eth_dst}${eth_src}0800 > > + local > ip=450000${ip_len}95f14000${ip_ttl}${proto}${ip_chksum}${ip_src}${ip_dst} > > + local packet=${eth}${ip}${data} > > + > > + check as $hv ovs-appctl netdev-dummy/receive ${inport} ${packet} > > +} > > + > > +# > > +# store_ip_multicast_pkt ETH_SRC ETH_DST IP_SRC IP_DST IP_LEN TTL > > +# IP_CHKSUM IP_PROTO DATA OUTFILE > > +# > > +# This shell function builds an IP multicast packet and stores the > hexdump of > > +# the packet in OUTFILE. > > +# > > +store_ip_multicast_pkt() { > > + local eth_src=$1 eth_dst=$2 > > + local ip_src=$3 ip_dst=$4 ip_len=$5 ip_ttl=$6 ip_chksum=$7 proto=$8 > > + local data=$9 outfile=${10} > > + > > + local eth=${eth_dst}${eth_src}0800 > > + local > ip=450000${ip_len}95f14000${ip_ttl}${proto}${ip_chksum}${ip_src}${ip_dst} > > + local packet=${eth}${ip}${data} > > + > > + echo ${packet} >> ${outfile} > > +} > > + > > +check ovn-nbctl ls-add sw1 \ > > + -- lsp-add sw1 sw1-p1 > > + > > +check ovn-nbctl ls-add sw2 \ > > + -- lsp-add sw2 sw2-p2 > > + > > +check ovn-nbctl lr-add rtr \ > > + -- lrp-add rtr rtr-sw1 00:00:00:00:01:00 10.0.0.254/24 \ > > + -- lrp-add rtr rtr-sw2 00:00:00:00:02:00 20.0.0.254/24 > > + > > +ovn-nbctl lsp-add sw1 sw1-rtr \ > > + -- lsp-set-type sw1-rtr router \ > > + -- lsp-set-addresses sw1-rtr 00:00:00:00:01:00 \ > > + -- lsp-set-options sw1-rtr router-port=rtr-sw1 > > +check ovn-nbctl lsp-add sw2 sw2-rtr \ > > + -- lsp-set-type sw2-rtr router \ > > + -- lsp-set-addresses sw2-rtr 00:00:00:00:02:00 \ > > + -- lsp-set-options sw2-rtr router-port=rtr-sw2 > > +check ovn-nbctl lrp-set-gateway-chassis rtr-sw1 hv1 10 > > +check ovn-nbctl lrp-set-gateway-chassis rtr-sw2 hv2 10 > > + > > +net_add n1 > > +sim_add hv1 > > +as hv1 > > +check ovs-vsctl add-br br-phys > > +ovn_attach n1 br-phys 192.168.0.1 > > +check ovs-vsctl -- add-port br-int hv1-vif1 -- \ > > + set interface hv1-vif1 external-ids:iface-id=sw1-p1 \ > > + options:tx_pcap=hv1/vif1-tx.pcap \ > > + options:rxq_pcap=hv1/vif1-rx.pcap > > + > > +sim_add hv2 > > +as hv2 > > +check ovs-vsctl add-br br-phys > > +ovn_attach n1 br-phys 192.168.0.2 > > +check ovs-vsctl -- add-port br-int hv2-vif2 -- \ > > + set interface hv2-vif2 external-ids:iface-id=sw2-p2 \ > > + options:tx_pcap=hv2/vif2-tx.pcap \ > > + options:rxq_pcap=hv2/vif2-rx.pcap > > + > > +wait_for_ports_up > > + > > +AS_BOX([Wait until cr-rtr-sw1 is claimed by hv1]) > > +hv1_chassis=$(fetch_column Chassis _uuid name=hv1) > > +AS_BOX([check that the chassis redirect port has been claimed by the hv1 > chassis]) > > +wait_row_count Port_Binding 1 logical_port=cr-rtr-sw1 > chassis=$hv1_chassis > > + > > +AS_BOX([Wait until cr-rtr-sw2 is claimed by hv2]) > > +hv2_chassis=$(fetch_column Chassis _uuid name=hv2) > > +AS_BOX([check that the chassis redirect port has been claimed by the hv2 > chassis]) > > +wait_row_count Port_Binding 1 logical_port=cr-rtr-sw2 > chassis=$hv2_chassis > > + > > +check ovn-nbctl --wait=hv sync > > + > > +AT_CAPTURE_FILE([exp]) > > +AT_CAPTURE_FILE([rcv]) > > +check_packets() { > > + > exp > > + > rcv > > + if test "$1" = --uniq; then > > + sort="sort -u"; shift > > + else > > + sort=sort > > + fi > > + for tuple in "$@"; do > > + set $tuple; pcap=$1 type=$2 > > + echo "--- $pcap" | tee -a exp >> rcv > > + $sort "$type" >> exp > > + $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" $pcap | $sort >> rcv > > + echo | tee -a exp >> rcv > > + done > > + > > + $at_diff exp rcv >/dev/null > > +} > > + > > +OVN_POPULATE_ARP > > + > > +# Enable IGMP snooping on sw1 and sw2 and relay on rtr. > > +check ovn-nbctl --wait=hv set Logical_Switch sw1 \ > > + other_config:mcast_querier="false" \ > > + other_config:mcast_snoop="true" > > +check ovn-nbctl --wait=hv set Logical_Switch sw2 \ > > + other_config:mcast_querier="false" \ > > + other_config:mcast_snoop="true" > > +check ovn-nbctl set logical_router rtr \ > > + options:mcast_relay="true" > > +check ovn-nbctl --wait=hv sync > > + > > +# Inject IGMP Join for 239.0.1.68 on sw2-p2. > > +send_igmp_v3_report hv2-vif2 hv2 \ > > + 000000000001 $(ip_to_hex 10 0 0 1) f9f8 \ > > + $(ip_to_hex 239 0 1 68) 04 e9b9 \ > > + /dev/null > > + > > +# Check that the IGMP Group is learned by all switches. > > +wait_row_count IGMP_Group 1 address=239.0.1.68 > > +check ovn-nbctl --wait=hv sync > > + > > +# Send traffic from sw1 and make sure it is relayed by rtr. > > +> expected_routed > > +> expected_empty > > + > > +as hv1 reset_pcap_file hv1-vif1 hv1/vif1 > > +as hv2 reset_pcap_file hv2-vif2 hv2/vif2 > > + > > +send_ip_multicast_pkt hv1-vif1 hv1 \ > > + 000000000001 01005e000144 \ > > + $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e 20 ca70 11 \ > > + e518e518000a3b3a0000 > > +store_ip_multicast_pkt \ > > + 000000000200 01005e000144 \ > > + $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e 1f cb70 11 \ > > + e518e518000a3b3a0000 expected_routed > > + > > +OVS_WAIT_UNTIL( > > + [check_packets 'hv1/vif1-tx.pcap expected_empty' \ > > + 'hv2/vif2-tx.pcap expected_routed'], > > + [$at_diff -F'^---' exp rcv]) > > + > > +OVN_CLEANUP([hv1], [hv2]) > > +AT_CLEANUP > > +]) > > + > > OVN_FOR_EACH_NORTHD([ > > AT_SETUP([MLD snoop/querier/relay]) > > AT_KEYWORDS([snoop query querier relay]) > > -- > > 2.27.0 > > > > _______________________________________________ > > dev mailing list > > d...@openvswitch.org > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > Thanks for the fix. I haven't tested, but it looks good. > > Acked-by: Han Zhou <hz...@ovn.org>
Thanks Dumitru and Han. I applied this patch to the main branch and to branch-21.09. Numan > _______________________________________________ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev