For route lookup based on the destination address a single routing table
is sufficient. For a more advanced routing when a lookup needs to take
into consideration other parameters, such as a source address, a
multi-table lookup is needed.

This change introduces infrastructure for using multiple routing
tables that can be added dynamically, as a pre-step towards importing
non-default routing tables from kernel.

Signed-off-by: Dima Chumak <dchu...@nvidia.com>
---
 lib/netdev-dummy.c            |  14 ++-
 lib/ovs-router.c              | 159 +++++++++++++++++++++++++++-------
 lib/ovs-router.h              |  13 ++-
 lib/route-table.c             |   6 +-
 tests/nsh.at                  |   9 +-
 tests/ofproto-dpif.at         |   9 +-
 tests/ovs-router.at           |  36 +++++---
 tests/packet-type-aware.at    |  15 ++--
 tests/tunnel-push-pop-ipv6.at |  30 ++++---
 tests/tunnel-push-pop.at      |  42 ++++++---
 tests/tunnel.at               |   6 +-
 11 files changed, 249 insertions(+), 90 deletions(-)

diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index b72820fcc506..bad86d3c4c76 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
@@ -2221,10 +2221,13 @@ netdev_dummy_ip4addr(struct unixctl_conn *conn, int 
argc OVS_UNUSED,
             mask.s_addr = be32_prefix_mask(plen);
             netdev_dummy_add_in4(netdev, ip, mask);
 
-            /* Insert local route entry for the new address. */
             in6_addr_set_mapped_ipv4(&ip6, ip.s_addr);
-            ovs_router_force_insert(0, &ip6, plen + 96, true, argv[1],
-                                    &in6addr_any, &ip6);
+            /* Insert local route entry for the new address. */
+            ovs_router_force_insert(CLS_MAIN, 0, &ip6, 32 + 96, true,
+                                    argv[1], &in6addr_any, &ip6);
+            /* Insert network route entry for the new address. */
+            ovs_router_force_insert(CLS_MAIN, 0, &ip6, plen + 96, false,
+                                    argv[1], &in6addr_any, &ip6);
 
             unixctl_command_reply(conn, "OK");
         } else {
@@ -2257,7 +2260,10 @@ netdev_dummy_ip6addr(struct unixctl_conn *conn, int argc 
OVS_UNUSED,
             netdev_dummy_add_in6(netdev, &ip6, &mask);
 
             /* Insert local route entry for the new address. */
-            ovs_router_force_insert(0, &ip6, plen, true, argv[1],
+            ovs_router_force_insert(CLS_MAIN, 0, &ip6, 128, true, argv[1],
+                                    &in6addr_any, &ip6);
+            /* Insert network route entry for the new address. */
+            ovs_router_force_insert(CLS_MAIN, 0, &ip6, plen, false, argv[1],
                                     &in6addr_any, &ip6);
 
             unixctl_command_reply(conn, "OK");
diff --git a/lib/ovs-router.c b/lib/ovs-router.c
index 2827a6e43574..0fcaf1dc7443 100644
--- a/lib/ovs-router.c
+++ b/lib/ovs-router.c
@@ -33,6 +33,7 @@
 #include "classifier.h"
 #include "command-line.h"
 #include "compiler.h"
+#include "cmap.h"
 #include "dpif.h"
 #include "fatal-signal.h"
 #include "openvswitch/dynamic-string.h"
@@ -50,10 +51,16 @@
 
 VLOG_DEFINE_THIS_MODULE(ovs_router);
 
+struct clsmap_node {
+    struct cmap_node cmap_node;
+    struct classifier cls;
+    uint32_t table;
+};
+
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 
 static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER;
-static struct classifier cls;
+static struct cmap clsmap OVS_GUARDED_BY(mutex) = CMAP_INITIALIZER;
 
 /* By default, use the system routing table.  For system-independent testing,
  * the unit tests disable using the system routing table. */
@@ -71,6 +78,52 @@ struct ovs_router_entry {
     uint32_t mark;
 };
 
+static void
+rt_entry_delete__(const struct cls_rule *cr, struct classifier *cls);
+
+static struct classifier *
+cls_find(uint32_t table)
+{
+    struct clsmap_node *node;
+
+    CMAP_FOR_EACH_WITH_HASH (node, cmap_node, hash_int(table, 0), &clsmap) {
+        if (node->table == table) {
+            return &node->cls;
+        }
+    }
+
+    return NULL;
+}
+
+static struct classifier *
+cls_create(uint32_t table)
+{
+    struct clsmap_node *node;
+
+    node = xmalloc(sizeof *node);
+    classifier_init(&node->cls, NULL);
+    node->table = table;
+    ovs_mutex_lock(&mutex);
+    cmap_insert(&clsmap, &node->cmap_node, hash_int(table, 0));
+    ovs_mutex_unlock(&mutex);
+
+    return &node->cls;
+}
+
+static void
+cls_flush(struct classifier *cls, bool flush_all)
+{
+    struct ovs_router_entry *rt;
+
+    classifier_defer(cls);
+    CLS_FOR_EACH (rt, cr, cls) {
+        if (flush_all || rt->priority == rt->plen || rt->local) {
+            rt_entry_delete__(&rt->cr, cls);
+        }
+    }
+    classifier_publish(cls);
+}
+
 static struct ovs_router_entry *
 ovs_router_entry_cast(const struct cls_rule *cr)
 {
@@ -110,15 +163,20 @@ ovs_router_lookup(uint32_t mark, const struct in6_addr 
*ip6_dst,
                   char output_netdev[],
                   struct in6_addr *src, struct in6_addr *gw)
 {
-    const struct cls_rule *cr;
     struct flow flow = {.ipv6_dst = *ip6_dst, .pkt_mark = mark};
+    struct classifier *cls_main = cls_find(CLS_MAIN);
+    const struct cls_rule *cr;
+
+    if (!cls_main) {
+        return false;
+    }
 
     if (src && ipv6_addr_is_set(src)) {
         const struct cls_rule *cr_src;
         struct flow flow_src = {.ipv6_dst = *src, .pkt_mark = mark};
 
-        cr_src = classifier_lookup(&cls, OVS_VERSION_MAX, &flow_src, NULL,
-                                   NULL);
+        cr_src = classifier_lookup(cls_main, OVS_VERSION_MAX, &flow_src,
+                                   NULL, NULL);
         if (cr_src) {
             struct ovs_router_entry *p_src = ovs_router_entry_cast(cr_src);
             if (!p_src->local) {
@@ -129,7 +187,7 @@ ovs_router_lookup(uint32_t mark, const struct in6_addr 
*ip6_dst,
         }
     }
 
-    cr = classifier_lookup(&cls, OVS_VERSION_MAX, &flow, NULL, NULL);
+    cr = classifier_lookup(cls_main, OVS_VERSION_MAX, &flow, NULL, NULL);
     if (cr) {
         struct ovs_router_entry *p = ovs_router_entry_cast(cr);
 
@@ -257,8 +315,8 @@ out:
 }
 
 static int
-ovs_router_insert__(uint32_t mark, uint8_t priority, bool local,
-                    const struct in6_addr *ip6_dst,
+ovs_router_insert__(uint32_t table, uint32_t mark, uint8_t priority,
+                    bool local, const struct in6_addr *ip6_dst,
                     uint8_t plen, const char output_netdev[],
                     const struct in6_addr *gw,
                     const struct in6_addr *ip6_src)
@@ -268,6 +326,7 @@ ovs_router_insert__(uint32_t mark, uint8_t priority, bool 
local,
                         struct in6_addr *prefsrc);
     const struct cls_rule *cr;
     struct ovs_router_entry *p;
+    struct classifier *cls;
     struct match match;
     int err;
 
@@ -307,8 +366,12 @@ ovs_router_insert__(uint32_t mark, uint8_t priority, bool 
local,
     /* Longest prefix matches first. */
     cls_rule_init(&p->cr, &match, priority);
 
+    cls = cls_find(table);
+    if (!cls) {
+        cls = cls_create(table);
+    }
     ovs_mutex_lock(&mutex);
-    cr = classifier_replace(&cls, &p->cr, OVS_VERSION_MIN, NULL, 0);
+    cr = classifier_replace(cls, &p->cr, OVS_VERSION_MIN, NULL, 0);
     ovs_mutex_unlock(&mutex);
 
     if (cr) {
@@ -321,13 +384,13 @@ ovs_router_insert__(uint32_t mark, uint8_t priority, bool 
local,
 }
 
 void
-ovs_router_insert(uint32_t mark, const struct in6_addr *ip_dst, uint8_t plen,
-                  bool local, const char output_netdev[],
+ovs_router_insert(uint32_t table, uint32_t mark, const struct in6_addr *ip_dst,
+                  uint8_t plen, bool local, const char output_netdev[],
                   const struct in6_addr *gw, const struct in6_addr *prefsrc)
 {
     if (use_system_routing_table) {
         uint8_t priority = local ? plen + 64 : plen;
-        ovs_router_insert__(mark, priority, local, ip_dst, plen,
+        ovs_router_insert__(table, mark, priority, local, ip_dst, plen,
                             output_netdev, gw, prefsrc);
     }
 }
@@ -335,24 +398,25 @@ ovs_router_insert(uint32_t mark, const struct in6_addr 
*ip_dst, uint8_t plen,
 /* The same as 'ovs_router_insert', but it adds the route even if updates
  * from the system routing table are disabled.  Used for unit tests. */
 void
-ovs_router_force_insert(uint32_t mark, const struct in6_addr *ip_dst,
+ovs_router_force_insert(uint32_t table, uint32_t mark,
+                        const struct in6_addr *ip_dst,
                         uint8_t plen, bool local, const char output_netdev[],
                         const struct in6_addr *gw,
                         const struct in6_addr *prefsrc)
 {
     uint8_t priority = local ? plen + 64 : plen;
 
-    ovs_router_insert__(mark, priority, local, ip_dst, plen,
+    ovs_router_insert__(table, mark, priority, local, ip_dst, plen,
                         output_netdev, gw, prefsrc);
 }
 
 static void
-rt_entry_delete__(const struct cls_rule *cr)
+rt_entry_delete__(const struct cls_rule *cr, struct classifier *cls)
 {
     struct ovs_router_entry *p = ovs_router_entry_cast(cr);
 
     tnl_port_map_delete_ipdev(p->output_netdev);
-    classifier_remove_assert(&cls, cr);
+    classifier_remove_assert(cls, cr);
     ovsrcu_postpone(rt_entry_free, ovs_router_entry_cast(cr));
 }
 
@@ -360,20 +424,25 @@ static bool
 rt_entry_delete(uint32_t mark, uint8_t priority,
                 const struct in6_addr *ip6_dst, uint8_t plen)
 {
+    struct classifier *cls_main = cls_find(CLS_MAIN);
     const struct cls_rule *cr;
     struct cls_rule rule;
     struct match match;
     bool res = false;
 
+    if (!cls_main) {
+        return false;
+    }
+
     rt_init_match(&match, mark, ip6_dst, plen);
 
     cls_rule_init(&rule, &match, priority);
 
     /* Find the exact rule. */
-    cr = classifier_find_rule_exactly(&cls, &rule, OVS_VERSION_MAX);
+    cr = classifier_find_rule_exactly(cls_main, &rule, OVS_VERSION_MAX);
     if (cr) {
         ovs_mutex_lock(&mutex);
-        rt_entry_delete__(cr);
+        rt_entry_delete__(cr, cls_main);
         ovs_mutex_unlock(&mutex);
 
         res = true;
@@ -469,8 +538,8 @@ ovs_router_add(struct unixctl_conn *conn, int argc,
         in6_addr_set_mapped_ipv4(&src6, src);
     }
 
-    err = ovs_router_insert__(mark, plen + 32, false, &ip6, plen, argv[2],
-                              &gw6, &src6);
+    err = ovs_router_insert__(CLS_MAIN, mark, plen + 32, false, &ip6, plen,
+                              argv[2], &gw6, &src6);
     if (err) {
         unixctl_command_reply_error(conn, "Error while inserting route.");
     } else {
@@ -512,12 +581,19 @@ ovs_router_del(struct unixctl_conn *conn, int argc 
OVS_UNUSED,
 static void
 ovs_router_show_json(struct json **routes)
 {
-    int n_rules = classifier_count(&cls);
     struct json **json_entries = NULL;
     struct ovs_router_entry *rt;
+    struct classifier *cls_main;
     struct ds ds;
+    int n_rules;
     int i = 0;
 
+    cls_main = cls_find(CLS_MAIN);
+    if (!cls_main) {
+        goto out;
+    }
+
+    n_rules = classifier_count(cls_main);
     if (!n_rules) {
         goto out;
     }
@@ -525,7 +601,7 @@ ovs_router_show_json(struct json **routes)
     json_entries = xmalloc(n_rules * sizeof *json_entries);
     ds_init(&ds);
 
-    CLS_FOR_EACH (rt, cr, &cls) {
+    CLS_FOR_EACH (rt, cr, cls_main) {
         bool user = rt->priority != rt->plen && !rt->local;
         uint8_t plen = rt->plen;
         struct json *json, *nh;
@@ -579,9 +655,15 @@ static void
 ovs_router_show_text(struct ds *ds)
 {
     struct ovs_router_entry *rt;
+    struct classifier *cls_main;
+
+    cls_main = cls_find(CLS_MAIN);
+    if (!cls_main) {
+        return;
+    }
 
     ds_put_format(ds, "Route Table:\n");
-    CLS_FOR_EACH (rt, cr, &cls) {
+    CLS_FOR_EACH (rt, cr, cls_main) {
         uint8_t plen;
         if (rt->priority == rt->plen || rt->local) {
             ds_put_format(ds, "Cached: ");
@@ -668,19 +750,26 @@ ovs_router_lookup_cmd(struct unixctl_conn *conn, int argc,
     }
 }
 
+static void
+clsmap_node_destroy_cb(struct clsmap_node *node)
+{
+    classifier_destroy(&node->cls);
+    ovsrcu_postpone(free, node);
+}
+
 void
-ovs_router_flush(void)
+ovs_router_flush(bool flush_all)
 {
-    struct ovs_router_entry *rt;
+    struct clsmap_node *node;
 
     ovs_mutex_lock(&mutex);
-    classifier_defer(&cls);
-    CLS_FOR_EACH(rt, cr, &cls) {
-        if (rt->priority == rt->plen || rt->local) {
-            rt_entry_delete__(&rt->cr);
+    CMAP_FOR_EACH (node, cmap_node, &clsmap) {
+        cls_flush(&node->cls, flush_all);
+        if (!node->cls.n_rules) {
+            cmap_remove(&clsmap, &node->cmap_node, hash_int(node->table, 0));
+            ovsrcu_postpone(clsmap_node_destroy_cb, node);
         }
     }
-    classifier_publish(&cls);
     ovs_mutex_unlock(&mutex);
     seq_change(tnl_conf_seq);
 }
@@ -688,7 +777,13 @@ ovs_router_flush(void)
 static void
 ovs_router_flush_handler(void *aux OVS_UNUSED)
 {
-    ovs_router_flush();
+    ovs_router_flush(true);
+
+    ovs_mutex_lock(&mutex);
+    ovs_assert(cmap_is_empty(&clsmap));
+    cmap_destroy(&clsmap);
+    cmap_init(&clsmap);
+    ovs_mutex_unlock(&mutex);
 }
 
 void
@@ -697,8 +792,10 @@ ovs_router_init(void)
     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
 
     if (ovsthread_once_start(&once)) {
+        ovs_mutex_lock(&mutex);
+        cmap_init(&clsmap);
+        ovs_mutex_unlock(&mutex);
         fatal_signal_add_hook(ovs_router_flush_handler, NULL, NULL, true);
-        classifier_init(&cls, NULL);
         unixctl_command_register("ovs/route/add",
                                  "ip/plen dev [gw] "
                                  "[pkt_mark=mark] [src=src_ip]",
diff --git a/lib/ovs-router.h b/lib/ovs-router.h
index b61712707b1e..f4e6487d3dc6 100644
--- a/lib/ovs-router.h
+++ b/lib/ovs-router.h
@@ -26,20 +26,27 @@
 extern "C" {
 #endif
 
+enum {
+    CLS_MAIN = 254,
+    CLS_ALL = UINT32_MAX,
+};
+
 bool ovs_router_lookup(uint32_t mark, const struct in6_addr *ip_dst,
                        char output_netdev[],
                        struct in6_addr *src, struct in6_addr *gw);
 void ovs_router_init(void);
-void ovs_router_insert(uint32_t mark, const struct in6_addr *ip_dst,
+void ovs_router_insert(uint32_t table, uint32_t mark,
+                       const struct in6_addr *ip_dst,
                        uint8_t plen, bool local,
                        const char output_netdev[], const struct in6_addr *gw,
                        const struct in6_addr *prefsrc);
-void ovs_router_force_insert(uint32_t mark, const struct in6_addr *ip_dst,
+void ovs_router_force_insert(uint32_t table, uint32_t mark,
+                             const struct in6_addr *ip_dst,
                              uint8_t plen, bool local,
                              const char output_netdev[],
                              const struct in6_addr *gw,
                              const struct in6_addr *prefsrc);
-void ovs_router_flush(void);
+void ovs_router_flush(bool flush_all);
 
 void ovs_router_disable_system_routing_table(void);
 
diff --git a/lib/route-table.c b/lib/route-table.c
index 2bbb51c08f7e..96b7d495e1a5 100644
--- a/lib/route-table.c
+++ b/lib/route-table.c
@@ -48,6 +48,8 @@ VLOG_DEFINE_THIS_MODULE(route_table);
 
 COVERAGE_DEFINE(route_table_dump);
 
+BUILD_ASSERT_DECL((enum rt_class_t) CLS_MAIN == RT_TABLE_MAIN);
+
 static struct ovs_mutex route_table_mutex = OVS_MUTEX_INITIALIZER;
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
 
@@ -556,7 +558,7 @@ route_table_handle_msg(const struct route_table_msg *change,
         rdnh = CONTAINER_OF(ovs_list_front(&change->rd.nexthops),
                             const struct route_data_nexthop, nexthop_node);
 
-        ovs_router_insert(rd->rta_mark, &rd->rta_dst,
+        ovs_router_insert(CLS_MAIN, rd->rta_mark, &rd->rta_dst,
                           IN6_IS_ADDR_V4MAPPED(&rd->rta_dst)
                           ? rd->rtm_dst_len + 96 : rd->rtm_dst_len,
                           rd->rtn_local, rdnh->ifname, &rdnh->addr,
@@ -567,7 +569,7 @@ route_table_handle_msg(const struct route_table_msg *change,
 static void
 route_map_clear(void)
 {
-    ovs_router_flush();
+    ovs_router_flush(false);
 }
 
 bool
diff --git a/tests/nsh.at b/tests/nsh.at
index 0040a50b36c5..b4da9b118bae 100644
--- a/tests/nsh.at
+++ b/tests/nsh.at
@@ -557,9 +557,12 @@ AT_CHECK([
 AT_CHECK([
     ovs-appctl ovs/route/show | grep Cached: | sort
 ], [0], [dnl
-Cached: 10.0.0.0/24 dev br-p1 SRC 10.0.0.1 local
-Cached: 20.0.0.0/24 dev br-p2 SRC 20.0.0.2 local
-Cached: 30.0.0.0/24 dev br-p3 SRC 30.0.0.3 local
+Cached: 10.0.0.0/24 dev br-p1 SRC 10.0.0.1
+Cached: 10.0.0.1/32 dev br-p1 SRC 10.0.0.1 local
+Cached: 20.0.0.0/24 dev br-p2 SRC 20.0.0.2
+Cached: 20.0.0.2/32 dev br-p2 SRC 20.0.0.2 local
+Cached: 30.0.0.0/24 dev br-p3 SRC 30.0.0.3
+Cached: 30.0.0.3/32 dev br-p3 SRC 30.0.0.3 local
 ])
 
 AT_CHECK([
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index a0cd4a5cec95..dd2a38cfe126 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -8504,7 +8504,8 @@ AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 
1.1.2.88/24], [0], [OK
 AT_CHECK([ovs-ofctl add-flow br0 action=normal])
 dnl Checking that a local route for added IP was successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
-Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
+Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88
 ])
 
 dnl Prime ARP Cache for 1.1.2.92
@@ -8521,8 +8522,10 @@ AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 
192.168.1.1/16], [0], [OK
 ])
 dnl Checking that a local route for added IP was successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl
-Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
-Cached: 192.168.0.0/16 dev br0 SRC 192.168.1.1 local
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88
+Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local
+Cached: 192.168.0.0/16 dev br0 SRC 192.168.1.1
+Cached: 192.168.1.1/32 dev br0 SRC 192.168.1.1 local
 ])
 
 dnl add rule for int-br to force packet onto tunnel. There is no ifindex
diff --git a/tests/ovs-router.at b/tests/ovs-router.at
index 641b780a582a..d5f56da786d9 100644
--- a/tests/ovs-router.at
+++ b/tests/ovs-router.at
@@ -31,14 +31,35 @@ User: 2.2.2.3/32 MARK 1 dev br0 SRC 2.2.2.2
 AT_CHECK([ovs-appctl --format=json --pretty ovs/route/show], [0], [dnl
 [[
   {
-    "dst": "2.2.2.0",
+    "dst": "2.2.2.2",
     "local": true,
+    "nexthops": [
+      {
+        "dev": "br0"}],
+    "prefix": 32,
+    "prefsrc": "2.2.2.2",
+    "priority": 192,
+    "user": false},
+  {
+    "dst": "2.2.2.3",
+    "local": false,
+    "mark": 1,
+    "nexthops": [
+      {
+        "dev": "br0"}],
+    "prefix": 32,
+    "prefsrc": "2.2.2.2",
+    "priority": 160,
+    "user": true},
+  {
+    "dst": "2.2.2.0",
+    "local": false,
     "nexthops": [
       {
         "dev": "br0"}],
     "prefix": 24,
     "prefsrc": "2.2.2.2",
-    "priority": 184,
+    "priority": 120,
     "user": false},
   {
     "dst": "1.1.1.0",
@@ -62,17 +83,6 @@ AT_CHECK([ovs-appctl --format=json --pretty ovs/route/show], 
[0], [dnl
     "prefix": 24,
     "prefsrc": "2.2.2.2",
     "priority": 152,
-    "user": true},
-  {
-    "dst": "2.2.2.3",
-    "local": false,
-    "mark": 1,
-    "nexthops": [
-      {
-        "dev": "br0"}],
-    "prefix": 32,
-    "prefsrc": "2.2.2.2",
-    "priority": 160,
     "user": true}]]
 ])
 OVS_VSWITCHD_STOP
diff --git a/tests/packet-type-aware.at b/tests/packet-type-aware.at
index d634930fd529..3161fddcd37e 100644
--- a/tests/packet-type-aware.at
+++ b/tests/packet-type-aware.at
@@ -160,9 +160,12 @@ AT_CHECK([
 AT_CHECK([
     ovs-appctl ovs/route/show | grep Cached: | sort
 ], [0], [dnl
-Cached: 10.0.0.0/24 dev br-p1 SRC 10.0.0.1 local
-Cached: 20.0.0.0/24 dev br-p2 SRC 20.0.0.2 local
-Cached: 30.0.0.0/24 dev br-p3 SRC 30.0.0.3 local
+Cached: 10.0.0.0/24 dev br-p1 SRC 10.0.0.1
+Cached: 10.0.0.1/32 dev br-p1 SRC 10.0.0.1 local
+Cached: 20.0.0.0/24 dev br-p2 SRC 20.0.0.2
+Cached: 20.0.0.2/32 dev br-p2 SRC 20.0.0.2 local
+Cached: 30.0.0.0/24 dev br-p3 SRC 30.0.0.3
+Cached: 30.0.0.3/32 dev br-p3 SRC 30.0.0.3 local
 ])
 
 AT_CHECK([
@@ -684,7 +687,8 @@ AT_CHECK([
 AT_CHECK([
     ovs-appctl ovs/route/show | grep Cached:
 ], [0], [dnl
-Cached: 10.0.0.0/24 dev br2 SRC 10.0.0.1 local
+Cached: 10.0.0.1/32 dev br2 SRC 10.0.0.1 local
+Cached: 10.0.0.0/24 dev br2 SRC 10.0.0.1
 ])
 
 
@@ -960,7 +964,8 @@ ovs-appctl time/warp 1000
 AT_CHECK([
     ovs-appctl ovs/route/show | grep Cached:
 ],[0], [dnl
-Cached: 20.0.0.0/24 dev br0 SRC 20.0.0.1 local
+Cached: 20.0.0.1/32 dev br0 SRC 20.0.0.1 local
+Cached: 20.0.0.0/24 dev br0 SRC 20.0.0.1
 ])
 
 AT_CHECK([
diff --git a/tests/tunnel-push-pop-ipv6.at b/tests/tunnel-push-pop-ipv6.at
index 39fbd2d35f55..2c8c9d9fb881 100644
--- a/tests/tunnel-push-pop-ipv6.at
+++ b/tests/tunnel-push-pop-ipv6.at
@@ -24,7 +24,8 @@ AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 
2001:cafe::88/24], [0], [OK
 ])
 dnl Checking that a local routes for added IPs were successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
-Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88 local
+Cached: 2001:cafe::88/128 dev br0 SRC 2001:cafe::88 local
+Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88
 ])
 AT_CHECK([ovs-appctl tnl/neigh/set br0 2001:cafe::91 aa:55:aa:55:00:01], [0], 
[OK
 ])
@@ -113,8 +114,10 @@ AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 
1.1.2.88/24], [0], [OK
 ])
 dnl Checking that a local routes for added IPs were successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl
-Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
-Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88 local
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88
+Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local
+Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88
+Cached: 2001:cafe::88/128 dev br0 SRC 2001:cafe::88 local
 ])
 
 AT_CHECK([ovs-ofctl add-flow br0 action=normal])
@@ -189,8 +192,10 @@ AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 
1.1.2.88/24], [0], [OK
 ])
 dnl Checking that a local routes for added IPs were successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl
-Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
-Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88 local
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88
+Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local
+Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88
+Cached: 2001:cafe::88/128 dev br0 SRC 2001:cafe::88 local
 ])
 
 AT_CHECK([ovs-ofctl add-flow br0 action=normal])
@@ -328,8 +333,10 @@ AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 
1.1.2.88/24], [0], [OK
 ])
 dnl Checking that a local routes for added IPs were successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl
-Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
-Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88 local
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88
+Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local
+Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88
+Cached: 2001:cafe::88/128 dev br0 SRC 2001:cafe::88 local
 ])
 
 AT_CHECK([ovs-ofctl add-flow br0 action=normal])
@@ -701,8 +708,10 @@ AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 
2001:beef::88/64], [0], [OK
 ])
 dnl Checking that a local route for added IP was successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl
-Cached: 2001:beef::/64 dev br0 SRC 2001:beef::88 local
-Cached: 2001:cafe::/64 dev br0 SRC 2001:cafe::88 local
+Cached: 2001:beef::/64 dev br0 SRC 2001:beef::88
+Cached: 2001:beef::88/128 dev br0 SRC 2001:beef::88 local
+Cached: 2001:cafe::/64 dev br0 SRC 2001:cafe::88
+Cached: 2001:cafe::88/128 dev br0 SRC 2001:cafe::88 local
 ])
 AT_CHECK([ovs-ofctl add-flow br0 action=normal])
 AT_CHECK([ovs-ofctl add-flow int-br action=normal])
@@ -784,7 +793,8 @@ AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 
2001:cafe::88/64], [0], [OK
 ])
 dnl Checking that a local route for added IP was successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl
-Cached: 2001:cafe::/64 dev br0 SRC 2001:cafe::88 local
+Cached: 2001:cafe::/64 dev br0 SRC 2001:cafe::88
+Cached: 2001:cafe::88/128 dev br0 SRC 2001:cafe::88 local
 ])
 
 dnl Add a dp-hash selection group.
diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
index 64c41460bbb2..dfd967e9802d 100644
--- a/tests/tunnel-push-pop.at
+++ b/tests/tunnel-push-pop.at
@@ -37,8 +37,10 @@ AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 
2001:cafe::88/24], [0], [OK
 ])
 dnl Checking that a local routes for added IPs were successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl
-Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
-Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88 local
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88
+Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local
+Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88
+Cached: 2001:cafe::88/128 dev br0 SRC 2001:cafe::88 local
 ])
 
 AT_CHECK([ovs-ofctl add-flow br0 action=normal])
@@ -246,8 +248,10 @@ AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 br0 
pkt_mark=1234], [0], [OK
 dnl Checking that local routes for added IPs and the static route with a mark
 dnl were successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep br0 | sort], [0], [dnl
-Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
-Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88 local
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88
+Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local
+Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88
+Cached: 2001:cafe::88/128 dev br0 SRC 2001:cafe::88 local
 User: 1.1.2.0/24 MARK 1234 dev br0 SRC 1.1.2.88
 ])
 
@@ -779,7 +783,8 @@ AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], 
[0], [OK
 ])
 dnl Checking that a local route for added IP was successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
-Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
+Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88
 ])
 
 AT_CHECK([ovs-ofctl add-flow br0 action=normal])
@@ -820,7 +825,8 @@ AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], 
[0], [OK
 ])
 dnl Checking that a local route for added IP was successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
-Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
+Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88
 ])
 AT_CHECK([ovs-ofctl add-flow br0 action=normal])
 
@@ -893,8 +899,10 @@ AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 
2.2.2.88/24], [0], [OK
 ])
 dnl Checking that a local route for added IP was successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl
-Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
-Cached: 2.2.2.0/24 dev br0 SRC 2.2.2.88 local
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88
+Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local
+Cached: 2.2.2.0/24 dev br0 SRC 2.2.2.88
+Cached: 2.2.2.88/32 dev br0 SRC 2.2.2.88 local
 ])
 AT_CHECK([ovs-ofctl add-flow br0 action=normal])
 AT_CHECK([ovs-ofctl add-flow int-br action=normal])
@@ -975,7 +983,8 @@ AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], 
[0], [OK
 ])
 dnl Checking that a local route for added IP was successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
-Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
+Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88
 ])
 
 AT_CHECK([ovs-ofctl add-flow br0 'arp,priority=1,action=normal'])
@@ -1025,7 +1034,8 @@ AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 
1.1.2.88/24], [0], [OK
 ])
 dnl Checking that a local route for added IP was successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
-Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
+Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88
 ])
 AT_CHECK([ovs-ofctl add-flow br0 action=normal])
 
@@ -1094,7 +1104,8 @@ AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 
10.0.0.2/24], [0], [OK
 ])
 dnl Checking that a local route for added IP was successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
-Cached: 10.0.0.0/24 dev br0 SRC 10.0.0.2 local
+Cached: 10.0.0.2/32 dev br0 SRC 10.0.0.2 local
+Cached: 10.0.0.0/24 dev br0 SRC 10.0.0.2
 ])
 
 dnl Send an ARP reply to port b8 on br0, so that packets will be forwarded
@@ -1141,7 +1152,8 @@ AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 
10.0.0.2/24], [0], [OK
 ])
 dnl Checking that a local route for added IP was successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
-Cached: 10.0.0.0/24 dev br0 SRC 10.0.0.2 local
+Cached: 10.0.0.2/32 dev br0 SRC 10.0.0.2 local
+Cached: 10.0.0.0/24 dev br0 SRC 10.0.0.2
 ])
 
 dnl Send an ARP reply to port b8 on br0, so that packets will be forwarded
