diff mbox series

[ovs-dev,v2] ic: learn routes to LR only from corresponding transit switch

Message ID 20210819153012.82531-1-odivlad@gmail.com
State Accepted
Headers show
Series [ovs-dev,v2] ic: learn routes to LR only from corresponding transit switch | expand

Checks

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

Commit Message

Vladislav Odintsov Aug. 19, 2021, 3:30 p.m. UTC
This commit fixes an error where in case of LRs were connected
between different AZs with ovn-ic, their routes were leaking
from one LR attached to its transit switch to another LR
attached to another transit switch.

Testcase, which reproduces described problem is added as well.

Signed-off-by: Vladislav Odintsov <odivlad@gmail.com>
---
v1 -> v2:
 - Address Han's review comments:
   - Make comments and test more clear to understand.
   - Use ovsdb_idl_index to optimize transit switch lookup.
---
 ic/ovn-ic.c     | 17 ++++++++++++++-
 tests/ovn-ic.at | 55 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+), 1 deletion(-)

Comments

Han Zhou Aug. 19, 2021, 5:06 p.m. UTC | #1
On Thu, Aug 19, 2021 at 8:30 AM Vladislav Odintsov <odivlad@gmail.com>
wrote:
>
> This commit fixes an error where in case of LRs were connected
> between different AZs with ovn-ic, their routes were leaking
> from one LR attached to its transit switch to another LR
> attached to another transit switch.
>
> Testcase, which reproduces described problem is added as well.
>
> Signed-off-by: Vladislav Odintsov <odivlad@gmail.com>
> ---
> v1 -> v2:
>  - Address Han's review comments:
>    - Make comments and test more clear to understand.
>    - Use ovsdb_idl_index to optimize transit switch lookup.
> ---
>  ic/ovn-ic.c     | 17 ++++++++++++++-
>  tests/ovn-ic.at | 55 +++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 71 insertions(+), 1 deletion(-)
>
> diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c
> index d69583956..75e798cd1 100644
> --- a/ic/ovn-ic.c
> +++ b/ic/ovn-ic.c
> @@ -67,6 +67,7 @@ struct ic_context {
>      struct ovsdb_idl_index *sbrec_chassis_by_name;
>      struct ovsdb_idl_index *sbrec_port_binding_by_name;
>      struct ovsdb_idl_index *icsbrec_port_binding_by_ts;
> +    struct ovsdb_idl_index *icsbrec_route_by_ts;
>  };
>
>  struct ic_state {
> @@ -1156,7 +1157,14 @@ sync_learned_route(struct ic_context *ctx,
>  {
>      ovs_assert(ctx->ovnnb_txn);
>      const struct icsbrec_route *isb_route;
> -    ICSBREC_ROUTE_FOR_EACH (isb_route, ctx->ovnisb_idl) {
> +    const struct icsbrec_route *isb_route_key =
> +        icsbrec_route_index_init_row(ctx->icsbrec_route_by_ts);
> +
> +    icsbrec_route_index_set_transit_switch(isb_route_key,
> +
ic_lr->isb_pb->transit_switch);
> +
> +    ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key,
> +                                  ctx->icsbrec_route_by_ts) {
>          if (isb_route->availability_zone == az) {
>              continue;
>          }
> @@ -1208,6 +1216,8 @@ sync_learned_route(struct ic_context *ctx,
>                  ic_lr->lr, nb_route);
>          }
>      }
> +    icsbrec_route_index_destroy_row(isb_route_key);
> +
>      /* Delete extra learned routes. */
>      struct ic_route_info *route_learned, *next;
>      HMAP_FOR_EACH_SAFE (route_learned, next, node,
&ic_lr->routes_learned) {
> @@ -1678,6 +1688,10 @@ main(int argc, char *argv[])
>          = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,
>
 &icsbrec_port_binding_col_transit_switch);
>
> +    struct ovsdb_idl_index *icsbrec_route_by_ts
> +        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,
> +                                  &icsbrec_route_col_transit_switch);
> +
>      /* Main loop. */
>      exiting = false;
>      state.had_lock = false;
> @@ -1718,6 +1732,7 @@ main(int argc, char *argv[])
>                  .sbrec_port_binding_by_name = sbrec_port_binding_by_name,
>                  .sbrec_chassis_by_name = sbrec_chassis_by_name,
>                  .icsbrec_port_binding_by_ts = icsbrec_port_binding_by_ts,
> +                .icsbrec_route_by_ts = icsbrec_route_by_ts,
>              };
>
>              if (!state.had_lock &&
ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) {
> diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at
> index 2a4fba031..ee78f4794 100644
> --- a/tests/ovn-ic.at
> +++ b/tests/ovn-ic.at
> @@ -315,6 +315,61 @@ OVS_WAIT_WHILE([ovn_as az2 ovn-nbctl lr-route-list
lr2 | grep learned | grep 192
>  # AZ1 shouldn't learn 10.11 any more.
>  OVS_WAIT_WHILE([ovn_as az1 ovn-nbctl lr-route-list lr1 | grep learned |
grep 10.11])
>
> +# cleanup
> +ovn-ic-nbctl --if-exists ts-del ts1
> +ovn_as az1 ovn-nbctl lr-del lr1
> +ovn_as az2 ovn-nbctl lr-del lr2
> +
> +# Create new transit switches and LRs. Test topology is next:
> +# logical router (lr11) - transit switch (ts11) - logical router (lr12)
> +# logical router (lr21) - transit switch (ts22) - logical router (lr22)
> +#
> +# lr12 has static route 10.0.0.0/24 and directly connected network
192.168.0.0/24
> +for i in 1 2; do
> +    ovn_as az$i
> +
> +    # Ensure route learning at AZ level
> +    ovn-nbctl set nb_global . options:ic-route-learn=true
> +    # Ensure route advertising at AZ level
> +    ovn-nbctl set nb_global . options:ic-route-adv=true
> +    # Drop blacklist
> +    ovn-nbctl remove nb_global . options ic-route-blacklist
> +
> +    for j in 1 2; do
> +        ts=ts$j$j
> +        ovn-ic-nbctl --may-exist ts-add $ts
> +
> +        # Create LRP and connect to TS
> +        lr=lr$j$i
> +        echo lr: $lr, ts: $ts
> +        ovn-nbctl lr-add $lr
> +        ovn-nbctl lrp-add $lr lrp-$lr-$ts aa:aa:aa:aa:aa:0$j
169.254.100.$i/24
> +        ovn-nbctl lsp-add $ts lsp-$ts-$lr \
> +                -- lsp-set-addresses lsp-$ts-$lr router \
> +                -- lsp-set-type lsp-$ts-$lr router \
> +                -- lsp-set-options lsp-$ts-$lr router-port=lrp-$lr-$ts
> +    done
> +done
> +
> +# Create directly-connected routes
> +ovn_as az2 ovn-nbctl lrp-add lr12 lrp-lr12-ls2 aa:aa:aa:aa:bb:01 "
192.168.0.1/24"
> +ovn_as az2 ovn-nbctl lr-route-add lr12 10.10.10.0/24 192.168.0.10
> +
> +echo az1
> +ovn_as az1 ovn-nbctl show
> +echo az2
> +ovn_as az2 ovn-nbctl show
> +
> +# Test routes from lr12 were learned to lr11
> +AT_CHECK([ovn_as az1 ovn-nbctl lr-route-list lr11 |
> +             grep learned | awk '{print $1, $2}' | sort], [0], [dnl
> +10.10.10.0/24 169.254.100.2
> +192.168.0.0/24 169.254.100.2
> +])
> +
> +# Test routes from lr12 didn't leak as learned to lr21
> +AT_CHECK([ovn_as az1 ovn-nbctl lr-route-list lr21], [0], [])
> +
>  OVN_CLEANUP_IC([az1], [az2])
>
>  AT_CLEANUP
> --
> 2.30.0
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Thanks Vladislav. I applied to all branches.
Vladislav Odintsov Aug. 19, 2021, 5:11 p.m. UTC | #2
Thanks!

Regards,
Vladislav Odintsov

> On 19 Aug 2021, at 20:06, Han Zhou <zhouhan@gmail.com> wrote:
> 
> On Thu, Aug 19, 2021 at 8:30 AM Vladislav Odintsov <odivlad@gmail.com>
> wrote:
>> 
>> This commit fixes an error where in case of LRs were connected
>> between different AZs with ovn-ic, their routes were leaking
>> from one LR attached to its transit switch to another LR
>> attached to another transit switch.
>> 
>> Testcase, which reproduces described problem is added as well.
>> 
>> Signed-off-by: Vladislav Odintsov <odivlad@gmail.com>
>> ---
>> v1 -> v2:
>> - Address Han's review comments:
>>   - Make comments and test more clear to understand.
>>   - Use ovsdb_idl_index to optimize transit switch lookup.
>> ---
>> ic/ovn-ic.c     | 17 ++++++++++++++-
>> tests/ovn-ic.at | 55 +++++++++++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 71 insertions(+), 1 deletion(-)
>> 
>> diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c
>> index d69583956..75e798cd1 100644
>> --- a/ic/ovn-ic.c
>> +++ b/ic/ovn-ic.c
>> @@ -67,6 +67,7 @@ struct ic_context {
>>     struct ovsdb_idl_index *sbrec_chassis_by_name;
>>     struct ovsdb_idl_index *sbrec_port_binding_by_name;
>>     struct ovsdb_idl_index *icsbrec_port_binding_by_ts;
>> +    struct ovsdb_idl_index *icsbrec_route_by_ts;
>> };
>> 
>> struct ic_state {
>> @@ -1156,7 +1157,14 @@ sync_learned_route(struct ic_context *ctx,
>> {
>>     ovs_assert(ctx->ovnnb_txn);
>>     const struct icsbrec_route *isb_route;
>> -    ICSBREC_ROUTE_FOR_EACH (isb_route, ctx->ovnisb_idl) {
>> +    const struct icsbrec_route *isb_route_key =
>> +        icsbrec_route_index_init_row(ctx->icsbrec_route_by_ts);
>> +
>> +    icsbrec_route_index_set_transit_switch(isb_route_key,
>> +
> ic_lr->isb_pb->transit_switch);
>> +
>> +    ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key,
>> +                                  ctx->icsbrec_route_by_ts) {
>>         if (isb_route->availability_zone == az) {
>>             continue;
>>         }
>> @@ -1208,6 +1216,8 @@ sync_learned_route(struct ic_context *ctx,
>>                 ic_lr->lr, nb_route);
>>         }
>>     }
>> +    icsbrec_route_index_destroy_row(isb_route_key);
>> +
>>     /* Delete extra learned routes. */
>>     struct ic_route_info *route_learned, *next;
>>     HMAP_FOR_EACH_SAFE (route_learned, next, node,
> &ic_lr->routes_learned) {
>> @@ -1678,6 +1688,10 @@ main(int argc, char *argv[])
>>         = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,
>> 
> &icsbrec_port_binding_col_transit_switch);
>> 
>> +    struct ovsdb_idl_index *icsbrec_route_by_ts
>> +        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,
>> +                                  &icsbrec_route_col_transit_switch);
>> +
>>     /* Main loop. */
>>     exiting = false;
>>     state.had_lock = false;
>> @@ -1718,6 +1732,7 @@ main(int argc, char *argv[])
>>                 .sbrec_port_binding_by_name = sbrec_port_binding_by_name,
>>                 .sbrec_chassis_by_name = sbrec_chassis_by_name,
>>                 .icsbrec_port_binding_by_ts = icsbrec_port_binding_by_ts,
>> +                .icsbrec_route_by_ts = icsbrec_route_by_ts,
>>             };
>> 
>>             if (!state.had_lock &&
> ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) {
>> diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at
>> index 2a4fba031..ee78f4794 100644
>> --- a/tests/ovn-ic.at
>> +++ b/tests/ovn-ic.at
>> @@ -315,6 +315,61 @@ OVS_WAIT_WHILE([ovn_as az2 ovn-nbctl lr-route-list
> lr2 | grep learned | grep 192
>> # AZ1 shouldn't learn 10.11 any more.
>> OVS_WAIT_WHILE([ovn_as az1 ovn-nbctl lr-route-list lr1 | grep learned |
> grep 10.11])
>> 
>> +# cleanup
>> +ovn-ic-nbctl --if-exists ts-del ts1
>> +ovn_as az1 ovn-nbctl lr-del lr1
>> +ovn_as az2 ovn-nbctl lr-del lr2
>> +
>> +# Create new transit switches and LRs. Test topology is next:
>> +# logical router (lr11) - transit switch (ts11) - logical router (lr12)
>> +# logical router (lr21) - transit switch (ts22) - logical router (lr22)
>> +#
>> +# lr12 has static route 10.0.0.0/24 and directly connected network
> 192.168.0.0/24
>> +for i in 1 2; do
>> +    ovn_as az$i
>> +
>> +    # Ensure route learning at AZ level
>> +    ovn-nbctl set nb_global . options:ic-route-learn=true
>> +    # Ensure route advertising at AZ level
>> +    ovn-nbctl set nb_global . options:ic-route-adv=true
>> +    # Drop blacklist
>> +    ovn-nbctl remove nb_global . options ic-route-blacklist
>> +
>> +    for j in 1 2; do
>> +        ts=ts$j$j
>> +        ovn-ic-nbctl --may-exist ts-add $ts
>> +
>> +        # Create LRP and connect to TS
>> +        lr=lr$j$i
>> +        echo lr: $lr, ts: $ts
>> +        ovn-nbctl lr-add $lr
>> +        ovn-nbctl lrp-add $lr lrp-$lr-$ts aa:aa:aa:aa:aa:0$j
> 169.254.100.$i/24
>> +        ovn-nbctl lsp-add $ts lsp-$ts-$lr \
>> +                -- lsp-set-addresses lsp-$ts-$lr router \
>> +                -- lsp-set-type lsp-$ts-$lr router \
>> +                -- lsp-set-options lsp-$ts-$lr router-port=lrp-$lr-$ts
>> +    done
>> +done
>> +
>> +# Create directly-connected routes
>> +ovn_as az2 ovn-nbctl lrp-add lr12 lrp-lr12-ls2 aa:aa:aa:aa:bb:01 "
> 192.168.0.1/24"
>> +ovn_as az2 ovn-nbctl lr-route-add lr12 10.10.10.0/24 192.168.0.10
>> +
>> +echo az1
>> +ovn_as az1 ovn-nbctl show
>> +echo az2
>> +ovn_as az2 ovn-nbctl show
>> +
>> +# Test routes from lr12 were learned to lr11
>> +AT_CHECK([ovn_as az1 ovn-nbctl lr-route-list lr11 |
>> +             grep learned | awk '{print $1, $2}' | sort], [0], [dnl
>> +10.10.10.0/24 169.254.100.2
>> +192.168.0.0/24 169.254.100.2
>> +])
>> +
>> +# Test routes from lr12 didn't leak as learned to lr21
>> +AT_CHECK([ovn_as az1 ovn-nbctl lr-route-list lr21], [0], [])
>> +
>> OVN_CLEANUP_IC([az1], [az2])
>> 
>> AT_CLEANUP
>> --
>> 2.30.0
>> 
>> _______________________________________________
>> dev mailing list
>> dev@openvswitch.org
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> 
> Thanks Vladislav. I applied to all branches.
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
diff mbox series

Patch

diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c
index d69583956..75e798cd1 100644
--- a/ic/ovn-ic.c
+++ b/ic/ovn-ic.c
@@ -67,6 +67,7 @@  struct ic_context {
     struct ovsdb_idl_index *sbrec_chassis_by_name;
     struct ovsdb_idl_index *sbrec_port_binding_by_name;
     struct ovsdb_idl_index *icsbrec_port_binding_by_ts;
+    struct ovsdb_idl_index *icsbrec_route_by_ts;
 };
 
 struct ic_state {
@@ -1156,7 +1157,14 @@  sync_learned_route(struct ic_context *ctx,
 {
     ovs_assert(ctx->ovnnb_txn);
     const struct icsbrec_route *isb_route;
-    ICSBREC_ROUTE_FOR_EACH (isb_route, ctx->ovnisb_idl) {
+    const struct icsbrec_route *isb_route_key =
+        icsbrec_route_index_init_row(ctx->icsbrec_route_by_ts);
+
+    icsbrec_route_index_set_transit_switch(isb_route_key,
+                                           ic_lr->isb_pb->transit_switch);
+
+    ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key,
+                                  ctx->icsbrec_route_by_ts) {
         if (isb_route->availability_zone == az) {
             continue;
         }
@@ -1208,6 +1216,8 @@  sync_learned_route(struct ic_context *ctx,
                 ic_lr->lr, nb_route);
         }
     }
+    icsbrec_route_index_destroy_row(isb_route_key);
+
     /* Delete extra learned routes. */
     struct ic_route_info *route_learned, *next;
     HMAP_FOR_EACH_SAFE (route_learned, next, node, &ic_lr->routes_learned) {
@@ -1678,6 +1688,10 @@  main(int argc, char *argv[])
         = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,
                                   &icsbrec_port_binding_col_transit_switch);
 
+    struct ovsdb_idl_index *icsbrec_route_by_ts
+        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,
+                                  &icsbrec_route_col_transit_switch);
+
     /* Main loop. */
     exiting = false;
     state.had_lock = false;
@@ -1718,6 +1732,7 @@  main(int argc, char *argv[])
                 .sbrec_port_binding_by_name = sbrec_port_binding_by_name,
                 .sbrec_chassis_by_name = sbrec_chassis_by_name,
                 .icsbrec_port_binding_by_ts = icsbrec_port_binding_by_ts,
+                .icsbrec_route_by_ts = icsbrec_route_by_ts,
             };
 
             if (!state.had_lock && ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) {
diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at
index 2a4fba031..ee78f4794 100644
--- a/tests/ovn-ic.at
+++ b/tests/ovn-ic.at
@@ -315,6 +315,61 @@  OVS_WAIT_WHILE([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 192
 # AZ1 shouldn't learn 10.11 any more.
 OVS_WAIT_WHILE([ovn_as az1 ovn-nbctl lr-route-list lr1 | grep learned | grep 10.11])
 
+# cleanup
+ovn-ic-nbctl --if-exists ts-del ts1
+ovn_as az1 ovn-nbctl lr-del lr1
+ovn_as az2 ovn-nbctl lr-del lr2
+
+# Create new transit switches and LRs. Test topology is next:
+# logical router (lr11) - transit switch (ts11) - logical router (lr12)
+# logical router (lr21) - transit switch (ts22) - logical router (lr22)
+#
+# lr12 has static route 10.0.0.0/24 and directly connected network 192.168.0.0/24
+for i in 1 2; do
+    ovn_as az$i
+
+    # Ensure route learning at AZ level
+    ovn-nbctl set nb_global . options:ic-route-learn=true
+    # Ensure route advertising at AZ level
+    ovn-nbctl set nb_global . options:ic-route-adv=true
+    # Drop blacklist
+    ovn-nbctl remove nb_global . options ic-route-blacklist
+
+    for j in 1 2; do
+        ts=ts$j$j
+        ovn-ic-nbctl --may-exist ts-add $ts
+
+        # Create LRP and connect to TS
+        lr=lr$j$i
+        echo lr: $lr, ts: $ts
+        ovn-nbctl lr-add $lr
+        ovn-nbctl lrp-add $lr lrp-$lr-$ts aa:aa:aa:aa:aa:0$j 169.254.100.$i/24
+        ovn-nbctl lsp-add $ts lsp-$ts-$lr \
+                -- lsp-set-addresses lsp-$ts-$lr router \
+                -- lsp-set-type lsp-$ts-$lr router \
+                -- lsp-set-options lsp-$ts-$lr router-port=lrp-$lr-$ts
+    done
+done
+
+# Create directly-connected routes
+ovn_as az2 ovn-nbctl lrp-add lr12 lrp-lr12-ls2 aa:aa:aa:aa:bb:01 "192.168.0.1/24"
+ovn_as az2 ovn-nbctl lr-route-add lr12 10.10.10.0/24 192.168.0.10
+
+echo az1
+ovn_as az1 ovn-nbctl show
+echo az2
+ovn_as az2 ovn-nbctl show
+
+# Test routes from lr12 were learned to lr11
+AT_CHECK([ovn_as az1 ovn-nbctl lr-route-list lr11 |
+             grep learned | awk '{print $1, $2}' | sort], [0], [dnl
+10.10.10.0/24 169.254.100.2
+192.168.0.0/24 169.254.100.2
+])
+
+# Test routes from lr12 didn't leak as learned to lr21
+AT_CHECK([ovn_as az1 ovn-nbctl lr-route-list lr21], [0], [])
+
 OVN_CLEANUP_IC([az1], [az2])
 
 AT_CLEANUP