Avoid recirculating IGMP/MLD packets more than one time from stage ls_out_pre_lb in the egress pipeline to ovn table 37 in order to avoid packet looping for ovn-ic deployment.
Reported-at: https://issues.redhat.com/browse/FDP-58 Acked-by: Mohammad Heib <mh...@redhat.com> Signed-off-by: Lorenzo Bianconi <lorenzo.bianc...@redhat.com> --- controller/pinctrl.c | 2 ++ include/ovn/logical-fields.h | 3 +++ lib/logical-fields.c | 5 +++++ northd/en-multicast.c | 2 +- northd/northd.c | 11 +++++++---- tests/ovn-ic.at | 32 +++++++++++++++++++++++++++++++- 6 files changed, 49 insertions(+), 6 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index bdb619b4d..5e24d97c8 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -727,6 +727,8 @@ pinctrl_forward_pkt(struct rconn *swconn, int64_t dp_key, put_load(dp_key, MFF_LOG_DATAPATH, 0, 64, &ofpacts); put_load(in_port_key, MFF_LOG_INPORT, 0, 32, &ofpacts); put_load(out_port_key, MFF_LOG_OUTPORT, 0, 32, &ofpacts); + /* Avoid re-injecting packet already consumed. */ + put_load(1, MFF_LOG_FLAGS, MLF_IGMP_IGMP_SNOOP_INJECT_BIT, 1, &ofpacts); struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts); resubmit->in_port = OFPP_CONTROLLER; diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h index 17154d38b..653145ddd 100644 --- a/include/ovn/logical-fields.h +++ b/include/ovn/logical-fields.h @@ -103,6 +103,7 @@ enum mff_log_flags_bits { MLF_FROM_CTRL_BIT = 19, MLF_UNSNAT_NEW_BIT = 20, MLF_UNSNAT_NOT_TRACKED_BIT = 21, + MLF_IGMP_IGMP_SNOOP_INJECT_BIT = 22, MLF_NETWORK_ID_START_BIT = 28, MLF_NETWORK_ID_END_BIT = 31, }; @@ -169,6 +170,8 @@ enum mff_log_flags { /* Indicate that the packet didn't go through unSNAT. */ MLF_UNSNAT_NOT_TRACKED = (1 << MLF_UNSNAT_NOT_TRACKED_BIT), + MLF_IGMP_IGMP_SNOOP = (1 << MLF_IGMP_IGMP_SNOOP_INJECT_BIT), + /* Assign network ID to packet to choose correct network for snat when * lb_force_snat_ip=router_ip. */ MLF_NETWORK_ID = (OVN_MAX_NETWORK_ID << MLF_NETWORK_ID_START_BIT), diff --git a/lib/logical-fields.c b/lib/logical-fields.c index db2d08ada..a74e18e0f 100644 --- a/lib/logical-fields.c +++ b/lib/logical-fields.c @@ -154,6 +154,11 @@ ovn_init_symtab(struct shash *symtab) snprintf(flags_str, sizeof flags_str, "flags[%d]", MLF_FROM_CTRL_BIT); expr_symtab_add_subfield(symtab, "flags.from_ctrl", NULL, flags_str); + snprintf(flags_str, sizeof flags_str, "flags[%d]", + MLF_IGMP_IGMP_SNOOP_INJECT_BIT); + expr_symtab_add_subfield(symtab, "flags.igmp_loopback", NULL, + flags_str); + /* Connection tracking state. */ expr_symtab_add_field_scoped(symtab, "ct_mark", MFF_CT_MARK, NULL, false, WR_CT_COMMIT); diff --git a/northd/en-multicast.c b/northd/en-multicast.c index 7f3a6077c..657e20b39 100644 --- a/northd/en-multicast.c +++ b/northd/en-multicast.c @@ -625,7 +625,7 @@ ovn_igmp_group_get_ports(const struct sbrec_igmp_group *sb_igmp_group, } /* If this is already a flood port skip it for the group. */ - if (port->mcast_info.flood) { + if (port->mcast_info.flood || port->mcast_info.flood_reports) { continue; } diff --git a/northd/northd.c b/northd/northd.c index 1f9340e55..5416244cc 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -6125,7 +6125,8 @@ build_interconn_mcast_snoop_flows(struct ovn_datapath *od, continue; } /* Punt IGMP traffic to controller. */ - char *match = xasprintf("inport == %s && igmp", op->json_key); + char *match = xasprintf("inport == %s && igmp && " + "flags.igmp_loopback == 0", op->json_key); ovn_lflow_metered(lflows, od, S_SWITCH_OUT_PRE_LB, 120, match, "clone { igmp; }; next;", copp_meter_get(COPP_IGMP, od->nbs->copp, @@ -6134,7 +6135,8 @@ build_interconn_mcast_snoop_flows(struct ovn_datapath *od, free(match); /* Punt MLD traffic to controller. */ - match = xasprintf("inport == %s && (mldv1 || mldv2)", op->json_key); + match = xasprintf("inport == %s && (mldv1 || mldv2) && " + "flags.igmp_loopback == 0", op->json_key); ovn_lflow_metered(lflows, od, S_SWITCH_OUT_PRE_LB, 120, match, "clone { igmp; }; next;", copp_meter_get(COPP_IGMP, od->nbs->copp, @@ -9994,14 +9996,15 @@ build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od, ds_put_cstr(actions, "igmp;"); /* Punt IGMP traffic to controller. */ ovn_lflow_metered(lflows, od, S_SWITCH_IN_L2_LKUP, 100, - "igmp", ds_cstr(actions), + "flags.igmp_loopback == 0 && igmp", ds_cstr(actions), copp_meter_get(COPP_IGMP, od->nbs->copp, meter_groups), lflow_ref); /* Punt MLD traffic to controller. */ ovn_lflow_metered(lflows, od, S_SWITCH_IN_L2_LKUP, 100, - "mldv1 || mldv2", ds_cstr(actions), + "flags.igmp_loopback == 0 && (mldv1 || mldv2)", + ds_cstr(actions), copp_meter_get(COPP_IGMP, od->nbs->copp, meter_groups), lflow_ref); diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at index c8276189c..401a71580 100644 --- a/tests/ovn-ic.at +++ b/tests/ovn-ic.at @@ -2043,6 +2043,10 @@ check ovs-vsctl -- add-port br-int hv2-vif2 \ -- set interface hv2-vif2 external-ids:iface-id=lsp3 \ options:tx_pcap=hv2/vif2-tx.pcap \ options:rxq_pcap=hv2/vif2-rx.pcap +check ovs-vsctl -- add-port br-int hv2-vif3 \ + -- set interface hv2-vif3 external-ids:iface-id=lsp4 \ + options:tx_pcap=hv2/vif3-tx.pcap \ + options:rxq_pcap=hv2/vif3-rx.pcap check ovs-vsctl set open . external-ids:ovn-is-interconn=true AT_CHECK([ovn-ic-nbctl --wait=sb create Transit_Switch name=ts], [0], [ignore]) @@ -2081,6 +2085,8 @@ check ovn-nbctl lsp-add ts ts-lr2 \ -- lsp-set-addresses ts-lr2 router \ -- lsp-set-type ts-lr2 router \ -- lsp-set-options ts-lr2 router-port=lr2-ts +check ovn-nbctl lsp-add ts lsp4 \ + -- lsp-set-addresses lsp4 unknown check ovn-nbctl lr-add lr3 \ -- lrp-add lr3 lr3-ts 00:00:00:02:00:02 42.42.42.3/24 4242::3/64 \ @@ -2165,6 +2171,18 @@ send_mld_v2_report hv2-vif2 hv2 \ ff0adeadbeef00000000000000000001 04 c0e4 \ /dev/null +# Inject IGMP Join for 239.0.1.68 on LSP4. +send_igmp_v3_report hv2-vif3 hv2 \ + 000000000001 $(ip_to_hex 10 0 0 42) f9cf \ + $(ip_to_hex 239 0 1 68) 04 e9b9 \ + /dev/null + +# Inject MLD Join for ff0a:dead:beef::1 on LSP3. +send_mld_v2_report hv2-vif3 hv2 \ + 000000000001 10000000000000000000000000000042 \ + ff0adeadbeef00000000000000000001 04 c0a3 \ + /dev/null + # Check that the IGMP and MLD groups are learned on both AZs (on the LS # and TS). ovn_as az1 @@ -2181,6 +2199,7 @@ check ovn-nbctl --wait=hv sync # to lsp1 and lsp3. > expected_az1 > expected_az2 +> expected_az2-lsp4 send_ip_multicast_pkt hv2-vif1 hv2 \ 000000000001 01005e000144 \ $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 20 7c6b 11 \ @@ -2193,6 +2212,10 @@ store_ip_multicast_pkt \ 000000020200 01005e000144 \ $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 1e 7e6b 11 \ e518e518000aed350000 expected_az2 +store_ip_multicast_pkt \ + 000000020001 01005e000144 \ + $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 1f 7d6b 11 \ + e518e518000aed350000 expected_az2-lsp4 send_ip6_multicast_pkt hv2-vif1 hv2 \ 000000000001 333300000001 \ @@ -2211,10 +2234,17 @@ store_ip6_multicast_pkt \ 000e 3e 11 \ 93407a69000e2b4e61736461640a \ expected_az2 +store_ip6_multicast_pkt \ + 000000020001 333300000001 \ + 00100000000000000000000000000042 ff0adeadbeef00000000000000000001 \ + 000e 3f 11 \ + 93407a69000e2b4e61736461640a \ + expected_az2-lsp4 OVS_WAIT_UNTIL( [check_packets 'hv1/vif1-tx.pcap expected_az1' \ - 'hv2/vif2-tx.pcap expected_az2'], + 'hv2/vif2-tx.pcap expected_az2' \ + 'hv2/vif3-tx.pcap expected_az2-lsp4'], [$at_diff -F'^---' exp rcv]) OVN_CLEANUP_SBOX([hv1], ["/IGMP Querier enabled without a valid IPv4/d -- 2.49.0 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev