Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
Post v26.09.09
--------------
- ovn-controller now injects locally generated IGMP/MLD membership
queries using the MC_FLOOD_L2 group (L2 ports only) instead of
MC_FLOOD. This matches snooped-query forwarding (RFC 4541) and
avoids exceeding the OVS 4096 resubmit limit when a logical switch
has many local ports or connected logical routers.
- Mark tunnel ports as transient (other_config:transient=true) when the
local chassis is a member of an HA chassis group.
Systems which invoke ovs-ctl --delete-transient-ports during OVS startup
Expand Down
17 changes: 12 additions & 5 deletions controller/pinctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,10 @@ VLOG_DEFINE_THIS_MODULE(pinctrl);
* contents and stores them in mcast_query_list.
*
* pinctrl_handler thread sends the periodic IGMP queries
* by walking the mcast_query_list.
* by walking the mcast_query_list. Locally generated
* queries are injected with outport MC_FLOOD_L2 so they
* stay in the L2 broadcast domain (RFC 4541) and are
* not flooded towards logical router ports.
*
* Notification between pinctrl_handler() and pinctrl_run()
* -------------------------------------------------------
Expand Down Expand Up @@ -6211,12 +6214,16 @@ ip_mcast_querier_send_igmp(struct rconn *swconn, struct ip_mcast_snoop *ip_ms)
uint8_t qqic = max_response;
packet_set_igmp3_query(&packet, max_response, 0, false, 0, qqic);

/* Inject multicast query. */
/* Inject multicast query. Use MC_FLOOD_L2 rather than MC_FLOOD so the
* query is not flooded to connected logical routers. Flooding to every
* local port (including router patch ports) can exceed the OVS 4096
* resubmit limit in scaled topologies. Snooped queries already use
* MC_FLOOD_L2 via ip_mcast_forward_query(). */
uint64_t ofpacts_stub[4096 / 8];
struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub);
enum ofp_version version = rconn_get_version(swconn);
put_load(ip_ms->dp_key, MFF_LOG_DATAPATH, 0, 64, &ofpacts);
put_load(OVN_MCAST_FLOOD_TUNNEL_KEY, MFF_LOG_OUTPORT, 0, 32, &ofpacts);
put_load(OVN_MCAST_FLOOD_L2_TUNNEL_KEY, MFF_LOG_OUTPORT, 0, 32, &ofpacts);
put_load(1, MFF_LOG_FLAGS, MLF_LOCAL_ONLY, 1, &ofpacts);
struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts);
resubmit->in_port = OFPP_CONTROLLER;
Expand Down Expand Up @@ -6261,12 +6268,12 @@ ip_mcast_querier_send_mld(struct rconn *swconn, struct ip_mcast_snoop *ip_ms)
struct in6_addr unspecified = { { { 0 } } };
packet_set_mld_query(&packet, max_response, &unspecified, false, 0, qqic);

/* Inject multicast query. */
/* Inject multicast query. See ip_mcast_querier_send_igmp(). */
uint64_t ofpacts_stub[4096 / 8];
struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub);
enum ofp_version version = rconn_get_version(swconn);
put_load(ip_ms->dp_key, MFF_LOG_DATAPATH, 0, 64, &ofpacts);
put_load(OVN_MCAST_FLOOD_TUNNEL_KEY, MFF_LOG_OUTPORT, 0, 32, &ofpacts);
put_load(OVN_MCAST_FLOOD_L2_TUNNEL_KEY, MFF_LOG_OUTPORT, 0, 32, &ofpacts);
put_load(1, MFF_LOG_FLAGS, MLF_LOCAL_ONLY, 1, &ofpacts);
struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts);
resubmit->in_port = OFPP_CONTROLLER;
Expand Down
26 changes: 22 additions & 4 deletions tests/ovn.at
Original file line number Diff line number Diff line change
Expand Up @@ -24633,8 +24633,11 @@ check ovn-nbctl set Logical_Switch sw2 \
other_config:mcast_ip4_src="20.0.0.254"

AS_BOX([IGMP traffic test 4])
# Check that multiple queries are generated over time.
# Check that multiple queries are generated over time and stay in the
# L2 domain (MC_FLOOD_L2): they must reach sw2 VIFs and must not be
# flooded towards the router onto sw1/sw3.
> expected
> expected_empty
store_igmp_v3_query 0000000002fe $(ip_to_hex 20 0 0 254) 84dd expected
store_igmp_v3_query 0000000002fe $(ip_to_hex 20 0 0 254) 84dd expected

Expand All @@ -24650,7 +24653,13 @@ for count in 1 2 3; do
OVS_WAIT_UNTIL(
[check_packets --uniq \
'hv1/vif3-tx.pcap expected' \
'hv2/vif3-tx.pcap expected'],
'hv2/vif3-tx.pcap expected' \
'hv1/vif1-tx.pcap expected_empty' \
'hv1/vif2-tx.pcap expected_empty' \
'hv1/vif4-tx.pcap expected_empty' \
'hv2/vif1-tx.pcap expected_empty' \
'hv2/vif2-tx.pcap expected_empty' \
'hv2/vif4-tx.pcap expected_empty'],
[$at_diff -F'^---' exp rcv])
done

Expand Down Expand Up @@ -25364,8 +25373,11 @@ check ovn-nbctl --wait=hv set Logical_Switch sw2 \
AT_CAPTURE_FILE([sbflows4])
ovn-sbctl dump-flows > sbflows4

# Check that multiple queries are generated over time.
# Check that multiple queries are generated over time and stay in the
# L2 domain (MC_FLOOD_L2): they must reach sw2 VIFs and must not be
# flooded towards the router onto sw1/sw3.
> expected
> expected_empty
store_mld_query 0000000002fe fe8000000000000000000000000000fe expected
store_mld_query 0000000002fe fe8000000000000000000000000000fe expected
for count in 1 2 3; do
Expand All @@ -25380,7 +25392,13 @@ for count in 1 2 3; do
OVS_WAIT_UNTIL(
[check_packets --uniq \
'hv1/vif3-tx.pcap expected' \
'hv2/vif3-tx.pcap expected'],
'hv2/vif3-tx.pcap expected' \
'hv1/vif1-tx.pcap expected_empty' \
'hv1/vif2-tx.pcap expected_empty' \
'hv1/vif4-tx.pcap expected_empty' \
'hv2/vif1-tx.pcap expected_empty' \
'hv2/vif2-tx.pcap expected_empty' \
'hv2/vif4-tx.pcap expected_empty'],
[$at_diff -F'^---' exp rcv])
done

Expand Down
Loading