diff mbox series

[ovs-dev] ovn-ic: Add support for route tag

Message ID 20240919130740.161652-1-rbartzen@gmail.com
State New
Headers show
Series [ovs-dev] ovn-ic: Add support for route tag | expand

Checks

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

Commit Message

Roberto Bartzen Acosta Sept. 19, 2024, 1:07 p.m. UTC
The OVN-IC feature can handle multiple points of redistribution when
we include more than one TS in the same Logical Router. So, it is a
good idea to use route tagging to prevent learing routes from logical
routers in the same user domain via Transit switch created for
peer-links with another user domain.

This means that there can be a logical separation by user domain
(e.g. VPCs), and a Transit Switch that peers between the different
VPCs, connecting the routers in the VPC1 with the routers in the VPC2,
for example. In this case, the route tag can ensure that the Logical
Routers of VPC1 does not learn routes from VPC1 itself via the peering
TS, avoiding installing additional openflow flows to handle
multipath/ecmp unnecessarily.

To use this route tag feature, new options were created to be configured
in the Logical Router Port connected to the TS. This configuration must
be performed in the LRP insted of the LR because the LRP is the path used
to advertise and learn routes connected to a specific TS (nexthop).

Signed-off-by: Roberto Bartzen Acosta <rbartzen@gmail.com>
---
 ic/ovn-ic.c     |  76 +++++++++++++-----
 ovn-nb.xml      |  27 +++++++
 tests/ovn-ic.at | 200 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 284 insertions(+), 19 deletions(-)

Comments

0-day Robot Sept. 19, 2024, 1:21 p.m. UTC | #1
Bleep bloop.  Greetings Roberto Bartzen Acosta, I am a robot and I have tried out your patch.
Thanks for your contribution.

I encountered some error that I wasn't expecting.  See the details below.


checkpatch:
WARNING: The subject summary should end with a dot.
Subject: ovn-ic: Add support for route tag
ERROR: Author Roberto Bartzen Acosta <roberto.acosta@luizalabs.com> needs to sign off.
WARNING: Unexpected sign-offs from developers who are not authors or co-authors or committers: Roberto Bartzen Acosta <rbartzen@gmail.com>
WARNING: Line is 86 characters long (recommended limit is 79)
#138 FILE: ic/ovn-ic.c:1373:
            route_filter_tag = smap_get_def(&lrp->options, "ic-route-filter-tag", "");

WARNING: Line is 91 characters long (recommended limit is 79)
#150 FILE: ic/ovn-ic.c:1397:
            const char *isb_route_tag = smap_get(&isb_route->external_ids, "ic-route-tag");

