diff mbox series

[ovs-dev,v3] ovn-controller: Reserve zones for upcoming ports.

Message ID 20240814063732.169230-1-mansi.sharma@nutanix.com
State Superseded
Delegated to: Numan Siddique
Headers show
Series [ovs-dev,v3] ovn-controller: Reserve zones for upcoming ports. | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/github-robot-_ovn-kubernetes success github build: passed

Commit Message

Mansi Sharma Aug. 14, 2024, 6:37 a.m. UTC
This change will be useful for migration cases, where it can be
used to sync ct-entries before port is up on new chassis,
resulting in reduced network package drops.
It also fulfills the need of any other service which might need
advance ct-zone reservation in future.

Signed-off-by: Mansi Sharma <mansi.sharma@nutanix.com>
---
v2--->v3:
1. Correct reference of external_ids key.
---
 controller/ct-zone.c            | 22 ++++++++
 controller/ovn-controller.8.xml | 15 +++++-
 tests/ovn-controller.at         | 92 ++++++++++++++++++++++++++++++---
 3 files changed, 121 insertions(+), 8 deletions(-)

Comments

Mansi Sharma Aug. 19, 2024, 4:47 a.m. UTC | #1
Ping for review!

On 14/08/24 12:07 pm, Mansi Sharma wrote:
> This change will be useful for migration cases, where it can be
> used to sync ct-entries before port is up on new chassis,
> resulting in reduced network package drops.
> It also fulfills the need of any other service which might need
> advance ct-zone reservation in future.
>
> Signed-off-by: Mansi Sharma <mansi.sharma@nutanix.com>
> ---
> v2--->v3:
> 1. Correct reference of external_ids key.
> ---
>   controller/ct-zone.c            | 22 ++++++++
>   controller/ovn-controller.8.xml | 15 +++++-
>   tests/ovn-controller.at         | 92 ++++++++++++++++++++++++++++++---
>   3 files changed, 121 insertions(+), 8 deletions(-)
>
> diff --git a/controller/ct-zone.c b/controller/ct-zone.c
> index 77eb16ac9..79632282f 100644
> --- a/controller/ct-zone.c
> +++ b/controller/ct-zone.c
> @@ -183,6 +183,28 @@ ct_zones_update(const struct sset *local_lports,
>           sset_add(&all_users, local_lport);
>       }
>   
> +    /* Add local_loprt name which are supposed to come up on the
> +     * chassis and might need ct-zone reservation in advance.
> +     * The data is picked up from ovs_vswitch table. */
> +    const struct ovsrec_open_vswitch *cfg;
> +    cfg = ovsrec_open_vswitch_table_first(ovs_table);
> +    if (cfg) {
> +        const char *reserve_ct_zone_request_list = smap_get(
> +                &cfg->external_ids, "reserve_ct_zones");
> +        if (reserve_ct_zone_request_list) {
> +            char *duplicate_reserve_list = xstrdup(
> +                    reserve_ct_zone_request_list);
> +            char *reserve_port;
> +            char *save_ptr = NULL;
> +            for (reserve_port = strtok_r(duplicate_reserve_list, ",",
> +                 &save_ptr); reserve_port != NULL;
> +                 reserve_port = strtok_r(NULL, ",", &save_ptr)) {
> +                   sset_add(&all_users, reserve_port);
> +            }
> +            free(duplicate_reserve_list);
> +        }
> +    }
> +
>       /* Local patched datapath (gateway routers) need zones assigned. */
>       const struct local_datapath *ld;
>       HMAP_FOR_EACH (ld, hmap_node, local_datapaths) {
> diff --git a/controller/ovn-controller.8.xml b/controller/ovn-controller.8.xml
> index faefa77b9..b070b724c 100644
> --- a/controller/ovn-controller.8.xml
> +++ b/controller/ovn-controller.8.xml
> @@ -626,7 +626,20 @@
>             <code>external_ids:ovn-installed-ts</code>.
>           </p>
>         </dd>
> -    </dl>
> +
> +      <dt>
> +        <code>external-ids:reserve_ct_zones</code> in the <code>Bridge</code>
> +        table
> +      </dt>
> +
> +      <dd>
> +        <p>
> +          This key represents list of ports which are supposed to come up on
> +          the chassis, and hence need advance reservation of ct-zones.
> +          It is comma seprated list of port names.
> +        </p>
> +      </dd>
> +   </dl>
>   
>       <h1>OVN Southbound Database Usage</h1>
>   
> diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
> index 74bff9035..7910939aa 100644
> --- a/tests/ovn-controller.at
> +++ b/tests/ovn-controller.at
> @@ -2535,6 +2535,7 @@ check_ovsdb_zone() {
>   
>   check ovs-vsctl add-port br-int ls0-hv1 -- set Interface ls0-hv1 external-ids:iface-id=ls0-hv1
>   check ovs-vsctl add-port br-int ls0-hv2 -- set Interface ls0-hv2 external-ids:iface-id=ls0-hv2
> +check ovs-vsctl set Open_vSwitch . external_ids:reserve_ct_zones=ls0-req-hv3,ls0-req-hv4
>   
>   check ovn-nbctl lr-add lr0
>   
> @@ -2560,17 +2561,25 @@ echo "$ct_zones"
>   
>   port1_zone=$(get_zone_num "$ct_zones" ls0-hv1)
>   port2_zone=$(get_zone_num "$ct_zones" ls0-hv2)
> -
> +req_port3_zone=$(get_zone_num "$ct_zones" ls0-req-hv3)
> +req_port4_zone=$(get_zone_num "$ct_zones" ls0-req-hv4)
>   snat_zone=$(get_zone_num "$ct_zones" lr0_snat)
>   echo "snat_zone is $snat_zone"
>   
> -check test "$port1_zone" -ne "$port2_zone"
> -check test "$port2_zone" -ne "$snat_zone"
> -check test "$port1_zone" -ne "$snat_zone"
> +zone_list=$(seq(port1_zone, port2_zone, req_port2_zone, req_port4_zone, snat_zone))
> +for i in $zone_list; do
> +    for j in $zone_list; do
> +        if ["$i" != "$j"]; then
> +            check tests "$i" -ne "$j"
> +        fi
> +    done
> +done
>   
>   OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv1 $port1_zone])
>   OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv2 $port2_zone])
>   OVS_WAIT_UNTIL([check_ovsdb_zone lr0_snat $snat_zone])
> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv3 $req_port3_zone])
> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv4 $req_port4_zone])
>   
>   # Now purposely request an SNAT zone for lr0 that conflicts with a zone
>   # currently assigned to a logical port
> @@ -2585,15 +2594,84 @@ echo "$ct_zones"
>   port1_zone=$(get_zone_num "$ct_zones" ls0-hv1)
>   port2_zone=$(get_zone_num "$ct_zones" ls0-hv2)
>   snat_zone=$(get_zone_num "$ct_zones" lr0_snat)
> +req_port3_zone=$(get_zone_num "$ct_zones" ls0-req-hv3)
> +req_port4_zone=$(get_zone_num "$ct_zones" ls0-req-hv4)
>   
>   check test "$snat_zone" -eq "$snat_req_zone"
> -check test "$port1_zone" -ne "$port2_zone"
> -check test "$port2_zone" -ne "$snat_zone"
> -check test "$port1_zone" -ne "$snat_zone"
> +
> +zone_list=$(seq(port1_zone, port2_zone, req_port2_zone, req_port4_zone, snat_zone))
> +for i in $zone_list; do
> +    for j in $zone_list; do
> +        if ["$i" != "$j"]; then
> +            check tests "$i" -ne "$j"
> +        fi
> +    done
> +done
> +
> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv1 $port1_zone])
> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv2 $port2_zone])
> +OVS_WAIT_UNTIL([check_ovsdb_zone lr0_snat $snat_zone])
> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv3 $req_port3_zone])
> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv4 $req_port4_zone])
> +
> +# Add port named ls0-req-hv3 and check if same zone assigned
> +# previously get assigned to it this time as well.
> +
> +check ovn-nbctl lsp-add ls0 ls0-req-hv3
> +check ovs-vsctl -- add-port br-int hv3-vif3 -- \
> +    set interface hv3-vif3 external-ids:iface-id=ls0-req-hv3
> +ct_zones=$(ovn-appctl -t ovn-controller ct-zone-list)
> +echo "$ct_zones"
> +
> +check ovn-nbctl --wait=hv sync
> +
> +req_port3_zone_new=$(get_zone_num "$ct_zones" ls0-req-hv3)
> +
> +check test "$req_port3_zone -eq $req_port3_zone_new"
> +
> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv1 $port1_zone])
> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv2 $port2_zone])
> +OVS_WAIT_UNTIL([check_ovsdb_zone lr0_snat $snat_zone])
> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv3 $req_port3_zone])
> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv4 $req_port4_zone])
> +
> +# Checks for two cases after removing entry from ovs_vswitch table -
> +# 1. If port is already up, ct-zone should be reserved.
> +# 2. If port is not up yet, ct-zone should not be reserved.
> +
> +check ovs-vsctl remove Open_vSwitch . external_ids reserve_ct_zones
> +
> +ct_zones=$(ovn-appctl -t ovn-controller ct-zone-list)
> +echo "$ct_zones"
> +
> +req_port3_zone_after_delete=$(get_zone_num "$ct_zones" ls0-req-hv3)
> +req_port4_zone_after_delete=$(get_zone_num "$ct_zones" ls0-req-hv4)
> +
> +check test "$req_port3_zone_new" -eq "$req_port3_zone_after_delete"
> +check test "$req_port4_zone_after_delete" == ""
> +
> +# Checks for case when a ct-zone is reserved it comes up on that chassis, and
> +# gets deleted, but its persisted in ovs_vswitch table, it should persist the
> +# same zone throughout.
> +
> +check ovs-vsctl set Open_vSwitch . external_ids:reserve_ct_zones=ls0-req-hv5
> +check ovn-nbctl lsp-add ls0 ls0-req-hv5
> +check ovs-vsctl -- add-port br-int hv5-vif5 -- \
> +    set interface hv5-vif5 external-ids:iface-id=ls0-req-hv5
> +ct_zones=$(ovn-appctl -t ovn-controller ct-zone-list)
> +echo "$ct_zones"
> +req_port5_zone=$(get_zone_num "$ct_zones" ls0-req-hv5)
> +
> +check ovs-vsctl remove interface hv5-vif5 external_ids iface-id
> +echo "$ct_zones"
> +req_port5_zone_new=$(get_zone_num "$ct_zones" ls0-req-hv5)
> +
> +check test "req_port5_zone" -eq "req_port5_zone_new"
>   
>   OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv1 $port1_zone])
>   OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv2 $port2_zone])
>   OVS_WAIT_UNTIL([check_ovsdb_zone lr0_snat $snat_zone])
> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv3 $req_port3_zone])
>   
>   # Now create a conflict in the OVSDB and restart ovn-controller.
>
Mansi Sharma Aug. 22, 2024, 7:39 a.m. UTC | #2
Ping for review.

