diff mbox series

[ovs-dev,ovn] ovn-controller: Fix the missing ct zone entries for container ports.

Message ID 20200717092141.1689895-1-numans@ovn.org
State Accepted
Headers show
Series [ovs-dev,ovn] ovn-controller: Fix the missing ct zone entries for container ports. | expand

Commit Message

Numan Siddique July 17, 2020, 9:21 a.m. UTC
From: Numan Siddique <numans@ovn.org>

After the commit in the Fixes tag, ovn-controller was not creating ct zone
entries for the container ports in the integration bridge's external_ids
column. Because of this, when a container port sends a traffic to
load balancer VIP, zone id is not used (because REG13 is not set).
But the reverse traffic doesn't go through the ct_lb action for undnat,
but instead go to the conntrack via the ct_commit() OVN action and the
packet gets dropped. This happens if an ACL with allow-related action
which matches in the egress pipeline of the logical switch.

This patch fixes this regression and the tests make sure the the ct zone
entries are created for the container ports.

Fixes: 6c8b9a132532("ovn-controller: Store the local port bindings in the runtime data I-P state.")
Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1857865
Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1858191
Signed-off-by: Numan Siddique <numans@ovn.org>
---
 controller/binding.c |  11 ++++
 tests/ovn.at         |  30 +++++++++++
 tests/system-ovn.at  | 118 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 159 insertions(+)

Comments

Dumitru Ceara July 17, 2020, 9:51 a.m. UTC | #1
On 7/17/20 11:21 AM, numans@ovn.org wrote:
> From: Numan Siddique <numans@ovn.org>
> 
> After the commit in the Fixes tag, ovn-controller was not creating ct zone
> entries for the container ports in the integration bridge's external_ids
> column. Because of this, when a container port sends a traffic to
> load balancer VIP, zone id is not used (because REG13 is not set).
> But the reverse traffic doesn't go through the ct_lb action for undnat,
> but instead go to the conntrack via the ct_commit() OVN action and the
> packet gets dropped. This happens if an ACL with allow-related action
> which matches in the egress pipeline of the logical switch.
> 
> This patch fixes this regression and the tests make sure the the ct zone
> entries are created for the container ports.
> 
> Fixes: 6c8b9a132532("ovn-controller: Store the local port bindings in the runtime data I-P state.")
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1857865
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1858191
> Signed-off-by: Numan Siddique <numans@ovn.org>
> ---
>  controller/binding.c |  11 ++++
>  tests/ovn.at         |  30 +++++++++++
>  tests/system-ovn.at  | 118 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 159 insertions(+)
> 
> diff --git a/controller/binding.c b/controller/binding.c
> index e630b60801..b73abb982c 100644
> --- a/controller/binding.c
> +++ b/controller/binding.c
> @@ -1011,6 +1011,7 @@ consider_vif_lport_(const struct sbrec_port_binding *pb,
>                                 b_ctx_out->local_datapaths,
>                                 b_ctx_out->tracked_dp_bindings);
>              update_local_lport_ids(pb, b_ctx_out);
> +            update_local_lports(pb->logical_port, b_ctx_out);
>              if (lbinding->iface && qos_map && b_ctx_in->ovs_idl_txn) {
>                  get_qos_params(pb, qos_map);
>              }
> @@ -1981,6 +1982,16 @@ handle_deleted_vif_lport(const struct sbrec_port_binding *pb,
>          }
>      }
>  
> +    /* If its a container lport, then delete its entry from local_lports
> +     * if present.
> +     * Note: If a normal lport is deleted, we don't want to remove
> +     * it from local_lports if there is a VIF entry.
> +     * consider_iface_release() takes care of removing from the local_lports
> +     * when the interface change happens. */
> +    if (is_lport_container(pb)) {
> +        remove_local_lports(pb->logical_port, b_ctx_out);
> +    }
> +
>      handle_deleted_lport(pb, b_ctx_in, b_ctx_out);
>      return true;
>  }
> diff --git a/tests/ovn.at b/tests/ovn.at
> index ba1a534e92..e19efafbe2 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -8785,6 +8785,36 @@ ip_to_hex() {
>      printf "%02x%02x%02x%02x" "$@"
>  }
>  
> +# Test that ovn-controllers create ct-zone entry for container ports.
> +foo1_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-foo1)
> +AT_CHECK([test ! -z $foo1_zoneid])
> +
> +bar1_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-bar1)
> +AT_CHECK([test ! -z $bar1_zoneid])
> +
> +bar3_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-bar3)
> +AT_CHECK([test ! -z $bar3_zoneid])
> +
> +foo2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-foo2)
> +AT_CHECK([test ! -z $foo2_zoneid])
> +
> +bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2)
> +AT_CHECK([test ! -z $bar2_zoneid])
> +
> +ovn-nbctl lsp-del bar2
> +ovn-nbctl --wait=hv sync
> +
> +bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2)
> +AT_CHECK([test  -z $bar2_zoneid])
> +
> +# Add back bar2
> +ovn-nbctl lsp-add bar bar2 vm2 1 \
> +-- lsp-set-addresses bar2 "f0:00:00:01:02:08 192.168.2.3"
> +ovn-nbctl --wait=hv sync
> +
> +bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2)
> +AT_CHECK([test ! -z $bar2_zoneid])
> +
>  # Send ip packets between foo1 and foo2 (same switch, different HVs and
>  # different VLAN tags).
>  src_mac="f00000010205"
> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> index 2999e52fde..77c92e86ec 100644
> --- a/tests/system-ovn.at
> +++ b/tests/system-ovn.at
> @@ -4365,3 +4365,121 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
>  /Service monitor not found.*/d"])
>  
>  AT_CLEANUP
> +
> +AT_SETUP([ovn -- Load balancer for container ports])
> +AT_SKIP_IF([test $HAVE_NC = no])
> +AT_KEYWORDS([lb])
> +
> +ovn_start
> +
> +OVS_TRAFFIC_VSWITCHD_START()
> +ADD_BR([br-int])
> +
> +# Set external-ids in br-int needed for ovn-controller
> +ovs-vsctl \
> +        -- set Open_vSwitch . external-ids:system-id=hv1 \
> +        -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
> +        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
> +        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
> +        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
> +
> +# Start ovn-controller
> +start_daemon ovn-controller
> +
> +ovn-nbctl ls-add sw0
> +ovn-nbctl lsp-add sw0 sw0-p1-lbc
> +ovn-nbctl lsp-set-addresses sw0-port1 "10:54:00:00:00:03 10.0.0.3"
> +
> +ovn-nbctl lsp-add sw0 sw0-p2-lbc
> +ovn-nbctl lsp-set-addresses sw0-port2 "10:54:00:00:00:04 10.0.0.4"
> +
> +ovn-nbctl ls-add sw1
> +ovn-nbctl lsp-add sw1 sw1-port1 sw0-p1-lbc 10
> +ovn-nbctl lsp-set-addresses sw1-port1 "40:54:00:00:00:03 20.0.0.3"
> +
> +ovn-nbctl lsp-add sw1 sw1-port2 sw0-p2-lbc 20
> +ovn-nbctl lsp-set-addresses sw1-port2 "40:54:00:00:00:04 20.0.0.4"
> +
> +
> +ovn-nbctl lr-add lr0
> +ovn-nbctl lrp-add lr0 lr0-sw1 00:00:00:00:ff:02 20.0.0.1/24
> +ovn-nbctl lsp-add sw1 sw1-lr0
> +ovn-nbctl lsp-set-type sw1-lr0 router
> +ovn-nbctl lsp-set-addresses sw1-lr0 router
> +ovn-nbctl lsp-set-options sw1-lr0 router-port=lr0-sw1
> +
> +
> +ovn-nbctl ls-add sw2
> +ovn-nbctl lsp-add sw2 sw2-port1
> +ovn-nbctl lsp-set-addresses sw2-port1 "50:54:00:00:00:03 30.0.0.3"
> +
> +ovn-nbctl lrp-add lr0 lr0-sw2 00:00:00:00:ff:03 30.0.0.1/24
> +ovn-nbctl lsp-add sw2 sw2-lr0
> +ovn-nbctl lsp-set-type sw2-lr0 router
> +ovn-nbctl lsp-set-addresses sw2-lr0 router
> +ovn-nbctl lsp-set-options sw2-lr0 router-port=lr0-sw2
> +
> +
> +ovn-nbctl lb-add lb0 "30.0.0.10:80" "20.0.0.4:80"
> +
> +ovn-nbctl ls-lb-add sw1 lb0
> +ovn-nbctl ls-lb-add sw2 lb0
> +ovn-nbctl lr-lb-add lr0 lb0
> +
> +ADD_NAMESPACES(sw0-p1-lbc)
> +ADD_VETH(sw0-p1-lbc, sw0-p1-lbc, br-int, "10.0.0.3/24", "10:54:00:00:00:03", \
> +         "10.0.0.1")
> +
> +ADD_NAMESPACES(sw0-p2-lbc)
> +ADD_VETH(sw0-p2-lbc, sw0-p2-lbc, br-int, "10.0.0.4/24", "10:54:00:00:00:04", \
> +         "10.0.0.1")
> +
> +# Create the interface for lport sw1-port1
> +NS_CHECK_EXEC([sw0-p1-lbc], [ip link add link sw0-p1-lbc name sw1p1 type vlan id 10], [0])
> +NS_CHECK_EXEC([sw0-p1-lbc], [ip link set sw1p1 address 40:54:00:00:00:03], [0])
> +NS_CHECK_EXEC([sw0-p1-lbc], [ip link set sw1p1 up], [0])
> +NS_CHECK_EXEC([sw0-p1-lbc], [ip addr add 20.0.0.3/24 dev sw1p1], [0])
> +NS_CHECK_EXEC([sw0-p1-lbc], [ip route delete default via 10.0.0.1 dev sw0-p1-lbc], [0])
> +NS_CHECK_EXEC([sw0-p1-lbc], [ip route add default via 20.0.0.1 dev sw1p1], [0])
> +
> +# Create the interface for lport sw1-port2
> +NS_CHECK_EXEC([sw0-p2-lbc], [ip link add link sw0-p2-lbc name sw1p2 type vlan id 20], [0])
> +NS_CHECK_EXEC([sw0-p2-lbc], [ip link set sw1p2 address 40:54:00:00:00:04], [0])
> +NS_CHECK_EXEC([sw0-p2-lbc], [ip link set sw1p2 up], [0])
> +NS_CHECK_EXEC([sw0-p2-lbc], [ip addr add 20.0.0.4/24 dev sw1p2], [0])
> +NS_CHECK_EXEC([sw0-p2-lbc], [ip route delete default via 10.0.0.1 dev sw0-p2-lbc], [0])
> +NS_CHECK_EXEC([sw0-p2-lbc], [ip route add default via 20.0.0.1 dev sw1p2], [0])
> +
> +# Start nc server on sw1p2 (sw0-p2-lbc is the parent)
> +NS_CHECK_EXEC([sw0-p2-lbc], [nc -l 20.0.0.4 80 -k &], [0])