WARNING: Line is 88 characters long (recommended limit is 79)
#151 FILE: ic/ovn-ic.c:1398:
            if ((isb_route_tag != NULL) && (!strcmp(isb_route_tag, route_filter_tag))) {

WARNING: Line is 80 characters long (recommended limit is 79)
#180 FILE: ic/ovn-ic.c:1517:
            icsbrec_route_update_external_ids_delkey(isb_route, "ic-route-tag");

Lines checked: 494, Warnings: 6, Errors: 1


Please check this out.  If you feel there has been an error, please email aconole@redhat.com

Thanks,
0-day Robot
diff mbox series

Patch

diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c
index 69bac4ab2..9ba206044 100644
--- a/ic/ovn-ic.c
+++ b/ic/ovn-ic.c
@@ -874,6 +874,7 @@  struct ic_route_info {
     struct in6_addr nexthop;
     const char *origin;
     const char *route_table;
+    const char *route_tag;
 
     const struct nbrec_logical_router *nb_lr;
 
@@ -1124,7 +1125,8 @@  add_to_routes_ad(struct hmap *routes_ad, const struct in6_addr prefix,
                  const char *origin, const char *route_table,
                  const struct nbrec_logical_router_port *nb_lrp,
                  const struct nbrec_logical_router_static_route *nb_route,
-                 const struct nbrec_logical_router *nb_lr)
+                 const struct nbrec_logical_router *nb_lr,
+                 const char *route_tag)
 {
     if (route_table == NULL) {
         route_table = "";
@@ -1143,6 +1145,7 @@  add_to_routes_ad(struct hmap *routes_ad, const struct in6_addr prefix,
         ic_route->route_table = route_table;
         ic_route->nb_lrp = nb_lrp;
         ic_route->nb_lr = nb_lr;
+        ic_route->route_tag = route_tag;
         hmap_insert(routes_ad, &ic_route->node, hash);
     } else {
         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
@@ -1158,7 +1161,8 @@  add_static_to_routes_ad(
     const struct nbrec_logical_router_static_route *nb_route,
     const struct nbrec_logical_router *nb_lr,
     const struct lport_addresses *nexthop_addresses,
-    const struct smap *nb_options)
+    const struct smap *nb_options,
+    const char *route_tag)
 {
     struct in6_addr prefix, nexthop;
     unsigned int plen;
@@ -1199,7 +1203,7 @@  add_static_to_routes_ad(
     }
 
     add_to_routes_ad(routes_ad, prefix, plen, nexthop, ROUTE_ORIGIN_STATIC,
-                     nb_route->route_table, NULL, nb_route, nb_lr);
+                     nb_route->route_table, NULL, nb_route, nb_lr, route_tag);
 }
 
 static void
@@ -1207,7 +1211,8 @@  add_network_to_routes_ad(struct hmap *routes_ad, const char *network,
                          const struct nbrec_logical_router_port *nb_lrp,
                          const struct lport_addresses *nexthop_addresses,
                          const struct smap *nb_options,
-                         const struct nbrec_logical_router *nb_lr)
+                         const struct nbrec_logical_router *nb_lr,
+                         const char *route_tag)
 {
     struct in6_addr prefix, nexthop;
     unsigned int plen;
@@ -1246,7 +1251,7 @@  add_network_to_routes_ad(struct hmap *routes_ad, const char *network,
 
     /* directly-connected routes go to <main> route table */
     add_to_routes_ad(routes_ad, prefix, plen, nexthop, ROUTE_ORIGIN_CONNECTED,
-                     NULL, nb_lrp, NULL, nb_lr);
+                     NULL, nb_lrp, NULL, nb_lr, route_tag);
 }
 
 static bool
@@ -1315,8 +1320,8 @@  get_lrp_name_by_ts_port_name(struct ic_context *ctx, const char *ts_port_name)
     return smap_get(&nb_lsp->options, "router-port");
 }
 
-static const char *
-get_route_table_by_lrp_name(struct ic_context *ctx, const char *lrp_name)
+static const struct nbrec_logical_router_port *
+get_lrp_by_lrp_name(struct ic_context *ctx, const char *lrp_name)
 {
     const struct nbrec_logical_router_port *lrp;
     const struct nbrec_logical_router_port *lrp_key =
@@ -1326,10 +1331,7 @@  get_route_table_by_lrp_name(struct ic_context *ctx, const char *lrp_name)
                                                lrp_key);
     nbrec_logical_router_port_index_destroy_row(lrp_key);
 
-    if (lrp) {
-        return smap_get_def(&lrp->options, "route_table", "");
-    }
-    return "";  /* <main> route table */
+    return lrp;
 }
 
 static bool
