diff --git a/src/core/nm-firewall-utils.c b/src/core/nm-firewall-utils.c index 45dab09308..a88c6f1a75 100644 --- a/src/core/nm-firewall-utils.c +++ b/src/core/nm-firewall-utils.c @@ -844,6 +844,18 @@ nm_firewall_nft_stdio_mlag(gboolean up, chain_name, previous_member); _append(&strbuf, "delete chain netdev %s %s", table_name, chain_name); + + chain_name = + _strbuf_set_sanitized(&strbuf_1, "tx-redirect-igmp-reports-", previous_member); + + _append(&strbuf, + "add chain netdev %s %s {" + " type filter hook egress device %s priority filter + 1; " + "}", + table_name, + chain_name, + previous_member); + _append(&strbuf, "delete chain netdev %s %s", table_name, chain_name); } /* OVS SLB rule 1 @@ -940,6 +952,57 @@ nm_firewall_nft_stdio_mlag(gboolean up, "add rule netdev %s rx-drop-looped-packets ether saddr @macset-untagged%s drop", table_name, s_counter); + + /* IGMP SNOOPING + * + * This redirects all IGMP reports to the primary member port. The TOR switches + * may prune the multicast tree. If we let the bonding vlan+srcmac hash occur, + * then the TOR may send the pruned multicast stream to a bond member port for + * which the RX filters will drop (e.g. report out non-primary, stream in + * non-primary). If it's known multicast then we must control the pruned tree by + * only sending the IGMP reports on a port for which we will accept the traffic, + * i.e. the primary member port. + */ + for (i = 0; i < n_active_members; i++) { + const char *active_member = active_members[i]; + const char *chain_name; + + if (!_nft_ifname_valid(active_member)) + continue; + + chain_name = + _strbuf_set_sanitized(&strbuf_1, "tx-redirect-igmp-reports-", active_member); + + _append(&strbuf, + "add chain netdev %s %s {" + " type filter hook egress device %s priority filter + 1; " + "}", + table_name, + chain_name, + active_member); + /* first is primary, we clean up in case it was previously a non-primary member */ + if (i == 0) { + _append(&strbuf, "delete chain netdev %s %s", table_name, chain_name); + continue; + } + + _append(&strbuf, + "add rule netdev %s %s igmp type {" + " membership-report-v1, membership-report-v2, membership-report-v3 " + "}%s fwd to %s", + table_name, + chain_name, + s_counter, + active_members[0]); + _append(&strbuf, + "add rule netdev %s %s icmpv6 type {" + " mld-listener-report, mld2-listener-report " + "}%s fwd to %s", + table_name, + chain_name, + s_counter, + active_members[0]); + } } out: diff --git a/src/core/tests/test-core.c b/src/core/tests/test-core.c index c5a598a695..71a3d8783a 100644 --- a/src/core/tests/test-core.c +++ b/src/core/tests/test-core.c @@ -2671,8 +2671,10 @@ test_nm_firewall_nft_stdio_mlag(void) "nm-mlag-bond0\012flush table netdev nm-mlag-bond0\012add chain netdev nm-mlag-bond0 " "rx-drop-bc-mc-eth2 { type filter hook ingress device eth2 priority filter; }\012delete " "chain netdev nm-mlag-bond0 rx-drop-bc-mc-eth2\012add chain netdev nm-mlag-bond0 " - "rx-drop-bc-mc-eth1 { type filter hook ingress device eth1 priority filter; }\012delete " - "chain netdev nm-mlag-bond0 rx-drop-bc-mc-eth1\012add set netdev nm-mlag-bond0 " + "tx-redirect-igmp-reports-eth2 { type filter hook egress device eth2 priority filter + 1; " + "}\012delete chain netdev nm-mlag-bond0 tx-redirect-igmp-reports-eth2\012add chain netdev " + "nm-mlag-bond0 rx-drop-bc-mc-eth1 { type filter hook ingress device eth1 priority filter; " + "}\012delete chain netdev nm-mlag-bond0 rx-drop-bc-mc-eth1\012add set netdev nm-mlag-bond0 " "macset-tagged { typeof ether saddr . vlan id; flags dynamic,timeout; }\012add set netdev " "nm-mlag-bond0 macset-untagged { typeof ether saddr; flags dynamic,timeout; }\012add chain " "netdev nm-mlag-bond0 tx-snoop-source-mac { type filter hook egress device bond0 priority " @@ -2683,7 +2685,9 @@ test_nm_firewall_nft_stdio_mlag(void) "priority filter; }\012add rule netdev nm-mlag-bond0 rx-drop-looped-packets ether saddr . " "vlan id @macset-tagged counter drop\012add rule netdev nm-mlag-bond0 " "rx-drop-looped-packets ether type vlan counter return\012add rule netdev nm-mlag-bond0 " - "rx-drop-looped-packets ether saddr @macset-untagged counter drop\012"); + "rx-drop-looped-packets ether saddr @macset-untagged counter drop\012add chain netdev " + "nm-mlag-bond0 tx-redirect-igmp-reports-eth1 { type filter hook egress device eth1 priority " + "filter + 1; }\012delete chain netdev nm-mlag-bond0 tx-redirect-igmp-reports-eth1\012"); _T(TRUE, "bond0", @@ -2695,8 +2699,10 @@ test_nm_firewall_nft_stdio_mlag(void) "nm-mlag-bond0\012flush table netdev nm-mlag-bond0\012add chain netdev nm-mlag-bond0 " "rx-drop-bc-mc-eth2 { type filter hook ingress device eth2 priority filter; }\012delete " "chain netdev nm-mlag-bond0 rx-drop-bc-mc-eth2\012add chain netdev nm-mlag-bond0 " - "rx-drop-bc-mc-eth1 { type filter hook ingress device eth1 priority filter; }\012delete " - "chain netdev nm-mlag-bond0 rx-drop-bc-mc-eth1\012add set netdev nm-mlag-bond0 " + "tx-redirect-igmp-reports-eth2 { type filter hook egress device eth2 priority filter + 1; " + "}\012delete chain netdev nm-mlag-bond0 tx-redirect-igmp-reports-eth2\012add chain netdev " + "nm-mlag-bond0 rx-drop-bc-mc-eth1 { type filter hook ingress device eth1 priority filter; " + "}\012delete chain netdev nm-mlag-bond0 rx-drop-bc-mc-eth1\012add set netdev nm-mlag-bond0 " "macset-tagged { typeof ether saddr . vlan id; flags dynamic,timeout; }\012add set netdev " "nm-mlag-bond0 macset-untagged { typeof ether saddr; flags dynamic,timeout; }\012add chain " "netdev nm-mlag-bond0 tx-snoop-source-mac { type filter hook egress device bond0 priority " @@ -2707,7 +2713,9 @@ test_nm_firewall_nft_stdio_mlag(void) "filter; }\012add rule netdev nm-mlag-bond0 rx-drop-looped-packets ether saddr . vlan id " "@macset-tagged drop\012add rule netdev nm-mlag-bond0 rx-drop-looped-packets ether type " "vlan return\012add rule netdev nm-mlag-bond0 rx-drop-looped-packets ether saddr " - "@macset-untagged drop\012"); + "@macset-untagged drop\012add chain netdev nm-mlag-bond0 tx-redirect-igmp-reports-eth1 { " + "type filter hook egress device eth1 priority filter + 1; }\012delete chain netdev " + "nm-mlag-bond0 tx-redirect-igmp-reports-eth1\012"); _T(TRUE, "bond0", @@ -2720,23 +2728,35 @@ test_nm_firewall_nft_stdio_mlag(void) "nm-mlag-bond0\012flush table netdev nm-mlag-bond0\012add chain netdev nm-mlag-bond0 " "rx-drop-bc-mc-eth4 { type filter hook ingress device eth4 priority filter; }\012delete " "chain netdev nm-mlag-bond0 rx-drop-bc-mc-eth4\012add chain netdev nm-mlag-bond0 " - "rx-drop-bc-mc-eth5 { type filter hook ingress device eth5 priority filter; }\012delete " - "chain netdev nm-mlag-bond0 rx-drop-bc-mc-eth5\012add chain netdev nm-mlag-bond0 " - "rx-drop-bc-mc-eth2 { type filter hook ingress device eth2 priority filter; }\012delete " - "chain netdev nm-mlag-bond0 rx-drop-bc-mc-eth2\012add chain netdev nm-mlag-bond0 " - "rx-drop-bc-mc-eth3 { type filter hook ingress device eth3 priority filter; }\012add rule " - "netdev nm-mlag-bond0 rx-drop-bc-mc-eth3 pkttype { broadcast, multicast } drop\012add set " - "netdev nm-mlag-bond0 macset-tagged { typeof ether saddr . vlan id; flags dynamic,timeout; " - "}\012add set netdev nm-mlag-bond0 macset-untagged { typeof ether saddr; flags " - "dynamic,timeout; }\012add chain netdev nm-mlag-bond0 tx-snoop-source-mac { type filter " - "hook egress device bond0 priority filter; }\012add rule netdev nm-mlag-bond0 " - "tx-snoop-source-mac set update ether saddr . vlan id timeout 5s @macset-tagged " - "return\012add rule netdev nm-mlag-bond0 tx-snoop-source-mac set update ether saddr timeout " - "5s @macset-untagged\012add chain netdev nm-mlag-bond0 rx-drop-looped-packets { type filter " - "hook ingress device bond0 priority filter; }\012add rule netdev nm-mlag-bond0 " - "rx-drop-looped-packets ether saddr . vlan id @macset-tagged drop\012add rule netdev " - "nm-mlag-bond0 rx-drop-looped-packets ether type vlan return\012add rule netdev " - "nm-mlag-bond0 rx-drop-looped-packets ether saddr @macset-untagged drop\012"); + "tx-redirect-igmp-reports-eth4 { type filter hook egress device eth4 priority filter + 1; " + "}\012delete chain netdev nm-mlag-bond0 tx-redirect-igmp-reports-eth4\012add chain netdev " + "nm-mlag-bond0 rx-drop-bc-mc-eth5 { type filter hook ingress device eth5 priority filter; " + "}\012delete chain netdev nm-mlag-bond0 rx-drop-bc-mc-eth5\012add chain netdev " + "nm-mlag-bond0 tx-redirect-igmp-reports-eth5 { type filter hook egress device eth5 priority " + "filter + 1; }\012delete chain netdev nm-mlag-bond0 tx-redirect-igmp-reports-eth5\012add " + "chain netdev nm-mlag-bond0 rx-drop-bc-mc-eth2 { type filter hook ingress device eth2 " + "priority filter; }\012delete chain netdev nm-mlag-bond0 rx-drop-bc-mc-eth2\012add chain " + "netdev nm-mlag-bond0 rx-drop-bc-mc-eth3 { type filter hook ingress device eth3 priority " + "filter; }\012add rule netdev nm-mlag-bond0 rx-drop-bc-mc-eth3 pkttype { broadcast, " + "multicast } drop\012add set netdev nm-mlag-bond0 macset-tagged { typeof ether saddr . vlan " + "id; flags dynamic,timeout; }\012add set netdev nm-mlag-bond0 macset-untagged { typeof " + "ether saddr; flags dynamic,timeout; }\012add chain netdev nm-mlag-bond0 " + "tx-snoop-source-mac { type filter hook egress device bond0 priority filter; }\012add rule " + "netdev nm-mlag-bond0 tx-snoop-source-mac set update ether saddr . vlan id timeout 5s " + "@macset-tagged return\012add rule netdev nm-mlag-bond0 tx-snoop-source-mac set update " + "ether saddr timeout 5s @macset-untagged\012add chain netdev nm-mlag-bond0 " + "rx-drop-looped-packets { type filter hook ingress device bond0 priority filter; }\012add " + "rule netdev nm-mlag-bond0 rx-drop-looped-packets ether saddr . vlan id @macset-tagged " + "drop\012add rule netdev nm-mlag-bond0 rx-drop-looped-packets ether type vlan return\012add " + "rule netdev nm-mlag-bond0 rx-drop-looped-packets ether saddr @macset-untagged drop\012add " + "chain netdev nm-mlag-bond0 tx-redirect-igmp-reports-eth2 { type filter hook egress device " + "eth2 priority filter + 1; }\012delete chain netdev nm-mlag-bond0 " + "tx-redirect-igmp-reports-eth2\012add chain netdev nm-mlag-bond0 " + "tx-redirect-igmp-reports-eth3 { type filter hook egress device eth3 priority filter + 1; " + "}\012add rule netdev nm-mlag-bond0 tx-redirect-igmp-reports-eth3 igmp type { " + "membership-report-v1, membership-report-v2, membership-report-v3 } fwd to eth2\012add rule " + "netdev nm-mlag-bond0 tx-redirect-igmp-reports-eth3 icmpv6 type { mld-listener-report, " + "mld2-listener-report } fwd to eth2\012"); _T(FALSE, "bond0",