On 19/08/24 10:17 am, Mansi Sharma wrote:
> Ping for review!
>
> On 14/08/24 12:07 pm, Mansi Sharma wrote:
>> This change will be useful for migration cases, where it can be
>> used to sync ct-entries before port is up on new chassis,
>> resulting in reduced network package drops.
>> It also fulfills the need of any other service which might need
>> advance ct-zone reservation in future.
>>
>> Signed-off-by: Mansi Sharma <mansi.sharma@nutanix.com>
>> ---
>> v2--->v3:
>> 1. Correct reference of external_ids key.
>> ---
>>   controller/ct-zone.c            | 22 ++++++++
>>   controller/ovn-controller.8.xml | 15 +++++-
>>   tests/ovn-controller.at         | 92 ++++++++++++++++++++++++++++++---
>>   3 files changed, 121 insertions(+), 8 deletions(-)
>>
>> diff --git a/controller/ct-zone.c b/controller/ct-zone.c
>> index 77eb16ac9..79632282f 100644
>> --- a/controller/ct-zone.c
>> +++ b/controller/ct-zone.c
>> @@ -183,6 +183,28 @@ ct_zones_update(const struct sset *local_lports,
>>           sset_add(&all_users, local_lport);
>>       }
>>   +    /* Add local_loprt name which are supposed to come up on the
>> +     * chassis and might need ct-zone reservation in advance.
>> +     * The data is picked up from ovs_vswitch table. */
>> +    const struct ovsrec_open_vswitch *cfg;
>> +    cfg = ovsrec_open_vswitch_table_first(ovs_table);
>> +    if (cfg) {
>> +        const char *reserve_ct_zone_request_list = smap_get(
>> +                &cfg->external_ids, "reserve_ct_zones");
>> +        if (reserve_ct_zone_request_list) {
>> +            char *duplicate_reserve_list = xstrdup(
>> +                    reserve_ct_zone_request_list);
>> +            char *reserve_port;
>> +            char *save_ptr = NULL;
>> +            for (reserve_port = strtok_r(duplicate_reserve_list, ",",
>> +                 &save_ptr); reserve_port != NULL;
>> +                 reserve_port = strtok_r(NULL, ",", &save_ptr)) {
>> +                   sset_add(&all_users, reserve_port);
>> +            }
>> +            free(duplicate_reserve_list);
>> +        }
>> +    }
>> +
>>       /* Local patched datapath (gateway routers) need zones 
>> assigned. */
>>       const struct local_datapath *ld;
>>       HMAP_FOR_EACH (ld, hmap_node, local_datapaths) {
>> diff --git a/controller/ovn-controller.8.xml 
>> b/controller/ovn-controller.8.xml
>> index faefa77b9..b070b724c 100644
>> --- a/controller/ovn-controller.8.xml
>> +++ b/controller/ovn-controller.8.xml
>> @@ -626,7 +626,20 @@
>> <code>external_ids:ovn-installed-ts</code>.
>>           </p>
>>         </dd>
>> -    </dl>
>> +
>> +      <dt>
>> +        <code>external-ids:reserve_ct_zones</code> in the 
>> <code>Bridge</code>
>> +        table
>> +      </dt>
>> +
>> +      <dd>
>> +        <p>
>> +          This key represents list of ports which are supposed to 
>> come up on
>> +          the chassis, and hence need advance reservation of ct-zones.
>> +          It is comma seprated list of port names.
>> +        </p>
>> +      </dd>
>> +   </dl>
>>         <h1>OVN Southbound Database Usage</h1>
>>   diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
>> index 74bff9035..7910939aa 100644
>> --- a/tests/ovn-controller.at
>> +++ b/tests/ovn-controller.at
>> @@ -2535,6 +2535,7 @@ check_ovsdb_zone() {
>>     check ovs-vsctl add-port br-int ls0-hv1 -- set Interface ls0-hv1 
>> external-ids:iface-id=ls0-hv1
>>   check ovs-vsctl add-port br-int ls0-hv2 -- set Interface ls0-hv2 
>> external-ids:iface-id=ls0-hv2
>> +check ovs-vsctl set Open_vSwitch . 
>> external_ids:reserve_ct_zones=ls0-req-hv3,ls0-req-hv4
>>     check ovn-nbctl lr-add lr0
>>   @@ -2560,17 +2561,25 @@ echo "$ct_zones"
>>     port1_zone=$(get_zone_num "$ct_zones" ls0-hv1)
>>   port2_zone=$(get_zone_num "$ct_zones" ls0-hv2)
>> -
>> +req_port3_zone=$(get_zone_num "$ct_zones" ls0-req-hv3)
>> +req_port4_zone=$(get_zone_num "$ct_zones" ls0-req-hv4)
>>   snat_zone=$(get_zone_num "$ct_zones" lr0_snat)
>>   echo "snat_zone is $snat_zone"
>>   -check test "$port1_zone" -ne "$port2_zone"
>> -check test "$port2_zone" -ne "$snat_zone"
>> -check test "$port1_zone" -ne "$snat_zone"
>> +zone_list=$(seq(port1_zone, port2_zone, req_port2_zone, 
>> req_port4_zone, snat_zone))
>> +for i in $zone_list; do
>> +    for j in $zone_list; do
>> +        if ["$i" != "$j"]; then
>> +            check tests "$i" -ne "$j"
>> +        fi
>> +    done
>> +done
>>     OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv1 $port1_zone])
>>   OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv2 $port2_zone])
>>   OVS_WAIT_UNTIL([check_ovsdb_zone lr0_snat $snat_zone])
>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv3 $req_port3_zone])
>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv4 $req_port4_zone])
>>     # Now purposely request an SNAT zone for lr0 that conflicts with 
>> a zone
>>   # currently assigned to a logical port
>> @@ -2585,15 +2594,84 @@ echo "$ct_zones"
>>   port1_zone=$(get_zone_num "$ct_zones" ls0-hv1)
>>   port2_zone=$(get_zone_num "$ct_zones" ls0-hv2)
>>   snat_zone=$(get_zone_num "$ct_zones" lr0_snat)
>> +req_port3_zone=$(get_zone_num "$ct_zones" ls0-req-hv3)
>> +req_port4_zone=$(get_zone_num "$ct_zones" ls0-req-hv4)
>>     check test "$snat_zone" -eq "$snat_req_zone"
>> -check test "$port1_zone" -ne "$port2_zone"
>> -check test "$port2_zone" -ne "$snat_zone"
>> -check test "$port1_zone" -ne "$snat_zone"
>> +
>> +zone_list=$(seq(port1_zone, port2_zone, req_port2_zone, 
>> req_port4_zone, snat_zone))
>> +for i in $zone_list; do
>> +    for j in $zone_list; do
>> +        if ["$i" != "$j"]; then
>> +            check tests "$i" -ne "$j"
>> +        fi
>> +    done
>> +done
>> +
>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv1 $port1_zone])
>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv2 $port2_zone])
>> +OVS_WAIT_UNTIL([check_ovsdb_zone lr0_snat $snat_zone])
>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv3 $req_port3_zone])
>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv4 $req_port4_zone])
>> +
>> +# Add port named ls0-req-hv3 and check if same zone assigned
>> +# previously get assigned to it this time as well.
>> +
>> +check ovn-nbctl lsp-add ls0 ls0-req-hv3
>> +check ovs-vsctl -- add-port br-int hv3-vif3 -- \
>> +    set interface hv3-vif3 external-ids:iface-id=ls0-req-hv3
>> +ct_zones=$(ovn-appctl -t ovn-controller ct-zone-list)
>> +echo "$ct_zones"
>> +
>> +check ovn-nbctl --wait=hv sync
>> +
>> +req_port3_zone_new=$(get_zone_num "$ct_zones" ls0-req-hv3)
>> +
>> +check test "$req_port3_zone -eq $req_port3_zone_new"
>> +
>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv1 $port1_zone])
>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv2 $port2_zone])
>> +OVS_WAIT_UNTIL([check_ovsdb_zone lr0_snat $snat_zone])
>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv3 $req_port3_zone])
>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv4 $req_port4_zone])
>> +
>> +# Checks for two cases after removing entry from ovs_vswitch table -
>> +# 1. If port is already up, ct-zone should be reserved.
>> +# 2. If port is not up yet, ct-zone should not be reserved.
>> +
>> +check ovs-vsctl remove Open_vSwitch . external_ids reserve_ct_zones
>> +
>> +ct_zones=$(ovn-appctl -t ovn-controller ct-zone-list)
>> +echo "$ct_zones"
>> +
>> +req_port3_zone_after_delete=$(get_zone_num "$ct_zones" ls0-req-hv3)
>> +req_port4_zone_after_delete=$(get_zone_num "$ct_zones" ls0-req-hv4)
>> +
>> +check test "$req_port3_zone_new" -eq "$req_port3_zone_after_delete"
>> +check test "$req_port4_zone_after_delete" == ""
>> +
>> +# Checks for case when a ct-zone is reserved it comes up on that 
>> chassis, and
>> +# gets deleted, but its persisted in ovs_vswitch table, it should 
>> persist the
>> +# same zone throughout.
>> +
>> +check ovs-vsctl set Open_vSwitch . 
>> external_ids:reserve_ct_zones=ls0-req-hv5
>> +check ovn-nbctl lsp-add ls0 ls0-req-hv5
>> +check ovs-vsctl -- add-port br-int hv5-vif5 -- \
>> +    set interface hv5-vif5 external-ids:iface-id=ls0-req-hv5
>> +ct_zones=$(ovn-appctl -t ovn-controller ct-zone-list)
>> +echo "$ct_zones"
>> +req_port5_zone=$(get_zone_num "$ct_zones" ls0-req-hv5)
>> +
>> +check ovs-vsctl remove interface hv5-vif5 external_ids iface-id
>> +echo "$ct_zones"
>> +req_port5_zone_new=$(get_zone_num "$ct_zones" ls0-req-hv5)
>> +
>> +check test "req_port5_zone" -eq "req_port5_zone_new"
>>     OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv1 $port1_zone])
>>   OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv2 $port2_zone])
>>   OVS_WAIT_UNTIL([check_ovsdb_zone lr0_snat $snat_zone])
>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv3 $req_port3_zone])
>>     # Now create a conflict in the OVSDB and restart ovn-controller.
Mansi Sharma Aug. 26, 2024, 3:03 p.m. UTC | #3
Ping for review.