This will leave nc running after the test has ended. I think we need
something like:

NS_CHECK_EXEC([sw0-p2-lbc], [timeout 2s nc -l 20.0.0.4 80 -k &], [0])

With this addressed, the rest looks good to me, thanks!

Acked-by: Dumitru Ceara <dceara@redhat.com>

Regards,
Dumitru

> +
> +# Send the packet to backend
> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 20.0.0.4 80], [0])
> +
> +# Send the packet to VIP.
> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 30.0.0.10 80], [0])
> +
> +# Now add an ACL in sw1.
> +ovn-nbctl --wait=hv acl-add sw1 to-lport 2002 "ip" allow-related
> +# Send the packet to backend
> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 20.0.0.4 80], [0])
> +
> +# Send the packet to VIP.
> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 30.0.0.10 80], [0])
> +
> +OVS_APP_EXIT_AND_WAIT([ovn-controller])
> +
> +as ovn-sb
> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> +
> +as ovn-nb
> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> +
> +as northd
> +OVS_APP_EXIT_AND_WAIT([ovn-northd])
> +
> +as
> +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
> +/connection dropped.*/d"])
> +
> +AT_CLEANUP
>
Mark Michelson July 17, 2020, 1:24 p.m. UTC | #2
On 7/17/20 5:51 AM, Dumitru Ceara wrote:
> On 7/17/20 11:21 AM, numans@ovn.org wrote:
>> From: Numan Siddique <numans@ovn.org>
>>
>> After the commit in the Fixes tag, ovn-controller was not creating ct zone
>> entries for the container ports in the integration bridge's external_ids
>> column. Because of this, when a container port sends a traffic to
>> load balancer VIP, zone id is not used (because REG13 is not set).
>> But the reverse traffic doesn't go through the ct_lb action for undnat,
>> but instead go to the conntrack via the ct_commit() OVN action and the
>> packet gets dropped. This happens if an ACL with allow-related action
>> which matches in the egress pipeline of the logical switch.
>>
>> This patch fixes this regression and the tests make sure the the ct zone
>> entries are created for the container ports.
>>
>> Fixes: 6c8b9a132532("ovn-controller: Store the local port bindings in the runtime data I-P state.")
>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1857865
>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1858191
>> Signed-off-by: Numan Siddique <numans@ovn.org>
>> ---
>>   controller/binding.c |  11 ++++
>>   tests/ovn.at         |  30 +++++++++++
>>   tests/system-ovn.at  | 118 +++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 159 insertions(+)
>>
>> diff --git a/controller/binding.c b/controller/binding.c
>> index e630b60801..b73abb982c 100644
>> --- a/controller/binding.c
>> +++ b/controller/binding.c
>> @@ -1011,6 +1011,7 @@ consider_vif_lport_(const struct sbrec_port_binding *pb,
>>                                  b_ctx_out->local_datapaths,
>>                                  b_ctx_out->tracked_dp_bindings);
>>               update_local_lport_ids(pb, b_ctx_out);
>> +            update_local_lports(pb->logical_port, b_ctx_out);
>>               if (lbinding->iface && qos_map && b_ctx_in->ovs_idl_txn) {
>>                   get_qos_params(pb, qos_map);
>>               }
>> @@ -1981,6 +1982,16 @@ handle_deleted_vif_lport(const struct sbrec_port_binding *pb,
>>           }
>>       }
>>   
>> +    /* If its a container lport, then delete its entry from local_lports
>> +     * if present.
>> +     * Note: If a normal lport is deleted, we don't want to remove
>> +     * it from local_lports if there is a VIF entry.
>> +     * consider_iface_release() takes care of removing from the local_lports
>> +     * when the interface change happens. */
>> +    if (is_lport_container(pb)) {
>> +        remove_local_lports(pb->logical_port, b_ctx_out);
>> +    }
>> +
>>       handle_deleted_lport(pb, b_ctx_in, b_ctx_out);
>>       return true;
>>   }
>> diff --git a/tests/ovn.at b/tests/ovn.at
>> index ba1a534e92..e19efafbe2 100644
>> --- a/tests/ovn.at
>> +++ b/tests/ovn.at
>> @@ -8785,6 +8785,36 @@ ip_to_hex() {
>>       printf "%02x%02x%02x%02x" "$@"
>>   }
>>   
>> +# Test that ovn-controllers create ct-zone entry for container ports.
>> +foo1_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-foo1)
>> +AT_CHECK([test ! -z $foo1_zoneid])
>> +
>> +bar1_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-bar1)
>> +AT_CHECK([test ! -z $bar1_zoneid])
>> +
>> +bar3_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-bar3)
>> +AT_CHECK([test ! -z $bar3_zoneid])
>> +
>> +foo2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-foo2)
>> +AT_CHECK([test ! -z $foo2_zoneid])
>> +
>> +bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2)
>> +AT_CHECK([test ! -z $bar2_zoneid])
>> +
>> +ovn-nbctl lsp-del bar2
>> +ovn-nbctl --wait=hv sync
>> +
>> +bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2)
>> +AT_CHECK([test  -z $bar2_zoneid])
>> +
>> +# Add back bar2
>> +ovn-nbctl lsp-add bar bar2 vm2 1 \
>> +-- lsp-set-addresses bar2 "f0:00:00:01:02:08 192.168.2.3"
>> +ovn-nbctl --wait=hv sync
>> +
>> +bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2)
>> +AT_CHECK([test ! -z $bar2_zoneid])
>> +
>>   # Send ip packets between foo1 and foo2 (same switch, different HVs and
>>   # different VLAN tags).
>>   src_mac="f00000010205"
>> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
>> index 2999e52fde..77c92e86ec 100644
>> --- a/tests/system-ovn.at
>> +++ b/tests/system-ovn.at
>> @@ -4365,3 +4365,121 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
>>   /Service monitor not found.*/d"])
>>   
>>   AT_CLEANUP
>> +
>> +AT_SETUP([ovn -- Load balancer for container ports])
>> +AT_SKIP_IF([test $HAVE_NC = no])
>> +AT_KEYWORDS([lb])
>> +
>> +ovn_start
>> +
>> +OVS_TRAFFIC_VSWITCHD_START()
>> +ADD_BR([br-int])
>> +
>> +# Set external-ids in br-int needed for ovn-controller
>> +ovs-vsctl \
>> +        -- set Open_vSwitch . external-ids:system-id=hv1 \
>> +        -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
>> +        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
>> +        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
>> +        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
>> +
>> +# Start ovn-controller
>> +start_daemon ovn-controller
>> +
>> +ovn-nbctl ls-add sw0
>> +ovn-nbctl lsp-add sw0 sw0-p1-lbc
>> +ovn-nbctl lsp-set-addresses sw0-port1 "10:54:00:00:00:03 10.0.0.3"
>> +
>> +ovn-nbctl lsp-add sw0 sw0-p2-lbc
>> +ovn-nbctl lsp-set-addresses sw0-port2 "10:54:00:00:00:04 10.0.0.4"
>> +
>> +ovn-nbctl ls-add sw1
>> +ovn-nbctl lsp-add sw1 sw1-port1 sw0-p1-lbc 10
>> +ovn-nbctl lsp-set-addresses sw1-port1 "40:54:00:00:00:03 20.0.0.3"
>> +
>> +ovn-nbctl lsp-add sw1 sw1-port2 sw0-p2-lbc 20
>> +ovn-nbctl lsp-set-addresses sw1-port2 "40:54:00:00:00:04 20.0.0.4"
>> +
>> +
>> +ovn-nbctl lr-add lr0
>> +ovn-nbctl lrp-add lr0 lr0-sw1 00:00:00:00:ff:02 20.0.0.1/24
>> +ovn-nbctl lsp-add sw1 sw1-lr0
>> +ovn-nbctl lsp-set-type sw1-lr0 router
>> +ovn-nbctl lsp-set-addresses sw1-lr0 router
>> +ovn-nbctl lsp-set-options sw1-lr0 router-port=lr0-sw1
>> +
>> +
>> +ovn-nbctl ls-add sw2
>> +ovn-nbctl lsp-add sw2 sw2-port1
>> +ovn-nbctl lsp-set-addresses sw2-port1 "50:54:00:00:00:03 30.0.0.3"
>> +
>> +ovn-nbctl lrp-add lr0 lr0-sw2 00:00:00:00:ff:03 30.0.0.1/24
>> +ovn-nbctl lsp-add sw2 sw2-lr0
>> +ovn-nbctl lsp-set-type sw2-lr0 router
>> +ovn-nbctl lsp-set-addresses sw2-lr0 router
>> +ovn-nbctl lsp-set-options sw2-lr0 router-port=lr0-sw2
>> +
>> +
>> +ovn-nbctl lb-add lb0 "30.0.0.10:80" "20.0.0.4:80"
>> +
>> +ovn-nbctl ls-lb-add sw1 lb0
>> +ovn-nbctl ls-lb-add sw2 lb0
>> +ovn-nbctl lr-lb-add lr0 lb0
>> +
>> +ADD_NAMESPACES(sw0-p1-lbc)
>> +ADD_VETH(sw0-p1-lbc, sw0-p1-lbc, br-int, "10.0.0.3/24", "10:54:00:00:00:03", \
>> +         "10.0.0.1")
>> +
>> +ADD_NAMESPACES(sw0-p2-lbc)
>> +ADD_VETH(sw0-p2-lbc, sw0-p2-lbc, br-int, "10.0.0.4/24", "10:54:00:00:00:04", \
>> +         "10.0.0.1")
>> +
>> +# Create the interface for lport sw1-port1
>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip link add link sw0-p1-lbc name sw1p1 type vlan id 10], [0])
>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip link set sw1p1 address 40:54:00:00:00:03], [0])
>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip link set sw1p1 up], [0])
>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip addr add 20.0.0.3/24 dev sw1p1], [0])
>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip route delete default via 10.0.0.1 dev sw0-p1-lbc], [0])
>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip route add default via 20.0.0.1 dev sw1p1], [0])
>> +
>> +# Create the interface for lport sw1-port2
>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip link add link sw0-p2-lbc name sw1p2 type vlan id 20], [0])
>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip link set sw1p2 address 40:54:00:00:00:04], [0])
>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip link set sw1p2 up], [0])
>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip addr add 20.0.0.4/24 dev sw1p2], [0])
>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip route delete default via 10.0.0.1 dev sw0-p2-lbc], [0])
>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip route add default via 20.0.0.1 dev sw1p2], [0])
>> +
>> +# Start nc server on sw1p2 (sw0-p2-lbc is the parent)
>> +NS_CHECK_EXEC([sw0-p2-lbc], [nc -l 20.0.0.4 80 -k &], [0])
> 
> This will leave nc running after the test has ended. I think we need
> something like:
> 
> NS_CHECK_EXEC([sw0-p2-lbc], [timeout 2s nc -l 20.0.0.4 80 -k &], [0])
> 
> With this addressed, the rest looks good to me, thanks!
> 
> Acked-by: Dumitru Ceara <dceara@redhat.com>
> 
> Regards,
> Dumitru