@@ -1213,7 +1225,8 @@ AT_CHECK([ovs-appctl netdev-dummy/ip4addr vtep0 
1.1.2.88/24], [0], [OK
 ])
 dnl Checking that a local route for added IP was successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
-Cached: 1.1.2.0/24 dev vtep0 SRC 1.1.2.88 local
+Cached: 1.1.2.88/32 dev vtep0 SRC 1.1.2.88 local
+Cached: 1.1.2.0/24 dev vtep0 SRC 1.1.2.88
 ])
 
 AT_CHECK([ovs-ofctl add-flow br0 action=normal])
@@ -1277,7 +1290,8 @@ AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 
1.1.2.88/24], [0], [OK
 ])
 dnl Checking that a local route for added IP was successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl
-Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88
+Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local
 ])
 
 dnl Add a dp-hash selection group.
diff --git a/tests/tunnel.at b/tests/tunnel.at
index 09e3c94c7a0a..35d8c581a0f4 100644
--- a/tests/tunnel.at
+++ b/tests/tunnel.at
@@ -529,7 +529,8 @@ AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 
172.31.1.1/24], [0], [OK
 ])
 dnl Checking that a local route for added IP was successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
-Cached: 172.31.1.0/24 dev br0 SRC 172.31.1.1 local
+Cached: 172.31.1.1/32 dev br0 SRC 172.31.1.1 local
+Cached: 172.31.1.0/24 dev br0 SRC 172.31.1.1
 ])
 
 dnl change the flow table to bump the internal table version
@@ -1288,7 +1289,8 @@ AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 
fc00::1/64], [0], [OK
 ])
 dnl Checking that a local route for added IP was successfully installed.
 AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
-Cached: fc00::/64 dev br0 SRC fc00::1 local
+Cached: fc00::1/128 dev br0 SRC fc00::1 local
+Cached: fc00::/64 dev br0 SRC fc00::1
 ])
 
 AT_DATA([flows.txt], [dnl
-- 
2.50.1

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

Reply via email to