2003-12-23 09:09:43 +01:00
|
|
|
/*
|
|
|
|
* IS-IS Rout(e)ing protocol - isis_route.c
|
|
|
|
* Copyright (C) 2001,2002 Sampo Saaristo
|
|
|
|
* Tampere University of Technology
|
|
|
|
* Institute of Communications Engineering
|
|
|
|
*
|
|
|
|
* 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.
|
2017-05-13 10:25:29 +02:00
|
|
|
*
|
|
|
|
* 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
|
2003-12-23 09:09:43 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
|
|
|
#include "thread.h"
|
|
|
|
#include "linklist.h"
|
|
|
|
#include "vty.h"
|
|
|
|
#include "log.h"
|
2019-08-06 22:43:46 +02:00
|
|
|
#include "lib_errors.h"
|
2003-12-23 09:09:43 +01:00
|
|
|
#include "memory.h"
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "hash.h"
|
|
|
|
#include "if.h"
|
|
|
|
#include "table.h"
|
2018-07-26 22:53:08 +02:00
|
|
|
#include "srcdest_table.h"
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
#include "isis_constants.h"
|
|
|
|
#include "isis_common.h"
|
2012-03-24 16:35:20 +01:00
|
|
|
#include "isis_flags.h"
|
2003-12-23 09:09:43 +01:00
|
|
|
#include "isisd.h"
|
|
|
|
#include "isis_misc.h"
|
|
|
|
#include "isis_adjacency.h"
|
|
|
|
#include "isis_circuit.h"
|
|
|
|
#include "isis_pdu.h"
|
|
|
|
#include "isis_lsp.h"
|
|
|
|
#include "isis_spf.h"
|
2020-08-23 05:22:32 +02:00
|
|
|
#include "isis_spf_private.h"
|
2003-12-23 09:09:43 +01:00
|
|
|
#include "isis_route.h"
|
|
|
|
#include "isis_zebra.h"
|
|
|
|
|
2019-08-08 00:44:11 +02:00
|
|
|
DEFINE_HOOK(isis_route_update_hook,
|
|
|
|
(struct isis_area * area, struct prefix *prefix,
|
|
|
|
struct isis_route_info *route_info),
|
|
|
|
(area, prefix, route_info))
|
|
|
|
|
2019-08-06 22:43:46 +02:00
|
|
|
static struct isis_nexthop *nexthoplookup(struct list *nexthops, int family,
|
|
|
|
union g_addr *ip, ifindex_t ifindex);
|
2019-08-08 00:44:11 +02:00
|
|
|
static void isis_route_update(struct isis_area *area, struct prefix *prefix,
|
|
|
|
struct prefix_ipv6 *src_p,
|
2019-08-08 00:42:18 +02:00
|
|
|
struct isis_route_info *route_info);
|
2019-08-06 22:24:54 +02:00
|
|
|
|
2019-08-06 22:43:46 +02:00
|
|
|
static struct isis_nexthop *isis_nexthop_create(int family, union g_addr *ip,
|
2016-01-18 11:12:10 +01:00
|
|
|
ifindex_t ifindex)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_nexthop *nexthop;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2005-09-28 20:45:54 +02:00
|
|
|
nexthop = XCALLOC(MTYPE_ISIS_NEXTHOP, sizeof(struct isis_nexthop));
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2019-08-06 22:43:46 +02:00
|
|
|
nexthop->family = family;
|
2003-12-23 09:09:43 +01:00
|
|
|
nexthop->ifindex = ifindex;
|
2019-08-06 22:43:46 +02:00
|
|
|
nexthop->ip = *ip;
|
2019-08-04 03:02:37 +02:00
|
|
|
isis_sr_nexthop_reset(&nexthop->sr);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
return nexthop;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void isis_nexthop_delete(struct isis_nexthop *nexthop)
|
|
|
|
{
|
2019-09-06 05:57:14 +02:00
|
|
|
XFREE(MTYPE_ISIS_NEXTHOP, nexthop);
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2019-08-06 22:43:46 +02:00
|
|
|
static struct isis_nexthop *nexthoplookup(struct list *nexthops, int family,
|
|
|
|
union g_addr *ip, ifindex_t ifindex)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
struct isis_nexthop *nh;
|
|
|
|
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO(nexthops, node, nh)) {
|
2019-08-06 22:43:46 +02:00
|
|
|
if (nh->family != family)
|
|
|
|
continue;
|
|
|
|
if (nh->ifindex != ifindex)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (family) {
|
|
|
|
case AF_INET:
|
|
|
|
if (IPV4_ADDR_CMP(&nh->ip.ipv4, &ip->ipv4))
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
if (IPV6_ADDR_CMP(&nh->ip.ipv6, &ip->ipv6))
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
flog_err(EC_LIB_DEVELOPMENT,
|
|
|
|
"%s: unknown address family [%d]", __func__,
|
|
|
|
family);
|
|
|
|
exit(1);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2019-08-06 22:43:46 +02:00
|
|
|
return nh;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2019-08-06 22:24:54 +02:00
|
|
|
return NULL;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2019-08-06 22:43:46 +02:00
|
|
|
static void adjinfo2nexthop(int family, struct list *nexthops,
|
|
|
|
struct isis_adjacency *adj)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_nexthop *nh;
|
2019-08-06 22:43:46 +02:00
|
|
|
union g_addr ip = {};
|
|
|
|
|
|
|
|
switch (family) {
|
|
|
|
case AF_INET:
|
|
|
|
for (unsigned int i = 0; i < adj->ipv4_address_count; i++) {
|
|
|
|
ip.ipv4 = adj->ipv4_addresses[i];
|
|
|
|
|
|
|
|
if (!nexthoplookup(nexthops, AF_INET, &ip,
|
|
|
|
adj->circuit->interface->ifindex)) {
|
|
|
|
nh = isis_nexthop_create(
|
|
|
|
AF_INET, &ip,
|
|
|
|
adj->circuit->interface->ifindex);
|
2019-08-04 03:02:37 +02:00
|
|
|
memcpy(nh->sysid, adj->sysid, sizeof(nh->sysid));
|
2019-08-06 22:43:46 +02:00
|
|
|
listnode_add(nexthops, nh);
|
|
|
|
break;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2019-08-06 22:43:46 +02:00
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
for (unsigned int i = 0; i < adj->ipv6_address_count; i++) {
|
|
|
|
ip.ipv6 = adj->ipv6_addresses[i];
|
|
|
|
|
|
|
|
if (!nexthoplookup(nexthops, AF_INET6, &ip,
|
|
|
|
adj->circuit->interface->ifindex)) {
|
|
|
|
nh = isis_nexthop_create(
|
|
|
|
AF_INET6, &ip,
|
|
|
|
adj->circuit->interface->ifindex);
|
2019-08-04 03:02:37 +02:00
|
|
|
memcpy(nh->sysid, adj->sysid, sizeof(nh->sysid));
|
2019-08-06 22:43:46 +02:00
|
|
|
listnode_add(nexthops, nh);
|
|
|
|
break;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2019-08-06 22:43:46 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
flog_err(EC_LIB_DEVELOPMENT, "%s: unknown address family [%d]",
|
|
|
|
__func__, family);
|
|
|
|
exit(1);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2012-03-28 08:48:05 +02:00
|
|
|
static struct isis_route_info *isis_route_info_new(struct prefix *prefix,
|
2018-07-26 22:53:08 +02:00
|
|
|
struct prefix_ipv6 *src_p,
|
2012-03-28 08:48:05 +02:00
|
|
|
uint32_t cost,
|
|
|
|
uint32_t depth,
|
|
|
|
struct list *adjacencies)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_route_info *rinfo;
|
2020-08-23 05:22:32 +02:00
|
|
|
struct isis_vertex_adj *vadj;
|
2005-09-28 20:45:54 +02:00
|
|
|
struct listnode *node;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-09-28 20:45:54 +02:00
|
|
|
rinfo = XCALLOC(MTYPE_ISIS_ROUTE_INFO, sizeof(struct isis_route_info));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2019-08-06 22:43:46 +02:00
|
|
|
rinfo->nexthops = list_new();
|
2020-08-23 05:22:32 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO(adjacencies, node, vadj)) {
|
|
|
|
struct isis_spf_adj *sadj = vadj->sadj;
|
|
|
|
struct isis_adjacency *adj = sadj->adj;
|
|
|
|
|
2019-08-06 22:43:46 +02:00
|
|
|
/* check for force resync this route */
|
|
|
|
if (CHECK_FLAG(adj->circuit->flags,
|
|
|
|
ISIS_CIRCUIT_FLAPPED_AFTER_SPF))
|
|
|
|
SET_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
|
|
|
|
|
|
|
|
/* update neighbor router address */
|
|
|
|
switch (prefix->family) {
|
|
|
|
case AF_INET:
|
2012-03-28 08:48:05 +02:00
|
|
|
if (depth == 2 && prefix->prefixlen == 32)
|
|
|
|
adj->router_address = prefix->u.prefix4;
|
2019-08-06 22:43:46 +02:00
|
|
|
break;
|
|
|
|
case AF_INET6:
|
2018-07-26 22:53:08 +02:00
|
|
|
if (depth == 2 && prefix->prefixlen == 128
|
|
|
|
&& (!src_p || !src_p->prefixlen)) {
|
2012-03-28 08:48:05 +02:00
|
|
|
adj->router_address6 = prefix->u.prefix6;
|
2018-07-26 22:53:08 +02:00
|
|
|
}
|
2019-08-06 22:43:46 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
flog_err(EC_LIB_DEVELOPMENT,
|
|
|
|
"%s: unknown address family [%d]", __func__,
|
|
|
|
prefix->family);
|
|
|
|
exit(1);
|
2012-03-24 16:35:20 +01:00
|
|
|
}
|
2019-08-06 22:43:46 +02:00
|
|
|
adjinfo2nexthop(prefix->family, rinfo->nexthops, adj);
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
rinfo->cost = cost;
|
|
|
|
rinfo->depth = depth;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return rinfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void isis_route_info_delete(struct isis_route_info *route_info)
|
|
|
|
{
|
2004-09-10 22:48:21 +02:00
|
|
|
if (route_info->nexthops) {
|
2004-09-26 18:24:14 +02:00
|
|
|
route_info->nexthops->del =
|
|
|
|
(void (*)(void *))isis_nexthop_delete;
|
2018-10-02 11:39:51 +02:00
|
|
|
list_delete(&route_info->nexthops);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
XFREE(MTYPE_ISIS_ROUTE_INFO, route_info);
|
|
|
|
}
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
static int isis_route_info_same_attrib(struct isis_route_info *new,
|
|
|
|
struct isis_route_info *old)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
if (new->cost != old->cost)
|
|
|
|
return 0;
|
|
|
|
if (new->depth != old->depth)
|
|
|
|
return 0;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
static int isis_route_info_same(struct isis_route_info *new,
|
2018-03-27 21:13:34 +02:00
|
|
|
struct isis_route_info *old, uint8_t family)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2005-09-28 20:45:54 +02:00
|
|
|
struct listnode *node;
|
2003-12-23 09:09:43 +01:00
|
|
|
struct isis_nexthop *nexthop;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
if (!CHECK_FLAG(old->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
|
|
|
|
return 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
if (CHECK_FLAG(new->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC))
|
|
|
|
return 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
if (!isis_route_info_same_attrib(new, old))
|
|
|
|
return 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2019-08-06 22:43:46 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO(new->nexthops, node, nexthop))
|
|
|
|
if (!nexthoplookup(old->nexthops, nexthop->family, &nexthop->ip,
|
|
|
|
nexthop->ifindex))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(old->nexthops, node, nexthop))
|
|
|
|
if (!nexthoplookup(new->nexthops, nexthop->family, &nexthop->ip,
|
|
|
|
nexthop->ifindex))
|
|
|
|
return 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-07-26 22:53:08 +02:00
|
|
|
struct isis_route_info *isis_route_create(struct prefix *prefix,
|
|
|
|
struct prefix_ipv6 *src_p,
|
|
|
|
uint32_t cost,
|
2018-03-27 21:13:34 +02:00
|
|
|
uint32_t depth,
|
2005-09-26 20:26:26 +02:00
|
|
|
struct list *adjacencies,
|
2018-07-24 17:40:24 +02:00
|
|
|
struct isis_area *area,
|
|
|
|
struct route_table *table)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct route_node *route_node;
|
|
|
|
struct isis_route_info *rinfo_new, *rinfo_old, *route_info = NULL;
|
2015-11-23 21:44:34 +01:00
|
|
|
char buff[PREFIX2STR_BUFFER];
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t family;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
family = prefix->family;
|
|
|
|
/* for debugs */
|
2015-11-23 21:44:34 +01:00
|
|
|
prefix2str(prefix, buff, sizeof(buff));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-07-24 17:40:24 +02:00
|
|
|
if (!table)
|
2012-11-27 02:10:30 +01:00
|
|
|
return NULL;
|
2018-07-24 17:40:24 +02:00
|
|
|
|
2018-07-26 22:53:08 +02:00
|
|
|
rinfo_new = isis_route_info_new(prefix, src_p, cost,
|
|
|
|
depth, adjacencies);
|
|
|
|
route_node = srcdest_rnode_get(table, prefix, src_p);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
rinfo_old = route_node->info;
|
|
|
|
if (!rinfo_old) {
|
2020-06-19 21:04:33 +02:00
|
|
|
if (IS_DEBUG_RTE_EVENTS)
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_debug("ISIS-Rte (%s) route created: %s",
|
|
|
|
area->area_tag, buff);
|
|
|
|
route_info = rinfo_new;
|
|
|
|
UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
2004-09-10 22:48:21 +02:00
|
|
|
} else {
|
2018-08-01 13:23:56 +02:00
|
|
|
route_unlock_node(route_node);
|
2020-06-19 21:04:33 +02:00
|
|
|
if (IS_DEBUG_RTE_EVENTS)
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_debug("ISIS-Rte (%s) route already exists: %s",
|
|
|
|
area->area_tag, buff);
|
|
|
|
if (isis_route_info_same(rinfo_new, rinfo_old, family)) {
|
2020-06-19 21:04:33 +02:00
|
|
|
if (IS_DEBUG_RTE_EVENTS)
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_debug("ISIS-Rte (%s) route unchanged: %s",
|
|
|
|
area->area_tag, buff);
|
|
|
|
isis_route_info_delete(rinfo_new);
|
|
|
|
route_info = rinfo_old;
|
2004-09-10 22:48:21 +02:00
|
|
|
} else {
|
2020-06-19 21:04:33 +02:00
|
|
|
if (IS_DEBUG_RTE_EVENTS)
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_debug("ISIS-Rte (%s) route changed: %s",
|
|
|
|
area->area_tag, buff);
|
|
|
|
isis_route_info_delete(rinfo_old);
|
|
|
|
route_info = rinfo_new;
|
|
|
|
UNSET_FLAG(route_info->flag,
|
|
|
|
ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE);
|
|
|
|
route_node->info = route_info;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return route_info;
|
|
|
|
}
|
|
|
|
|
2019-08-08 00:44:11 +02:00
|
|
|
static void isis_route_delete(struct isis_area *area, struct route_node *rode,
|
2018-07-26 22:53:08 +02:00
|
|
|
struct route_table *table)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_route_info *rinfo;
|
2018-07-26 22:53:08 +02:00
|
|
|
char buff[SRCDEST2STR_BUFFER];
|
2018-08-01 13:23:56 +02:00
|
|
|
struct prefix *prefix;
|
|
|
|
struct prefix_ipv6 *src_p;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/* for log */
|
2018-08-01 13:23:56 +02:00
|
|
|
srcdest_rnode2str(rode, buff, sizeof(buff));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-08-01 13:23:56 +02:00
|
|
|
srcdest_rnode_prefixes(rode, (const struct prefix **)&prefix,
|
|
|
|
(const struct prefix **)&src_p);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-08-01 13:23:56 +02:00
|
|
|
rinfo = rode->info;
|
2004-09-10 22:48:21 +02:00
|
|
|
if (rinfo == NULL) {
|
2020-06-19 21:04:33 +02:00
|
|
|
if (IS_DEBUG_RTE_EVENTS)
|
2004-12-24 01:14:50 +01:00
|
|
|
zlog_debug(
|
|
|
|
"ISIS-Rte: tried to delete non-existant route %s",
|
|
|
|
buff);
|
2004-09-10 22:48:21 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
if (CHECK_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) {
|
2004-09-10 22:48:21 +02:00
|
|
|
UNSET_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
|
2020-06-19 21:04:33 +02:00
|
|
|
if (IS_DEBUG_RTE_EVENTS)
|
2004-12-24 01:14:50 +01:00
|
|
|
zlog_debug("ISIS-Rte: route delete %s", buff);
|
2019-08-08 00:44:11 +02:00
|
|
|
isis_route_update(area, prefix, src_p, rinfo);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
isis_route_info_delete(rinfo);
|
|
|
|
rode->info = NULL;
|
2018-08-01 13:23:56 +02:00
|
|
|
route_unlock_node(rode);
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2019-08-08 00:44:11 +02:00
|
|
|
static void isis_route_update(struct isis_area *area, struct prefix *prefix,
|
|
|
|
struct prefix_ipv6 *src_p,
|
2019-08-08 00:42:18 +02:00
|
|
|
struct isis_route_info *route_info)
|
|
|
|
{
|
|
|
|
if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE)) {
|
|
|
|
if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
|
|
|
|
return;
|
|
|
|
|
2020-06-19 20:46:12 +02:00
|
|
|
isis_zebra_route_add_route(area->isis, prefix, src_p, route_info);
|
2019-08-08 00:44:11 +02:00
|
|
|
hook_call(isis_route_update_hook, area, prefix, route_info);
|
2019-08-08 00:42:18 +02:00
|
|
|
|
|
|
|
SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
|
|
|
UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
|
|
|
|
} else {
|
|
|
|
if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
|
|
|
|
return;
|
|
|
|
|
2020-06-19 20:46:12 +02:00
|
|
|
isis_zebra_route_del_route(area->isis, prefix, src_p, route_info);
|
2019-08-08 00:44:11 +02:00
|
|
|
hook_call(isis_route_update_hook, area, prefix, route_info);
|
2019-08-08 00:42:18 +02:00
|
|
|
|
|
|
|
UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-24 17:40:24 +02:00
|
|
|
static void _isis_route_verify_table(struct isis_area *area,
|
|
|
|
struct route_table *table,
|
|
|
|
struct route_table **tables)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2005-09-26 20:26:26 +02:00
|
|
|
struct route_node *rnode, *drnode;
|
2003-12-23 09:09:43 +01:00
|
|
|
struct isis_route_info *rinfo;
|
2018-07-26 22:53:08 +02:00
|
|
|
char buff[SRCDEST2STR_BUFFER];
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-07-26 22:53:08 +02:00
|
|
|
for (rnode = route_top(table); rnode;
|
|
|
|
rnode = srcdest_route_next(rnode)) {
|
2005-09-26 20:26:26 +02:00
|
|
|
if (rnode->info == NULL)
|
2004-09-10 22:48:21 +02:00
|
|
|
continue;
|
2005-09-26 20:26:26 +02:00
|
|
|
rinfo = rnode->info;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-07-26 22:53:08 +02:00
|
|
|
struct prefix *dst_p;
|
|
|
|
struct prefix_ipv6 *src_p;
|
|
|
|
|
|
|
|
srcdest_rnode_prefixes(rnode,
|
|
|
|
(const struct prefix **)&dst_p,
|
|
|
|
(const struct prefix **)&src_p);
|
|
|
|
|
2020-06-19 21:04:33 +02:00
|
|
|
if (IS_DEBUG_RTE_EVENTS) {
|
2018-07-26 22:53:08 +02:00
|
|
|
srcdest2str(dst_p, src_p, buff, sizeof(buff));
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_debug(
|
|
|
|
"ISIS-Rte (%s): route validate: %s %s %s %s",
|
2004-12-24 01:14:50 +01:00
|
|
|
area->area_tag,
|
2004-09-10 22:48:21 +02:00
|
|
|
(CHECK_FLAG(rinfo->flag,
|
2005-09-26 20:26:26 +02:00
|
|
|
ISIS_ROUTE_FLAG_ZEBRA_SYNCED)
|
2012-03-24 16:35:20 +01:00
|
|
|
? "synced"
|
|
|
|
: "not-synced"),
|
|
|
|
(CHECK_FLAG(rinfo->flag,
|
|
|
|
ISIS_ROUTE_FLAG_ZEBRA_RESYNC)
|
2017-07-17 14:03:14 +02:00
|
|
|
? "resync"
|
2012-03-24 16:35:20 +01:00
|
|
|
: "not-resync"),
|
|
|
|
(CHECK_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE)
|
|
|
|
? "active"
|
|
|
|
: "inactive"),
|
2017-07-17 14:03:14 +02:00
|
|
|
buff);
|
|
|
|
}
|
|
|
|
|
2019-08-08 00:44:11 +02:00
|
|
|
isis_route_update(area, dst_p, src_p, rinfo);
|
2018-08-01 13:23:56 +02:00
|
|
|
|
|
|
|
if (CHECK_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Area is either L1 or L2 => we use level route tables
|
|
|
|
* directly for
|
|
|
|
* validating => no problems with deleting routes. */
|
|
|
|
if (!tables) {
|
2019-08-08 00:44:11 +02:00
|
|
|
isis_route_delete(area, rnode, table);
|
2018-08-01 13:23:56 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If area is L1L2, we work with merge table and
|
|
|
|
* therefore must
|
|
|
|
* delete node from level tables as well before deleting
|
|
|
|
* route info. */
|
|
|
|
for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
|
|
|
|
drnode = srcdest_rnode_lookup(tables[level - 1],
|
|
|
|
dst_p, src_p);
|
|
|
|
if (!drnode)
|
2005-09-26 20:26:26 +02:00
|
|
|
continue;
|
2018-07-24 17:40:24 +02:00
|
|
|
|
2018-08-01 13:23:56 +02:00
|
|
|
route_unlock_node(drnode);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-08-01 13:23:56 +02:00
|
|
|
if (drnode->info != rnode->info)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
drnode->info = NULL;
|
|
|
|
route_unlock_node(drnode);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2018-08-01 13:23:56 +02:00
|
|
|
|
2019-08-08 00:44:11 +02:00
|
|
|
isis_route_delete(area, rnode, table);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2005-09-26 20:26:26 +02:00
|
|
|
}
|
|
|
|
|
2018-07-24 17:40:24 +02:00
|
|
|
void isis_route_verify_table(struct isis_area *area, struct route_table *table)
|
|
|
|
{
|
2018-11-20 16:30:20 +01:00
|
|
|
_isis_route_verify_table(area, table, NULL);
|
2018-07-24 17:40:24 +02:00
|
|
|
}
|
|
|
|
|
2005-09-26 20:26:26 +02:00
|
|
|
/* Function to validate route tables for L1L2 areas. In this case we can't use
|
|
|
|
* level route tables directly, we have to merge them at first. L1 routes are
|
|
|
|
* preferred over the L2 ones.
|
|
|
|
*
|
|
|
|
* Merge algorithm is trivial (at least for now). All L1 paths are copied into
|
|
|
|
* merge table at first, then L2 paths are added if L1 path for same prefix
|
|
|
|
* doesn't already exists there.
|
|
|
|
*
|
|
|
|
* FIXME: Is it right place to do it at all? Maybe we should push both levels
|
|
|
|
* to the RIB with different zebra route types and let RIB handle this? */
|
2018-07-24 17:40:24 +02:00
|
|
|
void isis_route_verify_merge(struct isis_area *area,
|
|
|
|
struct route_table *level1_table,
|
|
|
|
struct route_table *level2_table)
|
2005-09-26 20:26:26 +02:00
|
|
|
{
|
2018-07-24 17:40:24 +02:00
|
|
|
struct route_table *tables[] = { level1_table, level2_table };
|
2005-09-26 20:26:26 +02:00
|
|
|
struct route_table *merge;
|
|
|
|
struct route_node *rnode, *mrnode;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-07-26 22:53:08 +02:00
|
|
|
merge = srcdest_table_init();
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-07-24 17:40:24 +02:00
|
|
|
for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
|
|
|
|
for (rnode = route_top(tables[level - 1]); rnode;
|
2018-07-26 22:53:08 +02:00
|
|
|
rnode = srcdest_route_next(rnode)) {
|
2018-07-26 10:02:15 +02:00
|
|
|
struct isis_route_info *rinfo = rnode->info;
|
|
|
|
if (!rinfo)
|
2018-07-24 17:40:24 +02:00
|
|
|
continue;
|
2018-07-26 10:02:15 +02:00
|
|
|
|
2018-07-26 22:53:08 +02:00
|
|
|
struct prefix *prefix;
|
|
|
|
struct prefix_ipv6 *src_p;
|
|
|
|
|
|
|
|
srcdest_rnode_prefixes(rnode,
|
|
|
|
(const struct prefix **)&prefix,
|
|
|
|
(const struct prefix **)&src_p);
|
|
|
|
mrnode = srcdest_rnode_get(merge, prefix, src_p);
|
2018-07-26 10:02:15 +02:00
|
|
|
struct isis_route_info *mrinfo = mrnode->info;
|
|
|
|
if (mrinfo) {
|
2018-07-24 17:40:24 +02:00
|
|
|
route_unlock_node(mrnode);
|
2018-07-26 10:02:15 +02:00
|
|
|
if (CHECK_FLAG(mrinfo->flag,
|
|
|
|
ISIS_ROUTE_FLAG_ACTIVE)) {
|
|
|
|
/* Clear the ZEBRA_SYNCED flag on the
|
|
|
|
* L2 route when L1 wins, otherwise L2
|
|
|
|
* won't get reinstalled when L1
|
|
|
|
* disappears.
|
|
|
|
*/
|
|
|
|
UNSET_FLAG(
|
|
|
|
rinfo->flag,
|
|
|
|
ISIS_ROUTE_FLAG_ZEBRA_SYNCED
|
|
|
|
);
|
|
|
|
continue;
|
2019-05-28 16:46:06 +02:00
|
|
|
} else if (CHECK_FLAG(rinfo->flag,
|
|
|
|
ISIS_ROUTE_FLAG_ACTIVE)) {
|
2018-07-26 10:02:15 +02:00
|
|
|
/* Clear the ZEBRA_SYNCED flag on the L1
|
|
|
|
* route when L2 wins, otherwise L1
|
|
|
|
* won't get reinstalled when it
|
|
|
|
* reappears.
|
|
|
|
*/
|
|
|
|
UNSET_FLAG(
|
|
|
|
mrinfo->flag,
|
|
|
|
ISIS_ROUTE_FLAG_ZEBRA_SYNCED
|
|
|
|
);
|
2019-05-28 16:46:06 +02:00
|
|
|
} else if (
|
|
|
|
CHECK_FLAG(
|
|
|
|
mrinfo->flag,
|
|
|
|
ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) {
|
|
|
|
continue;
|
2018-07-26 10:02:15 +02:00
|
|
|
}
|
2018-07-24 17:40:24 +02:00
|
|
|
}
|
|
|
|
mrnode->info = rnode->info;
|
|
|
|
}
|
2005-09-26 20:26:26 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-07-24 17:40:24 +02:00
|
|
|
_isis_route_verify_table(area, merge, tables);
|
2005-09-26 20:26:26 +02:00
|
|
|
route_table_finish(merge);
|
|
|
|
}
|
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
void isis_route_invalidate_table(struct isis_area *area,
|
|
|
|
struct route_table *table)
|
|
|
|
{
|
|
|
|
struct route_node *rode;
|
|
|
|
struct isis_route_info *rinfo;
|
2018-07-26 22:53:08 +02:00
|
|
|
for (rode = route_top(table); rode; rode = srcdest_route_next(rode)) {
|
2012-03-24 16:35:20 +01:00
|
|
|
if (rode->info == NULL)
|
|
|
|
continue;
|
|
|
|
rinfo = rode->info;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
UNSET_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
|
|
|
|
}
|
|
|
|
}
|