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

Reply via email to