An alternate plan would be to use the NETNS_DAEMONIZE method to start 
the nc listener. This way, it will automatically be cleaned up when the 
test concludes.

An alternate alternate plan would be to use the on_exit() function to 
add a cleanup command yourself.

An alternate alternate alternate plan would be to use OVS_START_L7 to 
start an HTTP server, and then use `wget -q` instead of `nc -z` . This 
would save you the overhead of pidfile management, but would make the 
test more heavyweight.

> 
>> +
>> +# Send the packet to backend
>> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 20.0.0.4 80], [0])
>> +
>> +# Send the packet to VIP.
>> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 30.0.0.10 80], [0])
>> +
>> +# Now add an ACL in sw1.
>> +ovn-nbctl --wait=hv acl-add sw1 to-lport 2002 "ip" allow-related
>> +# Send the packet to backend
>> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 20.0.0.4 80], [0])
>> +
>> +# Send the packet to VIP.
>> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 30.0.0.10 80], [0])
>> +
>> +OVS_APP_EXIT_AND_WAIT([ovn-controller])
>> +
>> +as ovn-sb
>> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>> +
>> +as ovn-nb
>> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>> +
>> +as northd
>> +OVS_APP_EXIT_AND_WAIT([ovn-northd])
>> +
>> +as
>> +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
>> +/connection dropped.*/d"])
>> +
>> +AT_CLEANUP
>>
> 
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
Numan Siddique July 17, 2020, 1:29 p.m. UTC | #3
On Fri, Jul 17, 2020 at 6:55 PM Mark Michelson <mmichels@redhat.com> wrote:
>
> On 7/17/20 5:51 AM, Dumitru Ceara wrote:
> > On 7/17/20 11:21 AM, numans@ovn.org wrote:
> >> From: Numan Siddique <numans@ovn.org>
> >>
> >> After the commit in the Fixes tag, ovn-controller was not creating ct zone
> >> entries for the container ports in the integration bridge's external_ids
> >> column. Because of this, when a container port sends a traffic to
> >> load balancer VIP, zone id is not used (because REG13 is not set).
> >> But the reverse traffic doesn't go through the ct_lb action for undnat,
> >> but instead go to the conntrack via the ct_commit() OVN action and the
> >> packet gets dropped. This happens if an ACL with allow-related action
> >> which matches in the egress pipeline of the logical switch.
> >>
> >> This patch fixes this regression and the tests make sure the the ct zone
> >> entries are created for the container ports.
> >>
> >> Fixes: 6c8b9a132532("ovn-controller: Store the local port bindings in the runtime data I-P state.")
> >> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1857865
> >> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1858191
> >> Signed-off-by: Numan Siddique <numans@ovn.org>
> >> ---
> >>   controller/binding.c |  11 ++++
> >>   tests/ovn.at         |  30 +++++++++++
> >>   tests/system-ovn.at  | 118 +++++++++++++++++++++++++++++++++++++++++++
> >>   3 files changed, 159 insertions(+)
> >>
> >> diff --git a/controller/binding.c b/controller/binding.c
> >> index e630b60801..b73abb982c 100644
> >> --- a/controller/binding.c
> >> +++ b/controller/binding.c
> >> @@ -1011,6 +1011,7 @@ consider_vif_lport_(const struct sbrec_port_binding *pb,
> >>                                  b_ctx_out->local_datapaths,
> >>                                  b_ctx_out->tracked_dp_bindings);
> >>               update_local_lport_ids(pb, b_ctx_out);
> >> +            update_local_lports(pb->logical_port, b_ctx_out);
> >>               if (lbinding->iface && qos_map && b_ctx_in->ovs_idl_txn) {
> >>                   get_qos_params(pb, qos_map);
> >>               }
> >> @@ -1981,6 +1982,16 @@ handle_deleted_vif_lport(const struct sbrec_port_binding *pb,
> >>           }
> >>       }
> >>
> >> +    /* If its a container lport, then delete its entry from local_lports
> >> +     * if present.
> >> +     * Note: If a normal lport is deleted, we don't want to remove
> >> +     * it from local_lports if there is a VIF entry.
> >> +     * consider_iface_release() takes care of removing from the local_lports
> >> +     * when the interface change happens. */
> >> +    if (is_lport_container(pb)) {
> >> +        remove_local_lports(pb->logical_port, b_ctx_out);
> >> +    }
> >> +
> >>       handle_deleted_lport(pb, b_ctx_in, b_ctx_out);
> >>       return true;
> >>   }
> >> diff --git a/tests/ovn.at b/tests/ovn.at
> >> index ba1a534e92..e19efafbe2 100644
> >> --- a/tests/ovn.at
> >> +++ b/tests/ovn.at
> >> @@ -8785,6 +8785,36 @@ ip_to_hex() {
> >>       printf "%02x%02x%02x%02x" "$@"
> >>   }
> >>
> >> +# Test that ovn-controllers create ct-zone entry for container ports.
> >> +foo1_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-foo1)
> >> +AT_CHECK([test ! -z $foo1_zoneid])
> >> +
> >> +bar1_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-bar1)
> >> +AT_CHECK([test ! -z $bar1_zoneid])
> >> +
> >> +bar3_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-bar3)
> >> +AT_CHECK([test ! -z $bar3_zoneid])
> >> +
> >> +foo2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-foo2)
> >> +AT_CHECK([test ! -z $foo2_zoneid])
> >> +
> >> +bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2)
> >> +AT_CHECK([test ! -z $bar2_zoneid])
> >> +
> >> +ovn-nbctl lsp-del bar2
> >> +ovn-nbctl --wait=hv sync
> >> +
> >> +bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2)
> >> +AT_CHECK([test  -z $bar2_zoneid])
> >> +
> >> +# Add back bar2
> >> +ovn-nbctl lsp-add bar bar2 vm2 1 \
> >> +-- lsp-set-addresses bar2 "f0:00:00:01:02:08 192.168.2.3"
> >> +ovn-nbctl --wait=hv sync
> >> +
> >> +bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2)
> >> +AT_CHECK([test ! -z $bar2_zoneid])
> >> +
> >>   # Send ip packets between foo1 and foo2 (same switch, different HVs and
> >>   # different VLAN tags).
> >>   src_mac="f00000010205"
> >> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> >> index 2999e52fde..77c92e86ec 100644
> >> --- a/tests/system-ovn.at
> >> +++ b/tests/system-ovn.at
> >> @@ -4365,3 +4365,121 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
> >>   /Service monitor not found.*/d"])
> >>
> >>   AT_CLEANUP
> >> +
> >> +AT_SETUP([ovn -- Load balancer for container ports])
> >> +AT_SKIP_IF([test $HAVE_NC = no])
> >> +AT_KEYWORDS([lb])
> >> +
> >> +ovn_start
> >> +
> >> +OVS_TRAFFIC_VSWITCHD_START()
> >> +ADD_BR([br-int])
> >> +
> >> +# Set external-ids in br-int needed for ovn-controller
> >> +ovs-vsctl \
> >> +        -- set Open_vSwitch . external-ids:system-id=hv1 \
> >> +        -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
> >> +        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
> >> +        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
> >> +        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
> >> +
> >> +# Start ovn-controller
> >> +start_daemon ovn-controller
> >> +
> >> +ovn-nbctl ls-add sw0
> >> +ovn-nbctl lsp-add sw0 sw0-p1-lbc
> >> +ovn-nbctl lsp-set-addresses sw0-port1 "10:54:00:00:00:03 10.0.0.3"
> >> +
> >> +ovn-nbctl lsp-add sw0 sw0-p2-lbc
> >> +ovn-nbctl lsp-set-addresses sw0-port2 "10:54:00:00:00:04 10.0.0.4"
> >> +
> >> +ovn-nbctl ls-add sw1
> >> +ovn-nbctl lsp-add sw1 sw1-port1 sw0-p1-lbc 10
> >> +ovn-nbctl lsp-set-addresses sw1-port1 "40:54:00:00:00:03 20.0.0.3"
> >> +
> >> +ovn-nbctl lsp-add sw1 sw1-port2 sw0-p2-lbc 20
> >> +ovn-nbctl lsp-set-addresses sw1-port2 "40:54:00:00:00:04 20.0.0.4"
> >> +
> >> +
> >> +ovn-nbctl lr-add lr0
> >> +ovn-nbctl lrp-add lr0 lr0-sw1 00:00:00:00:ff:02 20.0.0.1/24
> >> +ovn-nbctl lsp-add sw1 sw1-lr0
> >> +ovn-nbctl lsp-set-type sw1-lr0 router
> >> +ovn-nbctl lsp-set-addresses sw1-lr0 router
> >> +ovn-nbctl lsp-set-options sw1-lr0 router-port=lr0-sw1
> >> +
> >> +
> >> +ovn-nbctl ls-add sw2
> >> +ovn-nbctl lsp-add sw2 sw2-port1
> >> +ovn-nbctl lsp-set-addresses sw2-port1 "50:54:00:00:00:03 30.0.0.3"
> >> +
> >> +ovn-nbctl lrp-add lr0 lr0-sw2 00:00:00:00:ff:03 30.0.0.1/24
> >> +ovn-nbctl lsp-add sw2 sw2-lr0
> >> +ovn-nbctl lsp-set-type sw2-lr0 router
> >> +ovn-nbctl lsp-set-addresses sw2-lr0 router
> >> +ovn-nbctl lsp-set-options sw2-lr0 router-port=lr0-sw2
> >> +
> >> +
> >> +ovn-nbctl lb-add lb0 "30.0.0.10:80" "20.0.0.4:80"
> >> +
> >> +ovn-nbctl ls-lb-add sw1 lb0
> >> +ovn-nbctl ls-lb-add sw2 lb0
> >> +ovn-nbctl lr-lb-add lr0 lb0
> >> +
> >> +ADD_NAMESPACES(sw0-p1-lbc)
> >> +ADD_VETH(sw0-p1-lbc, sw0-p1-lbc, br-int, "10.0.0.3/24", "10:54:00:00:00:03", \
> >> +         "10.0.0.1")
> >> +
> >> +ADD_NAMESPACES(sw0-p2-lbc)
> >> +ADD_VETH(sw0-p2-lbc, sw0-p2-lbc, br-int, "10.0.0.4/24", "10:54:00:00:00:04", \
> >> +         "10.0.0.1")
> >> +
> >> +# Create the interface for lport sw1-port1
> >> +NS_CHECK_EXEC([sw0-p1-lbc], [ip link add link sw0-p1-lbc name sw1p1 type vlan id 10], [0])
> >> +NS_CHECK_EXEC([sw0-p1-lbc], [ip link set sw1p1 address 40:54:00:00:00:03], [0])
> >> +NS_CHECK_EXEC([sw0-p1-lbc], [ip link set sw1p1 up], [0])
> >> +NS_CHECK_EXEC([sw0-p1-lbc], [ip addr add 20.0.0.3/24 dev sw1p1], [0])
> >> +NS_CHECK_EXEC([sw0-p1-lbc], [ip route delete default via 10.0.0.1 dev sw0-p1-lbc], [0])
> >> +NS_CHECK_EXEC([sw0-p1-lbc], [ip route add default via 20.0.0.1 dev sw1p1], [0])
> >> +
> >> +# Create the interface for lport sw1-port2
> >> +NS_CHECK_EXEC([sw0-p2-lbc], [ip link add link sw0-p2-lbc name sw1p2 type vlan id 20], [0])
> >> +NS_CHECK_EXEC([sw0-p2-lbc], [ip link set sw1p2 address 40:54:00:00:00:04], [0])
> >> +NS_CHECK_EXEC([sw0-p2-lbc], [ip link set sw1p2 up], [0])
> >> +NS_CHECK_EXEC([sw0-p2-lbc], [ip addr add 20.0.0.4/24 dev sw1p2], [0])
> >> +NS_CHECK_EXEC([sw0-p2-lbc], [ip route delete default via 10.0.0.1 dev sw0-p2-lbc], [0])
> >> +NS_CHECK_EXEC([sw0-p2-lbc], [ip route add default via 20.0.0.1 dev sw1p2], [0])
> >> +
> >> +# Start nc server on sw1p2 (sw0-p2-lbc is the parent)
> >> +NS_CHECK_EXEC([sw0-p2-lbc], [nc -l 20.0.0.4 80 -k &], [0])
> >
> > This will leave nc running after the test has ended. I think we need
> > something like:
> >
> > NS_CHECK_EXEC([sw0-p2-lbc], [timeout 2s nc -l 20.0.0.4 80 -k &], [0])
> >
> > With this addressed, the rest looks good to me, thanks!
> >
> > Acked-by: Dumitru Ceara <dceara@redhat.com>
> >
> > Regards,
> > Dumitru
>
> An alternate plan would be to use the NETNS_DAEMONIZE method to start
> the nc listener. This way, it will automatically be cleaned up when the
> test concludes.
>

