diff options
| -rw-r--r-- | zebra/interface.c | 4 | ||||
| -rw-r--r-- | zebra/zebra_static.c | 96 | ||||
| -rw-r--r-- | zebra/zebra_static.h | 9 | ||||
| -rw-r--r-- | zebra/zebra_vty.c | 50 |
4 files changed, 103 insertions, 56 deletions
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 <lib/nexthop.h> #include <lib/memory.h> #include <lib/srcdest_table.h> +#include <lib/if.h> #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; } |
