| Message ID | 20251027124259.3395209-2-dchumak@nvidia.com |
|---|---|
| State | Changes Requested |
| Delegated to: | Ilya Maximets |
| Headers | show |
| Series | ovs-router: Multi-table routing infrastructure. | expand |
| Context | Check | Description |
|---|---|---|
| ovsrobot/apply-robot | success | apply and check: success |
| ovsrobot/github-robot-_Build_and_Test | success | github build: passed |
| ovsrobot/github-robot-_Build_and_Test | success | github build: passed |
On 10/27/25 1:42 PM, Dima Chumak via dev wrote: > 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 <dchumak@nvidia.com> > --- > lib/netdev-dummy.c | 14 ++- > lib/ovs-router.c | 166 +++++++++++++++++++++++++++------- > 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, 253 insertions(+), 93 deletions(-) Mostly LGTM. Just a couple nits below. > > 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..70644f7bd4f2 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; > + uint32_t table; > + struct classifier cls; > +}; > + > 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 = 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,50 @@ struct ovs_router_entry { > uint32_t mark; > }; > > +static void rt_entry_delete__(const struct cls_rule *, struct classifier *); > + > +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) OVS_REQUIRES(mutex) > +{ > + struct clsmap_node *node; > + > + node = xmalloc(sizeof *node); > + classifier_init(&node->cls, NULL); > + node->table = table; > + cmap_insert(&clsmap, &node->cmap_node, hash_int(table, 0)); > + > + return &node->cls; > +} > + > +static void > +cls_flush(struct classifier *cls, bool flush_all) > + OVS_REQUIRES(mutex) > +{ > + 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 +161,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 +185,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 +313,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 +324,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; > > @@ -308,7 +365,11 @@ ovs_router_insert__(uint32_t mark, uint8_t priority, bool local, > cls_rule_init(&p->cr, &match, priority); > > ovs_mutex_lock(&mutex); > - cr = classifier_replace(&cls, &p->cr, OVS_VERSION_MIN, NULL, 0); > + cls = cls_find(table); > + if (!cls) { > + cls = cls_create(table); > + } > + cr = classifier_replace(cls, &p->cr, OVS_VERSION_MIN, NULL, 0); > ovs_mutex_unlock(&mutex); > > if (cr) { > @@ -321,13 +382,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 +396,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 +422,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 +536,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 +579,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 +599,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 +653,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,27 +748,46 @@ ovs_router_lookup_cmd(struct unixctl_conn *conn, int argc, > } > } > > -void > -ovs_router_flush(void) > +static void > +clsmap_node_destroy_cb(struct clsmap_node *node) > { > - struct ovs_router_entry *rt; > + classifier_destroy(&node->cls); > + ovsrcu_postpone(free, 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); > +static void > +ovs_router_flush_protected(bool flush_all) > + OVS_REQUIRES(mutex) > +{ > + struct clsmap_node *node; > + > + 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); > } > > +void > +ovs_router_flush(bool flush_all) > +{ > + ovs_mutex_lock(&mutex); > + ovs_router_flush_protected(flush_all); > + ovs_mutex_unlock(&mutex); > +} > + > static void > ovs_router_flush_handler(void *aux OVS_UNUSED) > { > - ovs_router_flush(); > + ovs_mutex_lock(&mutex); > + ovs_router_flush_protected(true); > + ovs_assert(cmap_is_empty(&clsmap)); > + cmap_destroy(&clsmap); > + cmap_init(&clsmap); > + ovs_mutex_unlock(&mutex); > } > > void > @@ -698,7 +797,6 @@ ovs_router_init(void) > > if (ovsthread_once_start(&once)) { > 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 ca87ff7dbba4..0e77a9c9325e 100644 > --- a/lib/route-table.c > +++ b/lib/route-table.c > @@ -57,6 +57,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); > > @@ -565,7 +567,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, > @@ -576,7 +578,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 022540dd68a4..3a2f2ed06774 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 7ebbee56d9e6..319640aee5cb 100644 > --- a/tests/ofproto-dpif.at > +++ b/tests/ofproto-dpif.at > @@ -8510,7 +8510,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 Need to add sort to the end, as these are still stored in a single classifier and the order is not defined. This will be less important with the next patches, but seems less brittle nevertheless. > -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 > @@ -8527,8 +8528,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 cebd8e6eeb46..300b17209d83 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: sort > ], [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: sort > ],[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 sort > -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 795817d62246..4108cc4a7dac 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]) > @@ -241,8 +243,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 > ]) > > @@ -778,7 +782,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 sort > -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]) > @@ -821,7 +826,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 sort > -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]) > AT_CHECK([ovs-appctl revalidator/wait]) > @@ -896,8 +902,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]) > @@ -979,7 +987,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 sort > -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']) > @@ -1031,7 +1040,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 sort > -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]) > AT_CHECK([ovs-appctl revalidator/wait]) > @@ -1101,7 +1111,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 sort > -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 > @@ -1149,7 +1160,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 sort > -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 > @@ -1223,7 +1235,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 sort > -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]) > @@ -1288,7 +1301,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 e1a16138fa29..be022f3a087c 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 sort > -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 > @@ -1286,7 +1287,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 sort > -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
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..70644f7bd4f2 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; + uint32_t table; + struct classifier cls; +}; + 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 = 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,50 @@ struct ovs_router_entry { uint32_t mark; }; +static void rt_entry_delete__(const struct cls_rule *, struct classifier *); + +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) OVS_REQUIRES(mutex) +{ + struct clsmap_node *node; + + node = xmalloc(sizeof *node); + classifier_init(&node->cls, NULL); + node->table = table; + cmap_insert(&clsmap, &node->cmap_node, hash_int(table, 0)); + + return &node->cls; +} + +static void +cls_flush(struct classifier *cls, bool flush_all) + OVS_REQUIRES(mutex) +{ + 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 +161,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 +185,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 +313,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 +324,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; @@ -308,7 +365,11 @@ ovs_router_insert__(uint32_t mark, uint8_t priority, bool local, cls_rule_init(&p->cr, &match, priority); ovs_mutex_lock(&mutex); - cr = classifier_replace(&cls, &p->cr, OVS_VERSION_MIN, NULL, 0); + cls = cls_find(table); + if (!cls) { + cls = cls_create(table); + } + cr = classifier_replace(cls, &p->cr, OVS_VERSION_MIN, NULL, 0); ovs_mutex_unlock(&mutex); if (cr) { @@ -321,13 +382,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 +396,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 +422,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 +536,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 +579,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 +599,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 +653,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,27 +748,46 @@ ovs_router_lookup_cmd(struct unixctl_conn *conn, int argc, } } -void -ovs_router_flush(void) +static void +clsmap_node_destroy_cb(struct clsmap_node *node) { - struct ovs_router_entry *rt; + classifier_destroy(&node->cls); + ovsrcu_postpone(free, 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); +static void +ovs_router_flush_protected(bool flush_all) + OVS_REQUIRES(mutex) +{ + struct clsmap_node *node; + + 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); } +void +ovs_router_flush(bool flush_all) +{ + ovs_mutex_lock(&mutex); + ovs_router_flush_protected(flush_all); + ovs_mutex_unlock(&mutex); +} + static void ovs_router_flush_handler(void *aux OVS_UNUSED) { - ovs_router_flush(); + ovs_mutex_lock(&mutex); + ovs_router_flush_protected(true); + ovs_assert(cmap_is_empty(&clsmap)); + cmap_destroy(&clsmap); + cmap_init(&clsmap); + ovs_mutex_unlock(&mutex); } void @@ -698,7 +797,6 @@ ovs_router_init(void) if (ovsthread_once_start(&once)) { 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 ca87ff7dbba4..0e77a9c9325e 100644 --- a/lib/route-table.c +++ b/lib/route-table.c @@ -57,6 +57,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); @@ -565,7 +567,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, @@ -576,7 +578,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 022540dd68a4..3a2f2ed06774 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 7ebbee56d9e6..319640aee5cb 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -8510,7 +8510,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 @@ -8527,8 +8528,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 cebd8e6eeb46..300b17209d83 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 795817d62246..4108cc4a7dac 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]) @@ -241,8 +243,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 ]) @@ -778,7 +782,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]) @@ -821,7 +826,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]) AT_CHECK([ovs-appctl revalidator/wait]) @@ -896,8 +902,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]) @@ -979,7 +987,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']) @@ -1031,7 +1040,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]) AT_CHECK([ovs-appctl revalidator/wait]) @@ -1101,7 +1111,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 @@ -1149,7 +1160,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 @@ -1223,7 +1235,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]) @@ -1288,7 +1301,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 e1a16138fa29..be022f3a087c 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 @@ -1286,7 +1287,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
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 <dchumak@nvidia.com> --- lib/netdev-dummy.c | 14 ++- lib/ovs-router.c | 166 +++++++++++++++++++++++++++------- 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, 253 insertions(+), 93 deletions(-)