I like this one. Thanks. I'll test it out locally.

Thanks
Numan



> An alternate alternate plan would be to use the on_exit() function to
> add a cleanup command yourself.
>
> An alternate alternate alternate plan would be to use OVS_START_L7 to
> start an HTTP server, and then use `wget -q` instead of `nc -z` . This
> would save you the overhead of pidfile management, but would make the
> test more heavyweight.
>
> >
> >> +
> >> +# Send the packet to backend
> >> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 20.0.0.4 80], [0])
> >> +
> >> +# Send the packet to VIP.
> >> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 30.0.0.10 80], [0])
> >> +
> >> +# Now add an ACL in sw1.
> >> +ovn-nbctl --wait=hv acl-add sw1 to-lport 2002 "ip" allow-related
> >> +# Send the packet to backend
> >> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 20.0.0.4 80], [0])
> >> +
> >> +# Send the packet to VIP.
> >> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 30.0.0.10 80], [0])
> >> +
> >> +OVS_APP_EXIT_AND_WAIT([ovn-controller])
> >> +
> >> +as ovn-sb
> >> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> >> +
> >> +as ovn-nb
> >> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> >> +
> >> +as northd
> >> +OVS_APP_EXIT_AND_WAIT([ovn-northd])
> >> +
> >> +as
> >> +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
> >> +/connection dropped.*/d"])
> >> +
> >> +AT_CLEANUP
> >>
> >
> > _______________________________________________
> > dev mailing list
> > dev@openvswitch.org
> > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> >
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
Dumitru Ceara July 17, 2020, 1:34 p.m. UTC | #4
On 7/17/20 3:29 PM, Numan Siddique wrote:
> On Fri, Jul 17, 2020 at 6:55 PM Mark Michelson <mmichels@redhat.com> wrote:
>>
>> On 7/17/20 5:51 AM, Dumitru Ceara wrote:
>>> On 7/17/20 11:21 AM, numans@ovn.org wrote:
>>>> From: Numan Siddique <numans@ovn.org>
>>>>
>>>> After the commit in the Fixes tag, ovn-controller was not creating ct zone
>>>> entries for the container ports in the integration bridge's external_ids
>>>> column. Because of this, when a container port sends a traffic to
>>>> load balancer VIP, zone id is not used (because REG13 is not set).
>>>> But the reverse traffic doesn't go through the ct_lb action for undnat,
>>>> but instead go to the conntrack via the ct_commit() OVN action and the
>>>> packet gets dropped. This happens if an ACL with allow-related action
>>>> which matches in the egress pipeline of the logical switch.
>>>>
>>>> This patch fixes this regression and the tests make sure the the ct zone
>>>> entries are created for the container ports.
>>>>
>>>> Fixes: 6c8b9a132532("ovn-controller: Store the local port bindings in the runtime data I-P state.")
>>>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1857865
>>>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1858191
>>>> Signed-off-by: Numan Siddique <numans@ovn.org>
>>>> ---
>>>>   controller/binding.c |  11 ++++
>>>>   tests/ovn.at         |  30 +++++++++++
>>>>   tests/system-ovn.at  | 118 +++++++++++++++++++++++++++++++++++++++++++
>>>>   3 files changed, 159 insertions(+)
>>>>
>>>> diff --git a/controller/binding.c b/controller/binding.c
>>>> index e630b60801..b73abb982c 100644
>>>> --- a/controller/binding.c
>>>> +++ b/controller/binding.c
>>>> @@ -1011,6 +1011,7 @@ consider_vif_lport_(const struct sbrec_port_binding *pb,
>>>>                                  b_ctx_out->local_datapaths,
>>>>                                  b_ctx_out->tracked_dp_bindings);
>>>>               update_local_lport_ids(pb, b_ctx_out);
>>>> +            update_local_lports(pb->logical_port, b_ctx_out);
>>>>               if (lbinding->iface && qos_map && b_ctx_in->ovs_idl_txn) {
>>>>                   get_qos_params(pb, qos_map);
>>>>               }
>>>> @@ -1981,6 +1982,16 @@ handle_deleted_vif_lport(const struct sbrec_port_binding *pb,
>>>>           }
>>>>       }
>>>>
>>>> +    /* If its a container lport, then delete its entry from local_lports
>>>> +     * if present.
>>>> +     * Note: If a normal lport is deleted, we don't want to remove
>>>> +     * it from local_lports if there is a VIF entry.
>>>> +     * consider_iface_release() takes care of removing from the local_lports
>>>> +     * when the interface change happens. */
>>>> +    if (is_lport_container(pb)) {
>>>> +        remove_local_lports(pb->logical_port, b_ctx_out);
>>>> +    }
>>>> +
>>>>       handle_deleted_lport(pb, b_ctx_in, b_ctx_out);
>>>>       return true;
>>>>   }
>>>> diff --git a/tests/ovn.at b/tests/ovn.at
>>>> index ba1a534e92..e19efafbe2 100644
>>>> --- a/tests/ovn.at
>>>> +++ b/tests/ovn.at
>>>> @@ -8785,6 +8785,36 @@ ip_to_hex() {
>>>>       printf "%02x%02x%02x%02x" "$@"
>>>>   }
>>>>
>>>> +# Test that ovn-controllers create ct-zone entry for container ports.
>>>> +foo1_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-foo1)
>>>> +AT_CHECK([test ! -z $foo1_zoneid])
>>>> +
>>>> +bar1_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-bar1)
>>>> +AT_CHECK([test ! -z $bar1_zoneid])
>>>> +
>>>> +bar3_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-bar3)
>>>> +AT_CHECK([test ! -z $bar3_zoneid])
>>>> +
>>>> +foo2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-foo2)
>>>> +AT_CHECK([test ! -z $foo2_zoneid])
>>>> +
>>>> +bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2)
>>>> +AT_CHECK([test ! -z $bar2_zoneid])
>>>> +
>>>> +ovn-nbctl lsp-del bar2
>>>> +ovn-nbctl --wait=hv sync
>>>> +
>>>> +bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2)
>>>> +AT_CHECK([test  -z $bar2_zoneid])
>>>> +
>>>> +# Add back bar2
>>>> +ovn-nbctl lsp-add bar bar2 vm2 1 \
>>>> +-- lsp-set-addresses bar2 "f0:00:00:01:02:08 192.168.2.3"
>>>> +ovn-nbctl --wait=hv sync
>>>> +
>>>> +bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2)
>>>> +AT_CHECK([test ! -z $bar2_zoneid])
>>>> +
>>>>   # Send ip packets between foo1 and foo2 (same switch, different HVs and
>>>>   # different VLAN tags).
>>>>   src_mac="f00000010205"
>>>> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
>>>> index 2999e52fde..77c92e86ec 100644
>>>> --- a/tests/system-ovn.at
>>>> +++ b/tests/system-ovn.at
>>>> @@ -4365,3 +4365,121 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
>>>>   /Service monitor not found.*/d"])
>>>>
>>>>   AT_CLEANUP
>>>> +
>>>> +AT_SETUP([ovn -- Load balancer for container ports])
>>>> +AT_SKIP_IF([test $HAVE_NC = no])
>>>> +AT_KEYWORDS([lb])
>>>> +
>>>> +ovn_start
>>>> +
>>>> +OVS_TRAFFIC_VSWITCHD_START()
>>>> +ADD_BR([br-int])
>>>> +
>>>> +# Set external-ids in br-int needed for ovn-controller
>>>> +ovs-vsctl \
>>>> +        -- set Open_vSwitch . external-ids:system-id=hv1 \
>>>> +        -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
>>>> +        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
>>>> +        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
>>>> +        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
>>>> +
>>>> +# Start ovn-controller
>>>> +start_daemon ovn-controller
>>>> +
>>>> +ovn-nbctl ls-add sw0
>>>> +ovn-nbctl lsp-add sw0 sw0-p1-lbc
>>>> +ovn-nbctl lsp-set-addresses sw0-port1 "10:54:00:00:00:03 10.0.0.3"
>>>> +
>>>> +ovn-nbctl lsp-add sw0 sw0-p2-lbc
>>>> +ovn-nbctl lsp-set-addresses sw0-port2 "10:54:00:00:00:04 10.0.0.4"
>>>> +
>>>> +ovn-nbctl ls-add sw1
>>>> +ovn-nbctl lsp-add sw1 sw1-port1 sw0-p1-lbc 10
>>>> +ovn-nbctl lsp-set-addresses sw1-port1 "40:54:00:00:00:03 20.0.0.3"
>>>> +
>>>> +ovn-nbctl lsp-add sw1 sw1-port2 sw0-p2-lbc 20
>>>> +ovn-nbctl lsp-set-addresses sw1-port2 "40:54:00:00:00:04 20.0.0.4"
>>>> +
>>>> +
>>>> +ovn-nbctl lr-add lr0
>>>> +ovn-nbctl lrp-add lr0 lr0-sw1 00:00:00:00:ff:02 20.0.0.1/24
>>>> +ovn-nbctl lsp-add sw1 sw1-lr0
>>>> +ovn-nbctl lsp-set-type sw1-lr0 router
>>>> +ovn-nbctl lsp-set-addresses sw1-lr0 router
>>>> +ovn-nbctl lsp-set-options sw1-lr0 router-port=lr0-sw1
>>>> +
>>>> +
>>>> +ovn-nbctl ls-add sw2
>>>> +ovn-nbctl lsp-add sw2 sw2-port1
>>>> +ovn-nbctl lsp-set-addresses sw2-port1 "50:54:00:00:00:03 30.0.0.3"
>>>> +
>>>> +ovn-nbctl lrp-add lr0 lr0-sw2 00:00:00:00:ff:03 30.0.0.1/24
>>>> +ovn-nbctl lsp-add sw2 sw2-lr0
>>>> +ovn-nbctl lsp-set-type sw2-lr0 router
>>>> +ovn-nbctl lsp-set-addresses sw2-lr0 router
>>>> +ovn-nbctl lsp-set-options sw2-lr0 router-port=lr0-sw2
>>>> +
>>>> +
>>>> +ovn-nbctl lb-add lb0 "30.0.0.10:80" "20.0.0.4:80"
>>>> +
>>>> +ovn-nbctl ls-lb-add sw1 lb0
>>>> +ovn-nbctl ls-lb-add sw2 lb0
>>>> +ovn-nbctl lr-lb-add lr0 lb0
>>>> +
>>>> +ADD_NAMESPACES(sw0-p1-lbc)
>>>> +ADD_VETH(sw0-p1-lbc, sw0-p1-lbc, br-int, "10.0.0.3/24", "10:54:00:00:00:03", \
>>>> +         "10.0.0.1")
>>>> +
>>>> +ADD_NAMESPACES(sw0-p2-lbc)
>>>> +ADD_VETH(sw0-p2-lbc, sw0-p2-lbc, br-int, "10.0.0.4/24", "10:54:00:00:00:04", \
>>>> +         "10.0.0.1")
>>>> +
>>>> +# Create the interface for lport sw1-port1
>>>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip link add link sw0-p1-lbc name sw1p1 type vlan id 10], [0])
>>>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip link set sw1p1 address 40:54:00:00:00:03], [0])
>>>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip link set sw1p1 up], [0])
>>>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip addr add 20.0.0.3/24 dev sw1p1], [0])
>>>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip route delete default via 10.0.0.1 dev sw0-p1-lbc], [0])
>>>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip route add default via 20.0.0.1 dev sw1p1], [0])
>>>> +
>>>> +# Create the interface for lport sw1-port2
>>>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip link add link sw0-p2-lbc name sw1p2 type vlan id 20], [0])
>>>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip link set sw1p2 address 40:54:00:00:00:04], [0])
>>>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip link set sw1p2 up], [0])
>>>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip addr add 20.0.0.4/24 dev sw1p2], [0])
>>>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip route delete default via 10.0.0.1 dev sw0-p2-lbc], [0])
>>>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip route add default via 20.0.0.1 dev sw1p2], [0])
>>>> +
>>>> +# Start nc server on sw1p2 (sw0-p2-lbc is the parent)
>>>> +NS_CHECK_EXEC([sw0-p2-lbc], [nc -l 20.0.0.4 80 -k &], [0])
>>>
>>> This will leave nc running after the test has ended. I think we need
>>> something like:
>>>
>>> NS_CHECK_EXEC([sw0-p2-lbc], [timeout 2s nc -l 20.0.0.4 80 -k &], [0])
>>>
>>> With this addressed, the rest looks good to me, thanks!
>>>
>>> Acked-by: Dumitru Ceara <dceara@redhat.com>
>>>
>>> Regards,
>>> Dumitru
>>
>> An alternate plan would be to use the NETNS_DAEMONIZE method to start
>> the nc listener. This way, it will automatically be cleaned up when the
>> test concludes.
>>
> 
> I like this one. Thanks. I'll test it out locally.
> 
> Thanks
> Numan
> 
> 