On 22/08/24 1:09 pm, Mansi Sharma wrote:
> Ping for review.
>
> On 19/08/24 10:17 am, Mansi Sharma wrote:
>> Ping for review!
>>
>> On 14/08/24 12:07 pm, Mansi Sharma wrote:
>>> This change will be useful for migration cases, where it can be
>>> used to sync ct-entries before port is up on new chassis,
>>> resulting in reduced network package drops.
>>> It also fulfills the need of any other service which might need
>>> advance ct-zone reservation in future.
>>>
>>> Signed-off-by: Mansi Sharma <mansi.sharma@nutanix.com>
>>> ---
>>> v2--->v3:
>>> 1. Correct reference of external_ids key.
>>> ---
>>>   controller/ct-zone.c            | 22 ++++++++
>>>   controller/ovn-controller.8.xml | 15 +++++-
>>>   tests/ovn-controller.at         | 92 
>>> ++++++++++++++++++++++++++++++---
>>>   3 files changed, 121 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/controller/ct-zone.c b/controller/ct-zone.c
>>> index 77eb16ac9..79632282f 100644
>>> --- a/controller/ct-zone.c
>>> +++ b/controller/ct-zone.c
>>> @@ -183,6 +183,28 @@ ct_zones_update(const struct sset *local_lports,
>>>           sset_add(&all_users, local_lport);
>>>       }
>>>   +    /* Add local_loprt name which are supposed to come up on the
>>> +     * chassis and might need ct-zone reservation in advance.
>>> +     * The data is picked up from ovs_vswitch table. */
>>> +    const struct ovsrec_open_vswitch *cfg;
>>> +    cfg = ovsrec_open_vswitch_table_first(ovs_table);
>>> +    if (cfg) {
>>> +        const char *reserve_ct_zone_request_list = smap_get(
>>> +                &cfg->external_ids, "reserve_ct_zones");
>>> +        if (reserve_ct_zone_request_list) {
>>> +            char *duplicate_reserve_list = xstrdup(
>>> +                    reserve_ct_zone_request_list);
>>> +            char *reserve_port;
>>> +            char *save_ptr = NULL;
>>> +            for (reserve_port = strtok_r(duplicate_reserve_list, ",",
>>> +                 &save_ptr); reserve_port != NULL;
>>> +                 reserve_port = strtok_r(NULL, ",", &save_ptr)) {
>>> +                   sset_add(&all_users, reserve_port);
>>> +            }
>>> +            free(duplicate_reserve_list);
>>> +        }
>>> +    }
>>> +
>>>       /* Local patched datapath (gateway routers) need zones 
>>> assigned. */
>>>       const struct local_datapath *ld;
>>>       HMAP_FOR_EACH (ld, hmap_node, local_datapaths) {
>>> diff --git a/controller/ovn-controller.8.xml 
>>> b/controller/ovn-controller.8.xml
>>> index faefa77b9..b070b724c 100644
>>> --- a/controller/ovn-controller.8.xml
>>> +++ b/controller/ovn-controller.8.xml
>>> @@ -626,7 +626,20 @@
>>> <code>external_ids:ovn-installed-ts</code>.
>>>           </p>
>>>         </dd>
>>> -    </dl>
>>> +
>>> +      <dt>
>>> + <code>external-ids:reserve_ct_zones</code> in the <code>Bridge</code>
>>> +        table
>>> +      </dt>
>>> +
>>> +      <dd>
>>> +        <p>
>>> +          This key represents list of ports which are supposed to 
>>> come up on
>>> +          the chassis, and hence need advance reservation of ct-zones.
>>> +          It is comma seprated list of port names.
>>> +        </p>
>>> +      </dd>
>>> +   </dl>
>>>         <h1>OVN Southbound Database Usage</h1>
>>>   diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
>>> index 74bff9035..7910939aa 100644
>>> --- a/tests/ovn-controller.at
>>> +++ b/tests/ovn-controller.at
>>> @@ -2535,6 +2535,7 @@ check_ovsdb_zone() {
>>>     check ovs-vsctl add-port br-int ls0-hv1 -- set Interface ls0-hv1 
>>> external-ids:iface-id=ls0-hv1
>>>   check ovs-vsctl add-port br-int ls0-hv2 -- set Interface ls0-hv2 
>>> external-ids:iface-id=ls0-hv2
>>> +check ovs-vsctl set Open_vSwitch . 
>>> external_ids:reserve_ct_zones=ls0-req-hv3,ls0-req-hv4
>>>     check ovn-nbctl lr-add lr0
>>>   @@ -2560,17 +2561,25 @@ echo "$ct_zones"
>>>     port1_zone=$(get_zone_num "$ct_zones" ls0-hv1)
>>>   port2_zone=$(get_zone_num "$ct_zones" ls0-hv2)
>>> -
>>> +req_port3_zone=$(get_zone_num "$ct_zones" ls0-req-hv3)
>>> +req_port4_zone=$(get_zone_num "$ct_zones" ls0-req-hv4)
>>>   snat_zone=$(get_zone_num "$ct_zones" lr0_snat)
>>>   echo "snat_zone is $snat_zone"
>>>   -check test "$port1_zone" -ne "$port2_zone"
>>> -check test "$port2_zone" -ne "$snat_zone"
>>> -check test "$port1_zone" -ne "$snat_zone"
>>> +zone_list=$(seq(port1_zone, port2_zone, req_port2_zone, 
>>> req_port4_zone, snat_zone))
>>> +for i in $zone_list; do
>>> +    for j in $zone_list; do
>>> +        if ["$i" != "$j"]; then
>>> +            check tests "$i" -ne "$j"
>>> +        fi
>>> +    done
>>> +done
>>>     OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv1 $port1_zone])
>>>   OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv2 $port2_zone])
>>>   OVS_WAIT_UNTIL([check_ovsdb_zone lr0_snat $snat_zone])
>>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv3 $req_port3_zone])
>>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv4 $req_port4_zone])
>>>     # Now purposely request an SNAT zone for lr0 that conflicts with 
>>> a zone
>>>   # currently assigned to a logical port
>>> @@ -2585,15 +2594,84 @@ echo "$ct_zones"
>>>   port1_zone=$(get_zone_num "$ct_zones" ls0-hv1)
>>>   port2_zone=$(get_zone_num "$ct_zones" ls0-hv2)
>>>   snat_zone=$(get_zone_num "$ct_zones" lr0_snat)
>>> +req_port3_zone=$(get_zone_num "$ct_zones" ls0-req-hv3)
>>> +req_port4_zone=$(get_zone_num "$ct_zones" ls0-req-hv4)
>>>     check test "$snat_zone" -eq "$snat_req_zone"
>>> -check test "$port1_zone" -ne "$port2_zone"
>>> -check test "$port2_zone" -ne "$snat_zone"
>>> -check test "$port1_zone" -ne "$snat_zone"
>>> +
>>> +zone_list=$(seq(port1_zone, port2_zone, req_port2_zone, 
>>> req_port4_zone, snat_zone))
>>> +for i in $zone_list; do
>>> +    for j in $zone_list; do
>>> +        if ["$i" != "$j"]; then
>>> +            check tests "$i" -ne "$j"
>>> +        fi
>>> +    done
>>> +done
>>> +
>>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv1 $port1_zone])
>>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv2 $port2_zone])
>>> +OVS_WAIT_UNTIL([check_ovsdb_zone lr0_snat $snat_zone])
>>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv3 $req_port3_zone])
>>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv4 $req_port4_zone])
>>> +
>>> +# Add port named ls0-req-hv3 and check if same zone assigned
>>> +# previously get assigned to it this time as well.
>>> +
>>> +check ovn-nbctl lsp-add ls0 ls0-req-hv3
>>> +check ovs-vsctl -- add-port br-int hv3-vif3 -- \
>>> +    set interface hv3-vif3 external-ids:iface-id=ls0-req-hv3
>>> +ct_zones=$(ovn-appctl -t ovn-controller ct-zone-list)
>>> +echo "$ct_zones"
>>> +
>>> +check ovn-nbctl --wait=hv sync
>>> +
>>> +req_port3_zone_new=$(get_zone_num "$ct_zones" ls0-req-hv3)
>>> +
>>> +check test "$req_port3_zone -eq $req_port3_zone_new"
>>> +
>>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv1 $port1_zone])
>>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv2 $port2_zone])
>>> +OVS_WAIT_UNTIL([check_ovsdb_zone lr0_snat $snat_zone])
>>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv3 $req_port3_zone])
>>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv4 $req_port4_zone])
>>> +
>>> +# Checks for two cases after removing entry from ovs_vswitch table -
>>> +# 1. If port is already up, ct-zone should be reserved.
>>> +# 2. If port is not up yet, ct-zone should not be reserved.
>>> +
>>> +check ovs-vsctl remove Open_vSwitch . external_ids reserve_ct_zones
>>> +
>>> +ct_zones=$(ovn-appctl -t ovn-controller ct-zone-list)
>>> +echo "$ct_zones"
>>> +
>>> +req_port3_zone_after_delete=$(get_zone_num "$ct_zones" ls0-req-hv3)
>>> +req_port4_zone_after_delete=$(get_zone_num "$ct_zones" ls0-req-hv4)
>>> +
>>> +check test "$req_port3_zone_new" -eq "$req_port3_zone_after_delete"
>>> +check test "$req_port4_zone_after_delete" == ""
>>> +
>>> +# Checks for case when a ct-zone is reserved it comes up on that 
>>> chassis, and
>>> +# gets deleted, but its persisted in ovs_vswitch table, it should 
>>> persist the
>>> +# same zone throughout.
>>> +
>>> +check ovs-vsctl set Open_vSwitch . 
>>> external_ids:reserve_ct_zones=ls0-req-hv5
>>> +check ovn-nbctl lsp-add ls0 ls0-req-hv5
>>> +check ovs-vsctl -- add-port br-int hv5-vif5 -- \
>>> +    set interface hv5-vif5 external-ids:iface-id=ls0-req-hv5
>>> +ct_zones=$(ovn-appctl -t ovn-controller ct-zone-list)
>>> +echo "$ct_zones"
>>> +req_port5_zone=$(get_zone_num "$ct_zones" ls0-req-hv5)
>>> +
>>> +check ovs-vsctl remove interface hv5-vif5 external_ids iface-id
>>> +echo "$ct_zones"
>>> +req_port5_zone_new=$(get_zone_num "$ct_zones" ls0-req-hv5)
>>> +
>>> +check test "req_port5_zone" -eq "req_port5_zone_new"
>>>     OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv1 $port1_zone])
>>>   OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv2 $port2_zone])
>>>   OVS_WAIT_UNTIL([check_ovsdb_zone lr0_snat $snat_zone])
>>> +OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv3 $req_port3_zone])
>>>     # Now create a conflict in the OVSDB and restart ovn-controller.
diff mbox series