@@ -1359,12 +1361,20 @@  sync_learned_routes(struct ic_context *ctx,
         nbrec_nb_global_first(ctx->ovnnb_idl);
     ovs_assert(nb_global);
 
-    const char *lrp_name, *ts_route_table;
+    const char *lrp_name, *ts_route_table, *route_filter_tag;
     const struct icsbrec_port_binding *isb_pb;
+    const struct nbrec_logical_router_port *lrp;
     for (int i = 0; i < ic_lr->n_isb_pbs; i++) {
         isb_pb = ic_lr->isb_pbs[i];
         lrp_name = get_lrp_name_by_ts_port_name(ctx, isb_pb->logical_port);
-        ts_route_table = get_route_table_by_lrp_name(ctx, lrp_name);
+        lrp = get_lrp_by_lrp_name(ctx, lrp_name);
+        if (lrp) {
+            ts_route_table = smap_get_def(&lrp->options, "route_table", "");
+            route_filter_tag = smap_get_def(&lrp->options, "ic-route-filter-tag", "");
+        } else {
+            ts_route_table = "";
+            route_filter_tag = "";
+        }
 
         isb_route_key = icsbrec_route_index_init_row(ctx->icsbrec_route_by_ts);
         icsbrec_route_index_set_transit_switch(isb_route_key,
@@ -1384,6 +1394,15 @@  sync_learned_routes(struct ic_context *ctx,
                 continue;
             }
 
+            const char *isb_route_tag = smap_get(&isb_route->external_ids, "ic-route-tag");
+            if ((isb_route_tag != NULL) && (!strcmp(isb_route_tag, route_filter_tag))) {
+                VLOG_DBG("Skip learning route %s -> %s as either "
+                         "its route tag %s is filtered by %s of TS LRP ",
+                         isb_route->ip_prefix, isb_route->nexthop,
+                         isb_route_tag, route_filter_tag);
+                continue;
+            }
+
             if (isb_route->route_table[0] &&
                 strcmp(isb_route->route_table, ts_route_table)) {
                 if (VLOG_IS_DBG_ENABLED()) {
@@ -1471,6 +1490,7 @@  ad_route_sync_external_ids(const struct ic_route_info *route_adv,
                            const struct icsbrec_route *isb_route)
 {
     struct uuid isb_ext_id, nb_id, isb_ext_lr_id, lr_id;
+    const char *route_tag;
     smap_get_uuid(&isb_route->external_ids, "nb-id", &isb_ext_id);
     smap_get_uuid(&isb_route->external_ids, "lr-id", &isb_ext_lr_id);
     nb_id = route_adv->nb_route ? route_adv->nb_route->header_.uuid
@@ -1488,6 +1508,15 @@  ad_route_sync_external_ids(const struct ic_route_info *route_adv,
                                                  uuid_s);
         free(uuid_s);
     }
+    if (strcmp(route_adv->route_tag, "")) {
+        icsbrec_route_update_external_ids_setkey(isb_route, "ic-route-tag",
+                                                 route_adv->route_tag);
+    } else {
+        route_tag = smap_get(&isb_route->external_ids, "ic-route-tag");
+        if (route_tag) {
+            icsbrec_route_update_external_ids_delkey(isb_route, "ic-route-tag");
+        }
+    }
 }
 
 /* Sync routes from routes_ad to IC-SB. */
@@ -1580,7 +1609,8 @@  build_ts_routes_to_adv(struct ic_context *ctx,
                        struct hmap *routes_ad,
                        struct lport_addresses *ts_port_addrs,
                        const struct nbrec_nb_global *nb_global,
-                       const char *ts_route_table)
+                       const char *ts_route_table,
+                       const char *route_tag)
 {
     const struct nbrec_logical_router *lr = ic_lr->lr;
 
@@ -1603,7 +1633,7 @@  build_ts_routes_to_adv(struct ic_context *ctx,
         } else if (!strcmp(ts_route_table, nb_route->route_table)) {
             /* It may be a route to be advertised */
             add_static_to_routes_ad(routes_ad, nb_route, lr, ts_port_addrs,
-                                    &nb_global->options);
+                                    &nb_global->options, route_tag);
         }
     }
 
@@ -1615,7 +1645,7 @@  build_ts_routes_to_adv(struct ic_context *ctx,
                 add_network_to_routes_ad(routes_ad, lrp->networks[j], lrp,
                                          ts_port_addrs,
                                          &nb_global->options,
-                                         lr);
+                                         lr, route_tag);
             }
         } else {
             /* The router port of the TS port is ignored. */
@@ -1635,9 +1665,10 @@  collect_lr_routes(struct ic_context *ctx,
     ovs_assert(nb_global);
 
     const struct icsbrec_port_binding *isb_pb;
-    const char *lrp_name, *ts_name, *route_table;
+    const char *lrp_name, *ts_name, *route_table, *route_tag;
     struct lport_addresses ts_port_addrs;
     const struct icnbrec_transit_switch *key;
+    const struct nbrec_logical_router_port *lrp;
 
     struct hmap *routes_ad;
     const struct icnbrec_transit_switch *t_sw;
@@ -1669,9 +1700,16 @@  collect_lr_routes(struct ic_context *ctx,
             continue;
         }
         lrp_name = get_lrp_name_by_ts_port_name(ctx, isb_pb->logical_port);
-        route_table = get_route_table_by_lrp_name(ctx, lrp_name);
+        lrp = get_lrp_by_lrp_name(ctx, lrp_name);
+        if (lrp) {
+            route_table = smap_get_def(&lrp->options, "route_table", "");
+            route_tag = smap_get_def(&lrp->options, "ic-route-tag", "");
+        } else {
+            route_table = "";
+            route_tag = "";
+        }
         build_ts_routes_to_adv(ctx, ic_lr, routes_ad, &ts_port_addrs,
-                               nb_global, route_table);
+                               nb_global, route_table, route_tag);
         destroy_lport_addresses(&ts_port_addrs);
     }
 }
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 2836f58f5..adb9144ae 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -3662,6 +3662,33 @@  or
 
         </ul>
       </column>