Nice, thanks Mark for pointing it out! I should probably change the
Hairpin test to use it too.

Regards,
Dumitru

> 
>> An alternate alternate plan would be to use the on_exit() function to
>> add a cleanup command yourself.
>>
>> An alternate alternate alternate plan would be to use OVS_START_L7 to
>> start an HTTP server, and then use `wget -q` instead of `nc -z` . This
>> would save you the overhead of pidfile management, but would make the
>> test more heavyweight.
>>
>>>
>>>> +
>>>> +# Send the packet to backend
>>>> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 20.0.0.4 80], [0])
>>>> +
>>>> +# Send the packet to VIP.
>>>> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 30.0.0.10 80], [0])
>>>> +
>>>> +# Now add an ACL in sw1.
>>>> +ovn-nbctl --wait=hv acl-add sw1 to-lport 2002 "ip" allow-related
>>>> +# Send the packet to backend
>>>> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 20.0.0.4 80], [0])
>>>> +
>>>> +# Send the packet to VIP.
>>>> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 30.0.0.10 80], [0])
>>>> +
>>>> +OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>> +
>>>> +as ovn-sb
>>>> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>> +
>>>> +as ovn-nb
>>>> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>> +
>>>> +as northd
>>>> +OVS_APP_EXIT_AND_WAIT([ovn-northd])
>>>> +
>>>> +as
>>>> +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
>>>> +/connection dropped.*/d"])
>>>> +
>>>> +AT_CLEANUP
>>>>
>>>
>>> _______________________________________________
>>> dev mailing list
>>> dev@openvswitch.org
>>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>>
>>
>> _______________________________________________
>> dev mailing list
>> dev@openvswitch.org
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>
>
Numan Siddique July 17, 2020, 5:24 p.m. UTC | #5
On Fri, Jul 17, 2020 at 7:04 PM Dumitru Ceara <dceara@redhat.com> wrote:

> On 7/17/20 3:29 PM, Numan Siddique wrote:
> > On Fri, Jul 17, 2020 at 6:55 PM Mark Michelson <mmichels@redhat.com>
> wrote:
> >>
> >> On 7/17/20 5:51 AM, Dumitru Ceara wrote:
> >>> On 7/17/20 11:21 AM, numans@ovn.org wrote:
> >>>> From: Numan Siddique <numans@ovn.org>
> >>>>
> >>>> After the commit in the Fixes tag, ovn-controller was not creating ct
> zone
> >>>> entries for the container ports in the integration bridge's
> external_ids
> >>>> column. Because of this, when a container port sends a traffic to
> >>>> load balancer VIP, zone id is not used (because REG13 is not set).
> >>>> But the reverse traffic doesn't go through the ct_lb action for
> undnat,
> >>>> but instead go to the conntrack via the ct_commit() OVN action and the
> >>>> packet gets dropped. This happens if an ACL with allow-related action
> >>>> which matches in the egress pipeline of the logical switch.
> >>>>
> >>>> This patch fixes this regression and the tests make sure the the ct
> zone
> >>>> entries are created for the container ports.
> >>>>
> >>>> Fixes: 6c8b9a132532("ovn-controller: Store the local port bindings in
> the runtime data I-P state.")
> >>>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1857865
> >>>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1858191
> >>>> Signed-off-by: Numan Siddique <numans@ovn.org>
> >>>> ---
> >>>>   controller/binding.c |  11 ++++
> >>>>   tests/ovn.at         |  30 +++++++++++
> >>>>   tests/system-ovn.at  | 118
> +++++++++++++++++++++++++++++++++++++++++++
> >>>>   3 files changed, 159 insertions(+)
> >>>>
> >>>> diff --git a/controller/binding.c b/controller/binding.c
> >>>> index e630b60801..b73abb982c 100644
> >>>> --- a/controller/binding.c
> >>>> +++ b/controller/binding.c
> >>>> @@ -1011,6 +1011,7 @@ consider_vif_lport_(const struct
> sbrec_port_binding *pb,
> >>>>                                  b_ctx_out->local_datapaths,
> >>>>                                  b_ctx_out->tracked_dp_bindings);
> >>>>               update_local_lport_ids(pb, b_ctx_out);
> >>>> +            update_local_lports(pb->logical_port, b_ctx_out);
> >>>>               if (lbinding->iface && qos_map &&
> b_ctx_in->ovs_idl_txn) {
> >>>>                   get_qos_params(pb, qos_map);
> >>>>               }
> >>>> @@ -1981,6 +1982,16 @@ handle_deleted_vif_lport(const struct
> sbrec_port_binding *pb,
> >>>>           }
> >>>>       }
> >>>>
> >>>> +    /* If its a container lport, then delete its entry from
> local_lports
> >>>> +     * if present.
> >>>> +     * Note: If a normal lport is deleted, we don't want to remove
> >>>> +     * it from local_lports if there is a VIF entry.
> >>>> +     * consider_iface_release() takes care of removing from the
> local_lports
> >>>> +     * when the interface change happens. */
> >>>> +    if (is_lport_container(pb)) {
> >>>> +        remove_local_lports(pb->logical_port, b_ctx_out);
> >>>> +    }
> >>>> +
> >>>>       handle_deleted_lport(pb, b_ctx_in, b_ctx_out);
> >>>>       return true;
> >>>>   }
> >>>> diff --git a/tests/ovn.at b/tests/ovn.at
> >>>> index ba1a534e92..e19efafbe2 100644
> >>>> --- a/tests/ovn.at
> >>>> +++ b/tests/ovn.at
> >>>> @@ -8785,6 +8785,36 @@ ip_to_hex() {
> >>>>       printf "%02x%02x%02x%02x" "$@"
> >>>>   }
> >>>>
> >>>> +# Test that ovn-controllers create ct-zone entry for container ports.
> >>>> +foo1_zoneid=$(as hv1 ovs-vsctl get bridge br-int
> external_ids:ct-zone-foo1)
> >>>> +AT_CHECK([test ! -z $foo1_zoneid])
> >>>> +
> >>>> +bar1_zoneid=$(as hv1 ovs-vsctl get bridge br-int
> external_ids:ct-zone-bar1)
> >>>> +AT_CHECK([test ! -z $bar1_zoneid])
> >>>> +
> >>>> +bar3_zoneid=$(as hv1 ovs-vsctl get bridge br-int
> external_ids:ct-zone-bar3)
> >>>> +AT_CHECK([test ! -z $bar3_zoneid])
> >>>> +
> >>>> +foo2_zoneid=$(as hv2 ovs-vsctl get bridge br-int
> external_ids:ct-zone-foo2)
> >>>> +AT_CHECK([test ! -z $foo2_zoneid])
> >>>> +
> >>>> +bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int
> external_ids:ct-zone-bar2)
> >>>> +AT_CHECK([test ! -z $bar2_zoneid])
> >>>> +
> >>>> +ovn-nbctl lsp-del bar2
> >>>> +ovn-nbctl --wait=hv sync
> >>>> +
> >>>> +bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int
> external_ids:ct-zone-bar2)
> >>>> +AT_CHECK([test  -z $bar2_zoneid])
> >>>> +
> >>>> +# Add back bar2
> >>>> +ovn-nbctl lsp-add bar bar2 vm2 1 \
> >>>> +-- lsp-set-addresses bar2 "f0:00:00:01:02:08 192.168.2.3"
> >>>> +ovn-nbctl --wait=hv sync
> >>>> +
> >>>> +bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int
> external_ids:ct-zone-bar2)
> >>>> +AT_CHECK([test ! -z $bar2_zoneid])
> >>>> +
> >>>>   # Send ip packets between foo1 and foo2 (same switch, different HVs
> and
> >>>>   # different VLAN tags).
> >>>>   src_mac="f00000010205"
> >>>> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> >>>> index 2999e52fde..77c92e86ec 100644
> >>>> --- a/tests/system-ovn.at
> >>>> +++ b/tests/system-ovn.at
> >>>> @@ -4365,3 +4365,121 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query
> port patch-.*/d
> >>>>   /Service monitor not found.*/d"])
> >>>>
> >>>>   AT_CLEANUP
> >>>> +
> >>>> +AT_SETUP([ovn -- Load balancer for container ports])
> >>>> +AT_SKIP_IF([test $HAVE_NC = no])
> >>>> +AT_KEYWORDS([lb])
> >>>> +
> >>>> +ovn_start
> >>>> +
> >>>> +OVS_TRAFFIC_VSWITCHD_START()
> >>>> +ADD_BR([br-int])
> >>>> +
> >>>> +# Set external-ids in br-int needed for ovn-controller
> >>>> +ovs-vsctl \
> >>>> +        -- set Open_vSwitch . external-ids:system-id=hv1 \
> >>>> +        -- set Open_vSwitch .
> external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
> >>>> +        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
> >>>> +        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
> >>>> +        -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true
> >>>> +
> >>>> +# Start ovn-controller
> >>>> +start_daemon ovn-controller
> >>>> +
> >>>> +ovn-nbctl ls-add sw0
> >>>> +ovn-nbctl lsp-add sw0 sw0-p1-lbc
> >>>> +ovn-nbctl lsp-set-addresses sw0-port1 "10:54:00:00:00:03 10.0.0.3"
> >>>> +
> >>>> +ovn-nbctl lsp-add sw0 sw0-p2-lbc
> >>>> +ovn-nbctl lsp-set-addresses sw0-port2 "10:54:00:00:00:04 10.0.0.4"
> >>>> +
> >>>> +ovn-nbctl ls-add sw1
> >>>> +ovn-nbctl lsp-add sw1 sw1-port1 sw0-p1-lbc 10
> >>>> +ovn-nbctl lsp-set-addresses sw1-port1 "40:54:00:00:00:03 20.0.0.3"
> >>>> +
> >>>> +ovn-nbctl lsp-add sw1 sw1-port2 sw0-p2-lbc 20
> >>>> +ovn-nbctl lsp-set-addresses sw1-port2 "40:54:00:00:00:04 20.0.0.4"
> >>>> +
> >>>> +
> >>>> +ovn-nbctl lr-add lr0
> >>>> +ovn-nbctl lrp-add lr0 lr0-sw1 00:00:00:00:ff:02 20.0.0.1/24
> >>>> +ovn-nbctl lsp-add sw1 sw1-lr0
> >>>> +ovn-nbctl lsp-set-type sw1-lr0 router
> >>>> +ovn-nbctl lsp-set-addresses sw1-lr0 router
> >>>> +ovn-nbctl lsp-set-options sw1-lr0 router-port=lr0-sw1
> >>>> +
> >>>> +
> >>>> +ovn-nbctl ls-add sw2
> >>>> +ovn-nbctl lsp-add sw2 sw2-port1
> >>>> +ovn-nbctl lsp-set-addresses sw2-port1 "50:54:00:00:00:03 30.0.0.3"
> >>>> +
> >>>> +ovn-nbctl lrp-add lr0 lr0-sw2 00:00:00:00:ff:03 30.0.0.1/24
> >>>> +ovn-nbctl lsp-add sw2 sw2-lr0
> >>>> +ovn-nbctl lsp-set-type sw2-lr0 router
> >>>> +ovn-nbctl lsp-set-addresses sw2-lr0 router
> >>>> +ovn-nbctl lsp-set-options sw2-lr0 router-port=lr0-sw2
> >>>> +
> >>>> +
> >>>> +ovn-nbctl lb-add lb0 "30.0.0.10:80" "20.0.0.4:80"
> >>>> +
> >>>> +ovn-nbctl ls-lb-add sw1 lb0
> >>>> +ovn-nbctl ls-lb-add sw2 lb0
> >>>> +ovn-nbctl lr-lb-add lr0 lb0
> >>>> +
> >>>> +ADD_NAMESPACES(sw0-p1-lbc)
> >>>> +ADD_VETH(sw0-p1-lbc, sw0-p1-lbc, br-int, "10.0.0.3/24",
> "10:54:00:00:00:03", \
> >>>> +         "10.0.0.1")
> >>>> +
> >>>> +ADD_NAMESPACES(sw0-p2-lbc)
> >>>> +ADD_VETH(sw0-p2-lbc, sw0-p2-lbc, br-int, "10.0.0.4/24",
> "10:54:00:00:00:04", \
> >>>> +         "10.0.0.1")
> >>>> +
> >>>> +# Create the interface for lport sw1-port1
> >>>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip link add link sw0-p1-lbc name sw1p1
> type vlan id 10], [0])
> >>>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip link set sw1p1 address
> 40:54:00:00:00:03], [0])
> >>>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip link set sw1p1 up], [0])
> >>>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip addr add 20.0.0.3/24 dev sw1p1],
> [0])
> >>>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip route delete default via 10.0.0.1
> dev sw0-p1-lbc], [0])
> >>>> +NS_CHECK_EXEC([sw0-p1-lbc], [ip route add default via 20.0.0.1 dev
> sw1p1], [0])
> >>>> +
> >>>> +# Create the interface for lport sw1-port2
> >>>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip link add link sw0-p2-lbc name sw1p2
> type vlan id 20], [0])
> >>>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip link set sw1p2 address
> 40:54:00:00:00:04], [0])
> >>>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip link set sw1p2 up], [0])
> >>>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip addr add 20.0.0.4/24 dev sw1p2],
> [0])
> >>>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip route delete default via 10.0.0.1
> dev sw0-p2-lbc], [0])
> >>>> +NS_CHECK_EXEC([sw0-p2-lbc], [ip route add default via 20.0.0.1 dev
> sw1p2], [0])
> >>>> +
> >>>> +# Start nc server on sw1p2 (sw0-p2-lbc is the parent)
> >>>> +NS_CHECK_EXEC([sw0-p2-lbc], [nc -l 20.0.0.4 80 -k &], [0])
> >>>
> >>> This will leave nc running after the test has ended. I think we need
> >>> something like:
> >>>
> >>> NS_CHECK_EXEC([sw0-p2-lbc], [timeout 2s nc -l 20.0.0.4 80 -k &], [0])
> >>>
> >>> With this addressed, the rest looks good to me, thanks!
> >>>
> >>> Acked-by: Dumitru Ceara <dceara@redhat.com>
>