Patch

diff --git a/controller/ct-zone.c b/controller/ct-zone.c
index 77eb16ac9..79632282f 100644
--- a/controller/ct-zone.c
+++ b/controller/ct-zone.c
@@ -183,6 +183,28 @@  ct_zones_update(const struct sset *local_lports,
         sset_add(&all_users, local_lport);
     }
 
+    /* Add local_loprt name which are supposed to come up on the
+     * chassis and might need ct-zone reservation in advance.
+     * The data is picked up from ovs_vswitch table. */
+    const struct ovsrec_open_vswitch *cfg;
+    cfg = ovsrec_open_vswitch_table_first(ovs_table);
+    if (cfg) {
+        const char *reserve_ct_zone_request_list = smap_get(
+                &cfg->external_ids, "reserve_ct_zones");
+        if (reserve_ct_zone_request_list) {
+            char *duplicate_reserve_list = xstrdup(
+                    reserve_ct_zone_request_list);
+            char *reserve_port;
+            char *save_ptr = NULL;
+            for (reserve_port = strtok_r(duplicate_reserve_list, ",",
+                 &save_ptr); reserve_port != NULL;
+                 reserve_port = strtok_r(NULL, ",", &save_ptr)) {
+                   sset_add(&all_users, reserve_port);
+            }
+            free(duplicate_reserve_list);
+        }
+    }
+
     /* Local patched datapath (gateway routers) need zones assigned. */
     const struct local_datapath *ld;
     HMAP_FOR_EACH (ld, hmap_node, local_datapaths) {
diff --git a/controller/ovn-controller.8.xml b/controller/ovn-controller.8.xml
index faefa77b9..b070b724c 100644
--- a/controller/ovn-controller.8.xml
+++ b/controller/ovn-controller.8.xml
@@ -626,7 +626,20 @@ 
           <code>external_ids:ovn-installed-ts</code>.
         </p>
       </dd>
-    </dl>
+
+      <dt>
+        <code>external-ids:reserve_ct_zones</code> in the <code>Bridge</code>
+        table
+      </dt>
+
+      <dd>
+        <p>
+          This key represents list of ports which are supposed to come up on
+          the chassis, and hence need advance reservation of ct-zones.
+          It is comma seprated list of port names.
+        </p>
+      </dd>
+   </dl>
 
     <h1>OVN Southbound Database Usage</h1>
 
diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
index 74bff9035..7910939aa 100644
--- a/tests/ovn-controller.at
+++ b/tests/ovn-controller.at
@@ -2535,6 +2535,7 @@  check_ovsdb_zone() {
 
 check ovs-vsctl add-port br-int ls0-hv1 -- set Interface ls0-hv1 external-ids:iface-id=ls0-hv1
 check ovs-vsctl add-port br-int ls0-hv2 -- set Interface ls0-hv2 external-ids:iface-id=ls0-hv2
+check ovs-vsctl set Open_vSwitch . external_ids:reserve_ct_zones=ls0-req-hv3,ls0-req-hv4
 
 check ovn-nbctl lr-add lr0
 
@@ -2560,17 +2561,25 @@  echo "$ct_zones"
 
 port1_zone=$(get_zone_num "$ct_zones" ls0-hv1)
 port2_zone=$(get_zone_num "$ct_zones" ls0-hv2)
-
+req_port3_zone=$(get_zone_num "$ct_zones" ls0-req-hv3)
+req_port4_zone=$(get_zone_num "$ct_zones" ls0-req-hv4)
 snat_zone=$(get_zone_num "$ct_zones" lr0_snat)
 echo "snat_zone is $snat_zone"
 
-check test "$port1_zone" -ne "$port2_zone"
-check test "$port2_zone" -ne "$snat_zone"
-check test "$port1_zone" -ne "$snat_zone"
+zone_list=$(seq(port1_zone, port2_zone, req_port2_zone, req_port4_zone, snat_zone))
+for i in $zone_list; do
+    for j in $zone_list; do
+        if ["$i" != "$j"]; then
+            check tests "$i" -ne "$j"
+        fi
+    done
+done
 
 OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv1 $port1_zone])
 OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv2 $port2_zone])
 OVS_WAIT_UNTIL([check_ovsdb_zone lr0_snat $snat_zone])
+OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv3 $req_port3_zone])
+OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv4 $req_port4_zone])
 
 # Now purposely request an SNAT zone for lr0 that conflicts with a zone
 # currently assigned to a logical port
@@ -2585,15 +2594,84 @@  echo "$ct_zones"
 port1_zone=$(get_zone_num "$ct_zones" ls0-hv1)
 port2_zone=$(get_zone_num "$ct_zones" ls0-hv2)
 snat_zone=$(get_zone_num "$ct_zones" lr0_snat)
+req_port3_zone=$(get_zone_num "$ct_zones" ls0-req-hv3)
+req_port4_zone=$(get_zone_num "$ct_zones" ls0-req-hv4)
 
 check test "$snat_zone" -eq "$snat_req_zone"
-check test "$port1_zone" -ne "$port2_zone"
-check test "$port2_zone" -ne "$snat_zone"
-check test "$port1_zone" -ne "$snat_zone"
+
+zone_list=$(seq(port1_zone, port2_zone, req_port2_zone, req_port4_zone, snat_zone))
+for i in $zone_list; do
+    for j in $zone_list; do
+        if ["$i" != "$j"]; then
+            check tests "$i" -ne "$j"
+        fi
+    done
+done
+
+OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv1 $port1_zone])
+OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv2 $port2_zone])
+OVS_WAIT_UNTIL([check_ovsdb_zone lr0_snat $snat_zone])
+OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv3 $req_port3_zone])
+OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv4 $req_port4_zone])
+
+# Add port named ls0-req-hv3 and check if same zone assigned
+# previously get assigned to it this time as well.
+
+check ovn-nbctl lsp-add ls0 ls0-req-hv3
+check ovs-vsctl -- add-port br-int hv3-vif3 -- \
+    set interface hv3-vif3 external-ids:iface-id=ls0-req-hv3
+ct_zones=$(ovn-appctl -t ovn-controller ct-zone-list)
+echo "$ct_zones"
+
+check ovn-nbctl --wait=hv sync
+
+req_port3_zone_new=$(get_zone_num "$ct_zones" ls0-req-hv3)
+
+check test "$req_port3_zone -eq $req_port3_zone_new"
+
+OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv1 $port1_zone])
+OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv2 $port2_zone])
+OVS_WAIT_UNTIL([check_ovsdb_zone lr0_snat $snat_zone])
+OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv3 $req_port3_zone])
+OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv4 $req_port4_zone])
+
+# Checks for two cases after removing entry from ovs_vswitch table -
+# 1. If port is already up, ct-zone should be reserved.
+# 2. If port is not up yet, ct-zone should not be reserved.
+
+check ovs-vsctl remove Open_vSwitch . external_ids reserve_ct_zones
+
+ct_zones=$(ovn-appctl -t ovn-controller ct-zone-list)
+echo "$ct_zones"
+
+req_port3_zone_after_delete=$(get_zone_num "$ct_zones" ls0-req-hv3)
+req_port4_zone_after_delete=$(get_zone_num "$ct_zones" ls0-req-hv4)
+
+check test "$req_port3_zone_new" -eq "$req_port3_zone_after_delete"
+check test "$req_port4_zone_after_delete" == ""
+
+# Checks for case when a ct-zone is reserved it comes up on that chassis, and
+# gets deleted, but its persisted in ovs_vswitch table, it should persist the
+# same zone throughout.
+
+check ovs-vsctl set Open_vSwitch . external_ids:reserve_ct_zones=ls0-req-hv5
+check ovn-nbctl lsp-add ls0 ls0-req-hv5
+check ovs-vsctl -- add-port br-int hv5-vif5 -- \
+    set interface hv5-vif5 external-ids:iface-id=ls0-req-hv5
+ct_zones=$(ovn-appctl -t ovn-controller ct-zone-list)
+echo "$ct_zones"
+req_port5_zone=$(get_zone_num "$ct_zones" ls0-req-hv5)
+
+check ovs-vsctl remove interface hv5-vif5 external_ids iface-id
+echo "$ct_zones"
+req_port5_zone_new=$(get_zone_num "$ct_zones" ls0-req-hv5)
+
+check test "req_port5_zone" -eq "req_port5_zone_new"
 
 OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv1 $port1_zone])
 OVS_WAIT_UNTIL([check_ovsdb_zone ls0-hv2 $port2_zone])
 OVS_WAIT_UNTIL([check_ovsdb_zone lr0_snat $snat_zone])
+OVS_WAIT_UNTIL([check_ovsdb_zone ls0-req-hv3 $req_port3_zone])
 
 # Now create a conflict in the OVSDB and restart ovn-controller.