+
+      <column name="options" key="ic-route-tag" type='{"type": "string"}'>
+        <p>
+          This option expects a name of a route-tag that's present in the
+          Logical Router Port. If set, it causes any route advertised by
+          the Logical Router Port to include the <code>route-tag</code> in
+          the <code> external_ids </code> register of the advertised route
+          entry in the <ref table="Route" db="OVN_IC_Southbound"/> table of
+          the <ref db="OVN_IC_Southbound"/> database.
+
+          This allows to tag and filter route tags in the process of
+          advertising and learning routes in <code>ovn-ic</code> daemon.
+        </p>
+      </column>
+
+      <column name="options" key="ic-route-filter-tag"
+              type='{"type": "string"}'>
+        <p>
+          This option expects a name of a filtered route-tag that's present
+          in the Logical Router Port. If set, it causes any route learned by
+          the Logical Router Port with the <code>route-tag</code> present in
+          the external_ids register of the advertised route entry in the
+          <ref table="Route" db="OVN_IC_Southbound"/> table of the
+          <ref db="OVN_IC_Southbound"/> database, will be filtered and not
+          learned by the <code>ovn-ic</code> daemon.
+        </p>
+      </column>
     </group>
 
     <group title="Attachment">
diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at
index 9fa41200e..33ad37f2e 100644
--- a/tests/ovn-ic.at
+++ b/tests/ovn-ic.at
@@ -2357,3 +2357,203 @@  OVN_CLEANUP_SBOX([hv2], ["/IGMP Querier enabled without a valid IPv4/d
 OVN_CLEANUP_IC([az1],[az2])
 AT_CLEANUP
 ])
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([ovn-ic -- route tag -- tagging and filtering routes])
+
+ovn_init_ic_db
+ovn-ic-nbctl ts-add ts1
+
+for i in 1 2; do
+    ovn_start az$i
+    ovn_as az$i
+
+    # Enable route learning at AZ level
+    ovn-nbctl set nb_global . options:ic-route-learn=true
+    # Enable route advertising at AZ level
+    ovn-nbctl set nb_global . options:ic-route-adv=true
+done
+
+# Create new transit switches and LRs. Test topology is next:
+# VPC1:
+#                       / transit switch (ts11) \
+# logical router (lr11) - transit switch (ts12) - logical router (lr12)
+#                       \                       /
+#                        transit switch (tspeer)
+# VPC2:                 /                       \
+# logical router (lr21) - transit switch (ts21) - logical router (lr22)
+#                       \ transit switch (ts22) /
+#
+
+# VPC1
+# create lr11, lr12, ts11, ts12 and connect them
+for i in 1 2; do
+    ovn_as az$i
+
+    lr=lr1$i
+    ovn-nbctl lr-add $lr
+
+    for j in 1 2; do
+        ts=ts1$j
+        ovn-ic-nbctl --wait=sb --may-exist ts-add $ts
+
+        lrp=lrp-$lr-$ts
+        lsp=lsp-$ts-$lr
+        # Create LRP and connect to TS
+        ovn-nbctl lrp-add $lr $lrp aa:aa:aa:aa:a$j:0$i 169.254.10$j.$i/24
+        ovn-nbctl lsp-add $ts $lsp \
+                -- lsp-set-addresses $lsp router \
+                -- lsp-set-type $lsp router \
+                -- lsp-set-options $lsp router-port=$lrp
+    done
+done
+
+# VPC2
+# create lr21, lr22, ts21, ts22 and connect them
+for i in 1 2; do
+    ovn_as az$i
+
+    lr=lr2$i
+    ovn-nbctl lr-add $lr
+
+    for j in 1 2; do
+        ts=ts2$j
+        ovn-ic-nbctl --wait=sb --may-exist ts-add $ts
+
+        lrp=lrp-$lr-$ts
+        lsp=lsp-$ts-$lr
+        # Create LRP and connect to TS
+        ovn-nbctl lrp-add $lr $lrp aa:aa:aa:aa:a$j:0$i 169.254.10$j.$i/24
+        ovn-nbctl lsp-add $ts $lsp \
+                -- lsp-set-addresses $lsp router \
+                -- lsp-set-type $lsp router \
+                -- lsp-set-options $lsp router-port=$lrp
+    done
+done
+
+# Create directly-connected route in VPC1
+ovn_as az2 ovn-nbctl lrp-add lr12 lrp-lr12 aa:aa:aa:aa:bb:01 "192.168.0.1/24"
+
+# Create directly-connected route in VPC2
+ovn_as az2 ovn-nbctl --wait=sb lrp-add lr22 lrp-lr22 aa:aa:aa:aa:cc:01 "192.168.1.1/24"
+
+check ovn-ic-nbctl --wait=sb sync
+
+# Test direct routes from lr12 were learned to lr11
+OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep 192.168 |
+             grep learned | awk '{print $1, $2, $5}' | sort ], [0], [dnl
+192.168.0.0/24 169.254.101.2 ecmp
+192.168.0.0/24 169.254.102.2 ecmp
+])
+
+# Test direct routes from lr22 were learned to lr21
+OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr21 | grep 192.168 |
+             grep learned | awk '{print $1, $2, $5}' | sort ], [0], [dnl
+192.168.1.0/24 169.254.101.2 ecmp
+192.168.1.0/24 169.254.102.2 ecmp
+])
+
+# Create peering TS
+ovn-ic-nbctl --wait=sb --may-exist ts-add tspeer
+
+# Create LRPs and connect to the peering TS
+ovn_as az1
+ovn-nbctl lrp-add lr11 lrp-lr11-tspeer aa:aa:aa:aa:11:01 169.254.103.11/24
+ovn-nbctl lsp-add tspeer lsp-tspeer-lr11 \
+        -- lsp-set-addresses lsp-tspeer-lr11 router \
+        -- lsp-set-type lsp-tspeer-lr11 router \
+        -- lsp-set-options lsp-tspeer-lr11 router-port=lrp-lr11-tspeer
+
+ovn_as az2
+ovn-nbctl lrp-add lr12 lrp-lr12-tspeer aa:aa:aa:aa:12:01 169.254.103.12/24
+ovn-nbctl lsp-add tspeer lsp-tspeer-lr12 \
+        -- lsp-set-addresses lsp-tspeer-lr12 router \
+        -- lsp-set-type lsp-tspeer-lr12 router \
+        -- lsp-set-options lsp-tspeer-lr12 router-port=lrp-lr12-tspeer
+
+ovn_as az1
+ovn-nbctl lrp-add lr21 lrp-lr21-tspeer aa:aa:aa:aa:21:01 169.254.103.21/24
+ovn-nbctl lsp-add tspeer lsp-tspeer-lr21 \
+        -- lsp-set-addresses lsp-tspeer-lr21 router \
+        -- lsp-set-type lsp-tspeer-lr21 router \
+        -- lsp-set-options lsp-tspeer-lr21 router-port=lrp-lr21-tspeer
+
+ovn_as az2
+ovn-nbctl lrp-add lr22 lrp-lr22-tspeer aa:aa:aa:aa:22:01 169.254.103.22/24
+ovn-nbctl lsp-add tspeer lsp-tspeer-lr22 \
+        -- lsp-set-addresses lsp-tspeer-lr22 router \
+        -- lsp-set-type lsp-tspeer-lr22 router \
+        -- lsp-set-options lsp-tspeer-lr22 router-port=lrp-lr22-tspeer
+
+check ovn-ic-nbctl --wait=sb sync
+
+# Test direct routes from lr12/lr22 were learned to lr11
+OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep 192.168 |
+             grep learned | awk '{print $1, $2}' | sort ], [0], [dnl
+192.168.0.0/24 169.254.101.2
+192.168.0.0/24 169.254.102.2
+192.168.0.0/24 169.254.103.12
+192.168.1.0/24 169.254.103.22
+])
+
+# Test direct routes from lr22/lr12 were learned to lr21
+OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr21 | grep 192.168 |
+             grep learned | awk '{print $1, $2}' | sort ], [0], [dnl
+192.168.0.0/24 169.254.103.12
+192.168.1.0/24 169.254.101.2
+192.168.1.0/24 169.254.102.2
+192.168.1.0/24 169.254.103.22
+])
+
+# VPC1: Create a route tag for VPC1 mark its own routes via lrp-lr12
+ovn_as az2 ovn-nbctl set logical_router_port lrp-lr12-tspeer options:ic-route-tag=vpc1
+
+# Test advertised routes with the vpc1 route tag present
+ovn-ic-sbctl list route
+wait_row_count ic-sb:Route 1 ip_prefix=192.168.0.1/24 nexthop=169.254.103.12 origin=connected external_ids:ic-route-tag=vpc1
+
+# Filter routes on VPC1 lrp-lr11-tspeer with the route tag vpc1 present
+ovn_as az1 ovn-nbctl set logical_router_port lrp-lr11-tspeer options:ic-route-filter-tag=vpc1
+
+# Test remaining direct routes from lr12 were learned to lr11
+# Routes from the 169.254.101.2 nexthop have been filtered
+OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep 192.168 |
+             grep learned | awk '{print $1, $2}' | sort ], [0], [dnl
+192.168.0.0/24 169.254.101.2
+192.168.0.0/24 169.254.102.2
+192.168.1.0/24 169.254.103.22
+])
+
+# Remove the route tag used for advertisement
+ovn_as az2 ovn-nbctl remove logical_router_port lrp-lr12-tspeer options ic-route-tag=vpc1
+
+# Test advertised routes with the vpc1 route tag present
+ovn-ic-sbctl list route
+wait_row_count ic-sb:Route 0 ip_prefix=192.168.0.1/24 nexthop=169.254.103.12 origin=connected external_ids:ic-route-tag=vpc1
+
+# Test the original direct routes from lr12/lr22 were learned to lr11
+OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep 192.168 |
+             grep learned | awk '{print $1, $2}' | sort ], [0], [dnl
+192.168.0.0/24 169.254.101.2
+192.168.0.0/24 169.254.102.2
+192.168.0.0/24 169.254.103.12
+192.168.1.0/24 169.254.103.22
+])
+
+# Remove route tag filter and add route tag on lrp-lr12-tspeer advertised routes
+ovn_as az1 ovn-nbctl remove logical_router_port lrp-lr11-tspeer options ic-route-filter-tag=vpc1
+ovn_as az2 ovn-nbctl set logical_router_port lrp-lr12-tspeer options:ic-route-tag=vpc1
+
+# Test if all the routes are learned because we no longer have the filter tag option enabled
+OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep 192.168 |
+             grep learned | awk '{print $1, $2}' | sort ], [0], [dnl
+192.168.0.0/24 169.254.101.2
+192.168.0.0/24 169.254.102.2
+192.168.0.0/24 169.254.103.12
+192.168.1.0/24 169.254.103.22
+])
+
+OVN_CLEANUP_IC([az1], [az2])
+
+AT_CLEANUP
+])