Thanks Dumitru. I applied this patch to master and branch-20.06.
I used the NETNS_DAEMONIZE as suggested by Mark to address your comment.

Thanks
Numan

>>>
> >>> Regards,
> >>> Dumitru
> >>
> >> An alternate plan would be to use the NETNS_DAEMONIZE method to start
> >> the nc listener. This way, it will automatically be cleaned up when the
> >> test concludes.
> >>
> >
> > I like this one. Thanks. I'll test it out locally.
> >
> > Thanks
> > Numan
> >
> >
>
> Nice, thanks Mark for pointing it out! I should probably change the
> Hairpin test to use it too.
>
> Regards,
> Dumitru
>
> >
> >> An alternate alternate plan would be to use the on_exit() function to
> >> add a cleanup command yourself.
> >>
> >> An alternate alternate alternate plan would be to use OVS_START_L7 to
> >> start an HTTP server, and then use `wget -q` instead of `nc -z` . This
> >> would save you the overhead of pidfile management, but would make the
> >> test more heavyweight.
> >>
> >>>
> >>>> +
> >>>> +# Send the packet to backend
> >>>> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 20.0.0.4 80], [0])
> >>>> +
> >>>> +# Send the packet to VIP.
> >>>> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 30.0.0.10 80], [0])
> >>>> +
> >>>> +# Now add an ACL in sw1.
> >>>> +ovn-nbctl --wait=hv acl-add sw1 to-lport 2002 "ip" allow-related
> >>>> +# Send the packet to backend
> >>>> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 20.0.0.4 80], [0])
> >>>> +
> >>>> +# Send the packet to VIP.
> >>>> +NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 30.0.0.10 80], [0])
> >>>> +
> >>>> +OVS_APP_EXIT_AND_WAIT([ovn-controller])
> >>>> +
> >>>> +as ovn-sb
> >>>> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> >>>> +
> >>>> +as ovn-nb
> >>>> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> >>>> +
> >>>> +as northd
> >>>> +OVS_APP_EXIT_AND_WAIT([ovn-northd])
> >>>> +
> >>>> +as
> >>>> +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
> >>>> +/connection dropped.*/d"])
> >>>> +
> >>>> +AT_CLEANUP
> >>>>
> >>>
> >>> _______________________________________________
> >>> dev mailing list
> >>> dev@openvswitch.org
> >>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> >>>
> >>
> >> _______________________________________________
> >> dev mailing list
> >> dev@openvswitch.org
> >> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> >>
> >
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
>
diff mbox series

