From: David Lamparter Date: Sun, 6 Aug 2017 03:14:39 +0000 (+0200) Subject: zebra: static: update on ifindex changes X-Git-Tag: reindent-3.0-before^2~1 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=a3358cacb8ea549599198bf821acf8a3a462df73;p=mirror%2Ffrr.git zebra: static: update on ifindex changes Whenever an interface is created or deleted in the system, we need to check whether we have static routes referencing that interface by name. If so, we need to [un]install these routes. This has the unfortunate side effect of making static routes with non-existent interfaces disappear from "show ip route", but I think that's acceptable (and I don't see a "good" fix for that). Signed-off-by: David Lamparter --- diff --git a/zebra/interface.c b/zebra/interface.c index 317cc722b4..13ac85d43d 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -48,6 +48,7 @@ #include "zebra/zebra_ptm.h" #include "zebra/rt_netlink.h" #include "zebra/interface.h" +#include "zebra/zebra_static.h" #define ZEBRA_PTM_SUPPORT @@ -520,6 +521,7 @@ if_add_update (struct interface *ifp) if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug ("interface %s vrf %u index %d becomes active.", ifp->name, ifp->vrf_id, ifp->ifindex); + static_ifindex_update(ifp, true); } else { @@ -695,6 +697,8 @@ if_delete_update (struct interface *ifp) zlog_debug ("interface %s vrf %u index %d is now inactive.", ifp->name, ifp->vrf_id, ifp->ifindex); + static_ifindex_update(ifp, false); + /* Delete connected routes from the kernel. */ if_delete_connected (ifp); diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c index 81c6f1911a..169f1827e0 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "vty.h" #include "zebra/debug.h" @@ -197,6 +198,9 @@ static_install_route (afi_t afi, safi_t safi, struct prefix *p, } } +/* this works correctly with IFNAME<>IFINDEX because a static route on a + * non-active interface will have IFINDEX_INTERNAL and thus compare false + */ static int static_nexthop_same (struct nexthop *nexthop, struct static_route *si) { @@ -340,8 +344,7 @@ static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, int static_add_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, - struct prefix_ipv6 *src_p, - union g_addr *gate, ifindex_t ifindex, + struct prefix_ipv6 *src_p, union g_addr *gate, const char *ifname, u_char flags, route_tag_t tag, u_char distance, struct zebra_vrf *zvrf, struct static_nh_label *snh_label) @@ -362,7 +365,7 @@ static_add_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, type == STATIC_IPV6_GATEWAY_IFNAME)) return -1; - if (!ifindex && + if (!ifname && (type == STATIC_IFNAME || type == STATIC_IPV6_GATEWAY_IFNAME)) return -1; @@ -377,7 +380,7 @@ static_add_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, && (! gate || ((afi == AFI_IP && IPV4_ADDR_SAME (gate, &si->addr.ipv4)) || (afi == AFI_IP6 && IPV6_ADDR_SAME (gate, &si->addr.ipv6)))) - && (! ifindex || ifindex == si->ifindex)) + && (!strcmp (ifname ? ifname : "", si->ifname))) { if ((distance == si->distance) && (tag == si->tag) && !memcmp (&si->snh_label, snh_label, sizeof (struct static_nh_label)) && @@ -393,7 +396,7 @@ static_add_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, /* Distance or tag or label changed, delete existing first. */ if (update) - static_delete_route (afi, safi, type, p, src_p, gate, ifindex, update->tag, + static_delete_route (afi, safi, type, p, src_p, gate, ifname, update->tag, update->distance, zvrf, &update->snh_label); /* Make new static route structure. */ @@ -404,9 +407,9 @@ static_add_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, si->flags = flags; si->tag = tag; si->vrf_id = zvrf_id (zvrf); - si->ifindex = ifindex; - if (si->ifindex) - strcpy(si->ifname, ifname); + if (ifname) + strlcpy(si->ifname, ifname, sizeof(si->ifname)); + si->ifindex = IFINDEX_INTERNAL; switch (type) { @@ -453,8 +456,20 @@ static_add_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, si->prev = pp; si->next = cp; - /* Install into rib. */ - static_install_route (afi, safi, p, src_p, si); + /* check whether interface exists in system & install if it does */ + if (!ifname) + static_install_route(afi, safi, p, src_p, si); + else + { + struct interface *ifp; + + ifp = if_lookup_by_name(ifname, zvrf_id(zvrf)); + if (ifp && ifp->ifindex != IFINDEX_INTERNAL) + { + si->ifindex = ifp->ifindex; + static_install_route (afi, safi, p, src_p, si); + } + } return 1; } @@ -462,7 +477,7 @@ static_add_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, int static_delete_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, struct prefix_ipv6 *src_p, - union g_addr *gate, ifindex_t ifindex, + union g_addr *gate, const char *ifname, route_tag_t tag, u_char distance, struct zebra_vrf *zvrf, struct static_nh_label *snh_label) { @@ -486,7 +501,7 @@ static_delete_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, && (! gate || ( (afi == AFI_IP && IPV4_ADDR_SAME (gate, &si->addr.ipv4)) || (afi == AFI_IP6 && IPV6_ADDR_SAME (gate, &si->addr.ipv6)))) - && (! ifindex || ifindex == si->ifindex) + && (!strcmp(ifname ? ifname : "", si->ifname)) && (! tag || (tag == si->tag)) && (! snh_label->num_labels || !memcmp (&si->snh_label, snh_label, sizeof (struct static_nh_label)))) @@ -499,8 +514,9 @@ static_delete_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, return 0; } - /* Install into rib. */ - static_uninstall_route (afi, safi, p, src_p, si); + /* Uninstall from rib. */ + if (!si->ifname[0] || si->ifindex != IFINDEX_INTERNAL) + static_uninstall_route (afi, safi, p, src_p, si); /* Unlink static route from linked list. */ if (si->prev) @@ -518,3 +534,55 @@ static_delete_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, return 1; } + +static void +static_ifindex_update_af(struct interface *ifp, bool up, + afi_t afi, safi_t safi) +{ + struct route_table *stable; + struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); + struct route_node *rn; + struct static_route *si; + struct prefix *p, *src_pp; + struct prefix_ipv6 *src_p; + + stable = zebra_vrf_static_table(afi, safi, zvrf); + if (!stable) + return; + + for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) + { + srcdest_rnode_prefixes(rn, &p, &src_pp); + src_p = (struct prefix_ipv6 *)src_pp; + + for (si = rn->info; si; si = si->next) + { + if (!si->ifname[0]) + continue; + if (up) + { + if (strcmp(si->ifname, ifp->name)) + continue; + si->ifindex = ifp->ifindex; + static_install_route(afi, safi, p, src_p, si); + } + else + { + if (si->ifindex != ifp->ifindex) + continue; + static_uninstall_route(afi, safi, p, src_p, si); + si->ifindex = IFINDEX_INTERNAL; + } + } + } +} + +/* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */ +void +static_ifindex_update(struct interface *ifp, bool up) +{ + static_ifindex_update_af(ifp, up, AFI_IP, SAFI_UNICAST); + static_ifindex_update_af(ifp, up, AFI_IP, SAFI_MULTICAST); + static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST); + static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST); +} diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h index 1379bef093..6d3bafa325 100644 --- a/zebra/zebra_static.h +++ b/zebra/zebra_static.h @@ -91,16 +91,15 @@ static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, extern int static_add_route (afi_t, safi_t safi, u_char type, struct prefix *p, - struct prefix_ipv6 *src_p, - union g_addr *gate, ifindex_t ifindex, + struct prefix_ipv6 *src_p, union g_addr *gate, const char *ifname, u_char flags, route_tag_t tag, u_char distance, struct zebra_vrf *zvrf, struct static_nh_label *snh_label); extern int static_delete_route (afi_t, safi_t safi, u_char type, struct prefix *p, - struct prefix_ipv6 *src_p, - union g_addr *gate, ifindex_t ifindex, route_tag_t tag, + struct prefix_ipv6 *src_p, union g_addr *gate, + const char *ifname, route_tag_t tag, u_char distance, struct zebra_vrf *zvrf, struct static_nh_label *snh_label); @@ -119,4 +118,6 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, const char *distance_str, const char *vrf_id_str, const char *label_str); +extern void static_ifindex_update(struct interface *ifp, bool up); + #endif diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index fb00e4d45e..aec8fd1ddf 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -69,7 +69,6 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, u_char flag = 0; route_tag_t tag = 0; struct zebra_vrf *zvrf = NULL; - unsigned int ifindex = 0; const char *ifname = NULL; u_char type = STATIC_BLACKHOLE; struct static_nh_label snh_label; @@ -142,10 +141,10 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, return CMD_WARNING; } if (add_cmd) - static_add_route (AFI_IP, safi, type, &p, NULL, NULL, ifindex, ifname, + static_add_route (AFI_IP, safi, type, &p, NULL, NULL, ifname, ZEBRA_FLAG_BLACKHOLE, tag, distance, zvrf, &snh_label); else - static_delete_route (AFI_IP, safi, type, &p, NULL, NULL, ifindex, tag, + static_delete_route (AFI_IP, safi, type, &p, NULL, NULL, ifname, tag, distance, zvrf, &snh_label); return CMD_SUCCESS; } @@ -170,11 +169,11 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, if (gate_str == NULL) { if (add_cmd) - static_add_route (AFI_IP, safi, type, &p, NULL, NULL, ifindex, ifname, flag, + static_add_route (AFI_IP, safi, type, &p, NULL, NULL, ifname, flag, tag, distance, zvrf, &snh_label); else - static_delete_route (AFI_IP, safi, type, &p, NULL, NULL, ifindex, tag, distance, - zvrf, &snh_label); + static_delete_route (AFI_IP, safi, type, &p, NULL, NULL, ifname, tag, + distance, zvrf, &snh_label); return CMD_SUCCESS; } @@ -184,14 +183,6 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, ret = inet_aton (gate_str, &gate); if (!ret) { - struct interface *ifp = if_lookup_by_name (gate_str, zvrf_id (zvrf)); - if (!ifp) - { - vty_out (vty, "%% Unknown interface: %s%s", gate_str, VTY_NEWLINE); - ifindex = IFINDEX_DELETED; - } - else - ifindex = ifp->ifindex; ifname = gate_str; type = STATIC_IFNAME; } @@ -200,11 +191,11 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, if (add_cmd) static_add_route (AFI_IP, safi, type, &p, NULL, - ifindex ? NULL : (union g_addr *)&gate, ifindex, ifname, + ret ? (union g_addr *)&gate : NULL, ifname, flag, tag, distance, zvrf, &snh_label); else static_delete_route (AFI_IP, safi, type, &p, NULL, - ifindex ? NULL : (union g_addr *)&gate, ifindex, tag, + ret ? (union g_addr *)&gate : NULL, ifname, tag, distance, zvrf, &snh_label); return CMD_SUCCESS; @@ -2347,8 +2338,6 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, u_char type = STATIC_BLACKHOLE; u_char flag = 0; route_tag_t tag = 0; - unsigned int ifindex = 0; - struct interface *ifp = NULL; struct zebra_vrf *zvrf; struct static_nh_label snh_label; @@ -2423,11 +2412,11 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, return CMD_WARNING; } if (add_cmd) - static_add_route (AFI_IP6, SAFI_UNICAST, type, &p, src_p, NULL, ifindex, ifname, + static_add_route (AFI_IP6, SAFI_UNICAST, type, &p, src_p, NULL, ifname, ZEBRA_FLAG_BLACKHOLE, tag, distance, zvrf, &snh_label); else - static_delete_route (AFI_IP6, SAFI_UNICAST, type, &p, src_p, NULL, ifindex, tag, - distance, zvrf, &snh_label); + static_delete_route (AFI_IP6, SAFI_UNICAST, type, &p, src_p, NULL, + ifname, tag, distance, zvrf, &snh_label); return CMD_SUCCESS; } @@ -2459,13 +2448,6 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, } type = STATIC_IPV6_GATEWAY_IFNAME; gate = &gate_addr; - ifp = if_lookup_by_name (ifname, zvrf_id (zvrf)); - if (!ifp) - { - vty_out (vty, "%% Malformed Interface name %s%s", ifname, VTY_NEWLINE); - return CMD_WARNING; - } - ifindex = ifp->ifindex; } else { @@ -2477,24 +2459,16 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, else { type = STATIC_IFNAME; - ifp = if_lookup_by_name (gate_str, zvrf_id (zvrf)); - if (!ifp) - { - vty_out (vty, "%% Malformed Interface name %s%s", gate_str, VTY_NEWLINE); - ifindex = IFINDEX_DELETED; - } - else - ifindex = ifp->ifindex; ifname = gate_str; } } if (add_cmd) static_add_route (AFI_IP6, SAFI_UNICAST, type, &p, src_p, (union g_addr *)gate, - ifindex, ifname, flag, tag, distance, zvrf, &snh_label); + ifname, flag, tag, distance, zvrf, &snh_label); else static_delete_route (AFI_IP6, SAFI_UNICAST, type, &p, src_p, (union g_addr *)gate, - ifindex, tag, distance, zvrf, &snh_label); + ifname, tag, distance, zvrf, &snh_label); return CMD_SUCCESS; }