From a50b580a0fe1fe443f5fc8d4bb5450ff3837fcfa Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 19 May 2015 18:04:16 -0700 Subject: [PATCH] Zebra: Don't resolve routes over default for nexthop tracking Resolving routes over the default route for NHT can lead to all sorts of problems. So, we explicitly exclude resolving routes for NHT over the default route. A knob is provided to allow the route to be resolved over the default in case of special circumstances. Signed-off-by: Dinesh G Dutt Reviewed-by: Daniel Walton --- zebra/zebra_rnh.c | 30 ++++++++++++++++++- zebra/zebra_rnh.h | 3 ++ zebra/zebra_rnh_null.c | 3 ++ zebra/zebra_routemap.c | 6 ++++ zebra/zebra_vty.c | 67 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 1 deletion(-) diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 380d06522b..f698e62e9c 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -63,6 +63,9 @@ static int compare_state(struct rib *r1, struct rib *r2); static int send_client(struct rnh *rnh, struct zserv *client); static void print_rnh(struct route_node *rn, struct vty *vty); +int zebra_rnh_ip_default_route = 0; +int zebra_rnh_ipv6_default_route = 0; + char * rnh_str (struct rnh *rnh, char *buf, int size) { @@ -217,6 +220,30 @@ zebra_deregister_rnh_static_nh(struct prefix *nh, struct route_node *static_rn) zebra_delete_rnh(rnh); } +static inline int +zebra_rnh_is_default_route(struct prefix *p) +{ + if (!p) + return 0; + + if (((p->family == AF_INET) && (p->u.prefix4.s_addr == INADDR_ANY)) + || ((p->family == AF_INET6) && + !memcmp(&p->u.prefix6, &in6addr_any, sizeof (struct in6_addr)))) + return 1; + + return 0; +} + +static inline int +zebra_rnh_resolve_via_default(int family) +{ + if (((family == AF_INET) && zebra_rnh_ip_default_route) || + ((family == AF_INET6) && zebra_rnh_ipv6_default_route)) + return 1; + else + return 0; +} + static int zebra_evaluate_rnh_nexthops(int family, struct rib *rib, struct route_node *prn, int proto) @@ -290,7 +317,8 @@ zebra_evaluate_rnh_table (int vrfid, int family, int force) at_least_one = 0; prn = route_node_match(ptable, &nrn->p); - if (!prn) + if (!prn || (zebra_rnh_is_default_route(&prn->p) && + !zebra_rnh_resolve_via_default(prn->p.family))) rib = NULL; else { diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index f18679dad3..2ef16bdf80 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -40,6 +40,9 @@ struct rnh int filtered[ZEBRA_ROUTE_MAX]; /* if this has been filtered for client */ }; +extern int zebra_rnh_ip_default_route; +extern int zebra_rnh_ipv6_default_route; + extern struct rnh *zebra_add_rnh(struct prefix *p, u_int32_t vrfid); extern struct rnh *zebra_lookup_rnh(struct prefix *p, u_int32_t vrfid); extern void zebra_delete_rnh(struct rnh *rnh); diff --git a/zebra/zebra_rnh_null.c b/zebra/zebra_rnh_null.c index da1bab876a..205382b482 100644 --- a/zebra/zebra_rnh_null.c +++ b/zebra/zebra_rnh_null.c @@ -3,6 +3,9 @@ #include "zebra/zserv.h" #include "zebra/zebra_rnh.h" +int zebra_rnh_ip_default_route = 0; +int zebra_rnh_ipv6_default_route = 0; + int zebra_evaluate_rnh_table (int vrfid, int family, int force) { return 0; } diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 55f131d61e..6ec28d73a8 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -1558,6 +1558,12 @@ static int config_write_protocol(struct vty *vty) { int i; + if (zebra_rnh_ip_default_route) + vty_out (vty, "ip nht resolve-via-default%s", VTY_NEWLINE); + + if (zebra_rnh_ipv6_default_route) + vty_out (vty, "ipv6 nht resolve-via-default%s", VTY_NEWLINE); + for (i=0;i", @@ -3097,6 +3160,10 @@ zebra_vty_init (void) install_element (CONFIG_NODE, &no_ipv6_route_flags_pref_tag_cmd); install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_tag_cmd); install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_pref_tag_cmd); + install_element (CONFIG_NODE, &ip_nht_default_route_cmd); + install_element (CONFIG_NODE, &no_ip_nht_default_route_cmd); + install_element (CONFIG_NODE, &ipv6_nht_default_route_cmd); + install_element (CONFIG_NODE, &no_ipv6_nht_default_route_cmd); install_element (VIEW_NODE, &show_ipv6_route_cmd); install_element (VIEW_NODE, &show_ipv6_route_tag_cmd); install_element (VIEW_NODE, &show_ipv6_route_summary_cmd);