Patch

diff --git a/controller/binding.c b/controller/binding.c
index e630b60801..b73abb982c 100644
--- a/controller/binding.c
+++ b/controller/binding.c
@@ -1011,6 +1011,7 @@  consider_vif_lport_(const struct sbrec_port_binding *pb,
                                b_ctx_out->local_datapaths,
                                b_ctx_out->tracked_dp_bindings);
             update_local_lport_ids(pb, b_ctx_out);
+            update_local_lports(pb->logical_port, b_ctx_out);
             if (lbinding->iface && qos_map && b_ctx_in->ovs_idl_txn) {
                 get_qos_params(pb, qos_map);
             }
@@ -1981,6 +1982,16 @@  handle_deleted_vif_lport(const struct sbrec_port_binding *pb,
         }
     }
 
+    /* If its a container lport, then delete its entry from local_lports
+     * if present.
+     * Note: If a normal lport is deleted, we don't want to remove
+     * it from local_lports if there is a VIF entry.
+     * consider_iface_release() takes care of removing from the local_lports
+     * when the interface change happens. */
+    if (is_lport_container(pb)) {
+        remove_local_lports(pb->logical_port, b_ctx_out);
+    }
+
     handle_deleted_lport(pb, b_ctx_in, b_ctx_out);
     return true;
 }
diff --git a/tests/ovn.at b/tests/ovn.at
index ba1a534e92..e19efafbe2 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -8785,6 +8785,36 @@  ip_to_hex() {
     printf "%02x%02x%02x%02x" "$@"
 }
 
+# Test that ovn-controllers create ct-zone entry for container ports.
+foo1_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-foo1)
+AT_CHECK([test ! -z $foo1_zoneid])
+
+bar1_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-bar1)
+AT_CHECK([test ! -z $bar1_zoneid])
+
+bar3_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-bar3)
+AT_CHECK([test ! -z $bar3_zoneid])
+
+foo2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-foo2)
+AT_CHECK([test ! -z $foo2_zoneid])
+
+bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2)
+AT_CHECK([test ! -z $bar2_zoneid])
+
+ovn-nbctl lsp-del bar2
+ovn-nbctl --wait=hv sync
+
+bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2)
+AT_CHECK([test  -z $bar2_zoneid])
+
+# Add back bar2
+ovn-nbctl lsp-add bar bar2 vm2 1 \
+-- lsp-set-addresses bar2 "f0:00:00:01:02:08 192.168.2.3"
+ovn-nbctl --wait=hv sync
+
+bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2)
+AT_CHECK([test ! -z $bar2_zoneid])
+
 # Send ip packets between foo1 and foo2 (same switch, different HVs and
 # different VLAN tags).
 src_mac="f00000010205"
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index 2999e52fde..77c92e86ec 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -4365,3 +4365,121 @@  OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
 /Service monitor not found.*/d"])
 
 AT_CLEANUP
+
+AT_SETUP([ovn -- Load balancer for container ports])
+AT_SKIP_IF([test $HAVE_NC = no])
+AT_KEYWORDS([lb])
+
+ovn_start
+
+OVS_TRAFFIC_VSWITCHD_START()
+ADD_BR([br-int])
+
+# Set external-ids in br-int needed for ovn-controller
+ovs-vsctl \
+        -- set Open_vSwitch . external-ids:system-id=hv1 \
+        -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
+        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
+        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
+        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
+
+# Start ovn-controller
+start_daemon ovn-controller
+
+ovn-nbctl ls-add sw0
+ovn-nbctl lsp-add sw0 sw0-p1-lbc
+ovn-nbctl lsp-set-addresses sw0-port1 "10:54:00:00:00:03 10.0.0.3"
+
+ovn-nbctl lsp-add sw0 sw0-p2-lbc
+ovn-nbctl lsp-set-addresses sw0-port2 "10:54:00:00:00:04 10.0.0.4"
+
+ovn-nbctl ls-add sw1
+ovn-nbctl lsp-add sw1 sw1-port1 sw0-p1-lbc 10
+ovn-nbctl lsp-set-addresses sw1-port1 "40:54:00:00:00:03 20.0.0.3"
+
+ovn-nbctl lsp-add sw1 sw1-port2 sw0-p2-lbc 20
+ovn-nbctl lsp-set-addresses sw1-port2 "40:54:00:00:00:04 20.0.0.4"
+
+
+ovn-nbctl lr-add lr0
+ovn-nbctl lrp-add lr0 lr0-sw1 00:00:00:00:ff:02 20.0.0.1/24
+ovn-nbctl lsp-add sw1 sw1-lr0
+ovn-nbctl lsp-set-type sw1-lr0 router
+ovn-nbctl lsp-set-addresses sw1-lr0 router
+ovn-nbctl lsp-set-options sw1-lr0 router-port=lr0-sw1
+
+
+ovn-nbctl ls-add sw2
+ovn-nbctl lsp-add sw2 sw2-port1
+ovn-nbctl lsp-set-addresses sw2-port1 "50:54:00:00:00:03 30.0.0.3"
+
+ovn-nbctl lrp-add lr0 lr0-sw2 00:00:00:00:ff:03 30.0.0.1/24
+ovn-nbctl lsp-add sw2 sw2-lr0
+ovn-nbctl lsp-set-type sw2-lr0 router
+ovn-nbctl lsp-set-addresses sw2-lr0 router
+ovn-nbctl lsp-set-options sw2-lr0 router-port=lr0-sw2
+
+
+ovn-nbctl lb-add lb0 "30.0.0.10:80" "20.0.0.4:80"
+
+ovn-nbctl ls-lb-add sw1 lb0
+ovn-nbctl ls-lb-add sw2 lb0
+ovn-nbctl lr-lb-add lr0 lb0
+
+ADD_NAMESPACES(sw0-p1-lbc)
+ADD_VETH(sw0-p1-lbc, sw0-p1-lbc, br-int, "10.0.0.3/24", "10:54:00:00:00:03", \
+         "10.0.0.1")
+
+ADD_NAMESPACES(sw0-p2-lbc)
+ADD_VETH(sw0-p2-lbc, sw0-p2-lbc, br-int, "10.0.0.4/24", "10:54:00:00:00:04", \
+         "10.0.0.1")
+
+# Create the interface for lport sw1-port1
+NS_CHECK_EXEC([sw0-p1-lbc], [ip link add link sw0-p1-lbc name sw1p1 type vlan id 10], [0])
+NS_CHECK_EXEC([sw0-p1-lbc], [ip link set sw1p1 address 40:54:00:00:00:03], [0])
+NS_CHECK_EXEC([sw0-p1-lbc], [ip link set sw1p1 up], [0])
+NS_CHECK_EXEC([sw0-p1-lbc], [ip addr add 20.0.0.3/24 dev sw1p1], [0])
+NS_CHECK_EXEC([sw0-p1-lbc], [ip route delete default via 10.0.0.1 dev sw0-p1-lbc], [0])
+NS_CHECK_EXEC([sw0-p1-lbc], [ip route add default via 20.0.0.1 dev sw1p1], [0])
+
+# Create the interface for lport sw1-port2
+NS_CHECK_EXEC([sw0-p2-lbc], [ip link add link sw0-p2-lbc name sw1p2 type vlan id 20], [0])
+NS_CHECK_EXEC([sw0-p2-lbc], [ip link set sw1p2 address 40:54:00:00:00:04], [0])
+NS_CHECK_EXEC([sw0-p2-lbc], [ip link set sw1p2 up], [0])
+NS_CHECK_EXEC([sw0-p2-lbc], [ip addr add 20.0.0.4/24 dev sw1p2], [0])
+NS_CHECK_EXEC([sw0-p2-lbc], [ip route delete default via 10.0.0.1 dev sw0-p2-lbc], [0])
+NS_CHECK_EXEC([sw0-p2-lbc], [ip route add default via 20.0.0.1 dev sw1p2], [0])
+
+# Start nc server on sw1p2 (sw0-p2-lbc is the parent)
+NS_CHECK_EXEC([sw0-p2-lbc], [nc -l 20.0.0.4 80 -k &], [0])
+
+# Send the packet to backend
+NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 20.0.0.4 80], [0])
+
+# Send the packet to VIP.
+NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 30.0.0.10 80], [0])
+
+# Now add an ACL in sw1.
+ovn-nbctl --wait=hv acl-add sw1 to-lport 2002 "ip" allow-related
+# Send the packet to backend
+NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 20.0.0.4 80], [0])
+
+# Send the packet to VIP.
+NS_CHECK_EXEC([sw0-p1-lbc], [nc -z 30.0.0.10 80], [0])
+
+OVS_APP_EXIT_AND_WAIT([ovn-controller])
+
+as ovn-sb
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+
+as ovn-nb
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+
+as northd
+OVS_APP_EXIT_AND_WAIT([ovn-northd])
+
+as
+OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
+/connection dropped.*/d"])
+
+AT_CLEANUP