+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* IS-IS Rout(e)ing protocol - isis_route.c
* Copyright (C) 2001,2002 Sampo Saaristo
*
* based on ../ospf6d/ospf6_route.[ch]
* by Yasuhiro Ohara
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public Licenseas published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
struct isis_nexthop *nh;
for (ALL_LIST_ELEMENTS_RO(nexthops, node, nh)) {
- if (nh->family != family)
- continue;
if (nh->ifindex != ifindex)
continue;
+ /* if the IP is unspecified, return the first nexthop found on
+ * the interface
+ */
+ if (!ip)
+ return nh;
+
+ if (nh->family != family)
+ continue;
+
switch (family) {
case AF_INET:
if (IPV4_ADDR_CMP(&nh->ip.ipv4, &ip->ipv4))
}
break;
case AF_INET6:
- for (unsigned int i = 0; i < adj->ipv6_address_count; i++) {
- ip.ipv6 = adj->ipv6_addresses[i];
+ for (unsigned int i = 0; i < adj->ll_ipv6_count; i++) {
+ ip.ipv6 = adj->ll_ipv6_addrs[i];
if (!nexthoplookup(nexthops, AF_INET6, &ip,
adj->circuit->interface->ifindex)) {
if (rinfo == NULL) {
if (IS_DEBUG_RTE_EVENTS)
zlog_debug(
- "ISIS-Rte: tried to delete non-existant route %s",
+ "ISIS-Rte: tried to delete non-existent route %s",
buff);
return;
}
route_unlock_node(rode);
}
+static void isis_route_remove_previous_sid(struct isis_area *area,
+ struct prefix *prefix,
+ struct isis_route_info *route_info)
+{
+ /*
+ * Explicitly uninstall previous Prefix-SID label if it has
+ * changed or was removed.
+ */
+ if (route_info->sr_previous.present &&
+ (!route_info->sr.present ||
+ route_info->sr_previous.label != route_info->sr.label))
+ isis_zebra_prefix_sid_uninstall(area, prefix, route_info,
+ &route_info->sr_previous);
+}
+
static void isis_route_update(struct isis_area *area, struct prefix *prefix,
struct prefix_ipv6 *src_p,
struct isis_route_info *route_info)
{
+ if (area == NULL)
+ return;
+
if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE)) {
if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
return;
- /*
- * Explicitly uninstall previous Prefix-SID label if it has
- * changed or was removed.
- */
- if (route_info->sr_previous.present
- && (!route_info->sr.present
- || route_info->sr_previous.label
- != route_info->sr.label))
- isis_zebra_prefix_sid_uninstall(
- area, prefix, route_info,
- &route_info->sr_previous);
+ isis_route_remove_previous_sid(area, prefix, route_info);
/* Install route. */
isis_zebra_route_add_route(area->isis, prefix, src_p,
UNSET_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
}
}
+
+void isis_route_switchover_nexthop(struct isis_area *area,
+ struct route_table *table, int family,
+ union g_addr *nexthop_addr,
+ ifindex_t ifindex)
+{
+ const char *ifname = NULL, *vrfname = NULL;
+ struct isis_route_info *rinfo;
+ struct prefix_ipv6 *src_p;
+ struct route_node *rnode;
+ vrf_id_t vrf_id;
+ struct prefix *prefix;
+
+ if (IS_DEBUG_EVENTS) {
+ if (area && area->isis) {
+ vrf_id = area->isis->vrf_id;
+ vrfname = vrf_id_to_name(vrf_id);
+ ifname = ifindex2ifname(ifindex, vrf_id);
+ }
+ zlog_debug("%s: initiating fast-reroute %s on VRF %s iface %s",
+ __func__, family2str(family), vrfname ? vrfname : "",
+ ifname ? ifname : "");
+ }
+
+ for (rnode = route_top(table); rnode;
+ rnode = srcdest_route_next(rnode)) {
+ if (!rnode->info)
+ continue;
+ rinfo = rnode->info;
+
+ if (!rinfo->backup)
+ continue;
+
+ if (!nexthoplookup(rinfo->nexthops, family, nexthop_addr,
+ ifindex))
+ continue;
+
+ srcdest_rnode_prefixes(rnode, (const struct prefix **)&prefix,
+ (const struct prefix **)&src_p);
+
+ /* Switchover route. */
+ isis_route_remove_previous_sid(area, prefix, rinfo);
+ UNSET_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
+ isis_route_update(area, prefix, src_p, rinfo->backup);
+
+ isis_route_info_delete(rinfo);
+
+ rnode->info = NULL;
+ route_unlock_node(rnode);
+ }
+}