On 3/14/25 11:02 AM, Ales Musil wrote:
> On Thu, Mar 13, 2025 at 9:33 AM Xavier Simonart <xsimo...@redhat.com> wrote:
> 
>> If we add a datapath local to the current hv to a load balancer which was
>> only added to
>> non local datapaths, then hairpin flows were missing.
>>
>> For instance, let's have sw0 and sw0p1 bound to hv0, and sw1 and sw1p1
>> bound to hv1
>> Let's also have a load balancer lb1 added to sw0.
>> When lb1 is added to sw1, hairpin flows were missing.
>>
>> Signed-off-by: Xavier Simonart <xsimo...@redhat.com>
>> ---
>>  controller/ovn-controller.c |  6 +--
>>  tests/ovn.at                | 86 +++++++++++++++++++++++++++++++++++++
>>  2 files changed, 88 insertions(+), 4 deletions(-)
>>
>> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
>> index c0f167c54..bc8acddf1 100644
>> --- a/controller/ovn-controller.c
>> +++ b/controller/ovn-controller.c
>> @@ -2861,11 +2861,9 @@ lb_data_sb_load_balancer_handler(struct engine_node
>> *node, void *data)
>>          if (!sbrec_load_balancer_is_new(sbrec_lb)) {
>>              lb = ovn_controller_lb_find(&lb_data->local_lbs,
>>                                          &sbrec_lb->header_.uuid);
>> -            if (!lb) {
>> -                continue;
>> +            if (lb) {
>> +                lb_data_local_lb_remove(lb_data, lb);
>>              }
>> -
>> -            lb_data_local_lb_remove(lb_data, lb);
>>          }
>>
>>          if (sbrec_load_balancer_is_deleted(sbrec_lb) ||
>> diff --git a/tests/ovn.at b/tests/ovn.at
>> index f9e1c96c9..f4abfb345 100644
>> --- a/tests/ovn.at
>> +++ b/tests/ovn.at
>> @@ -42164,3 +42164,89 @@ wait_row_count ACL_ID 0
>>
>>  AT_CLEANUP
>>  ])
>> +
>> +# Test when a load balancer is added to two logical switches
>> +# which are local to different hypervisors.
>> +OVN_FOR_EACH_NORTHD([
>> +AT_SETUP([Load balancer hairpin flows])
>> +AT_KEYWORDS([lb])
>> +ovn_start
>> +
>> +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=sw0-p1 \
>> +    options:tx_pcap=hv1/vif1-tx.pcap \
>> +    options:rxq_pcap=hv1/vif1-rx.pcap
>> +
>> +sim_add hv2
>> +as hv2
>> +ovs-vsctl add-br br-phys
>> +ovn_attach n1 br-phys 192.168.0.2
>> +ovs-vsctl -- add-port br-int hv2-vif1 -- \
>> +    set interface hv2-vif1 external-ids:iface-id=sw1-p1 \
>> +    options:tx_pcap=hv2/vif1-tx.pcap \
>> +    options:rxq_pcap=hv2/vif1-rx.pcap
>> +
>> +check ovn-nbctl ls-add sw0
>> +check ovn-nbctl ls-add sw1
>> +
>> +check ovn-nbctl lsp-add sw0 sw0-p1
>> +check ovn-nbctl lsp-set-addresses sw0-p1 "50:54:10:00:00:01 10.0.0.1"
>> +
>> +check ovn-nbctl lsp-add sw1 sw1-p1
>> +check ovn-nbctl lsp-set-addresses sw1-p1 "50:54:20:00:00:01 20.0.0.1"
>> +
>> +# Create a logical router and attach both logical switches.
>> +# Make the logical router a GW router.
>> +check ovn-nbctl lr-add lr0
>> +check ovn-nbctl set logical_router lr0 options:chassis=hv1
>> +check ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.254/24
>> +check ovn-nbctl lsp-add sw0 sw0-lr0
>> +check ovn-nbctl lsp-set-type sw0-lr0 router
>> +check ovn-nbctl lsp-set-addresses sw0-lr0 router
>> +check ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
>> +
>> +check ovn-nbctl lrp-add lr0 lr0-sw1 00:00:00:00:ff:02 20.0.0.254/24
>> +check ovn-nbctl lsp-add sw1 sw1-lr0
>> +check ovn-nbctl lsp-set-type sw1-lr0 router
>> +check ovn-nbctl lsp-set-addresses sw1-lr0 router
>> +check ovn-nbctl lsp-set-options sw1-lr0 router-port=lr0-sw1
>> +
>> +check ovn-nbctl lb-add lb1 10.0.0.10:80 20.0.0.1:80 udp
>> +check ovn-nbctl ls-lb-add sw0 lb1
>> +check ovn-nbctl ls-lb-add sw1 lb1
>> +
>> +OVN_POPULATE_ARP
>> +wait_for_ports_up
>> +check ovn-nbctl --wait=hv sync
>> +
>> +# Send a packet from the lb backend to the lb VIP (hairpin).
>> +src_mac="50:54:20:00:00:03"
>> +dst_mac="00:00:00:00:ff:02"
>> +src_ip="20.0.0.1"
>> +dst_ip="10.0.0.10"
>> +sport=4369
>> +dport=80
>> +
>> +packet=$(fmt_pkt "Ether(dst='${dst_mac}', src='${src_mac}')/
>> +                IP(dst='${dst_ip}', src='${src_ip}')/ \
>> +                UDP(sport=$sport, dport=$dport)")
>> +
>> +check as hv2 ovs-appctl netdev-dummy/receive hv2-vif1 $packet
>> +
>> +# Packet expected from the load balancer VIP.
>> +# It should have snatted the src_ip to the VIP of the LB.
>> +packet=$(fmt_pkt "Ether(dst='${src_mac}', src='${dst_mac}')/
>> +                      IP(dst='${src_ip}', src='${dst_ip}', ttl=64)/ \
>> +                      UDP(sport=$sport, dport=$dport)")
>> +echo $packet > expected
>> +OVN_CHECK_PACKETS_REMOVE_BROADCAST([hv2/vif1-tx.pcap], [expected])
>> +
>> +OVN_CLEANUP([hv1], [hv2])
>> +AT_CLEANUP
>> +])
>> --
>> 2.47.1
>>
>> _______________________________________________
>> dev mailing list
>> d...@openvswitch.org
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>
>>
> Looks good to me, thanks.
> Acked-by: Ales Musil <amu...@redhat.com>

Thanks, Xavier and Ales!  Applied to main, 25.03, 24.09 and 24.03.

Regards,
Dumitru

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to