2023-02-08 13:17:09 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2003-12-23 09:09:43 +01:00
|
|
|
/*
|
|
|
|
* IS-IS Rout(e)ing protocol - isis_adjacency.c
|
|
|
|
* handling of IS-IS adjacencies
|
|
|
|
*
|
|
|
|
* Copyright (C) 2001,2002 Sampo Saaristo
|
|
|
|
* Tampere University of Technology
|
|
|
|
* Institute of Communications Engineering
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
|
|
|
#include "log.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "hash.h"
|
|
|
|
#include "vty.h"
|
|
|
|
#include "linklist.h"
|
2023-03-07 20:22:48 +01:00
|
|
|
#include "frrevent.h"
|
2003-12-23 09:09:43 +01:00
|
|
|
#include "if.h"
|
|
|
|
#include "stream.h"
|
2022-04-07 12:25:12 +02:00
|
|
|
#include "bfd.h"
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
#include "isisd/isis_constants.h"
|
|
|
|
#include "isisd/isis_common.h"
|
2012-03-24 16:35:20 +01:00
|
|
|
#include "isisd/isis_flags.h"
|
2003-12-23 09:09:43 +01:00
|
|
|
#include "isisd/isisd.h"
|
|
|
|
#include "isisd/isis_circuit.h"
|
|
|
|
#include "isisd/isis_adjacency.h"
|
|
|
|
#include "isisd/isis_misc.h"
|
|
|
|
#include "isisd/isis_dr.h"
|
|
|
|
#include "isisd/isis_dynhn.h"
|
|
|
|
#include "isisd/isis_pdu.h"
|
2012-03-24 16:35:20 +01:00
|
|
|
#include "isisd/isis_lsp.h"
|
|
|
|
#include "isisd/isis_events.h"
|
2017-04-27 13:56:43 +02:00
|
|
|
#include "isisd/isis_mt.h"
|
2018-03-05 21:00:40 +01:00
|
|
|
#include "isisd/isis_tlvs.h"
|
fabricd: adjacency formation optimization as per section 2.4
OpenFabric changes IS-IS's initial database synchronization. While
regular IS-IS will simultaneuously exchange LSPs with all neighboring
routers during startup, this is considered too much churn for a densely
connected fabric.
To mitigate this, OpenFabric prescribes that a router should only
bring up an adjacency with a single neighbor and perform a full
synchronization with that neighbor, before bringing up further
adjacencies.
This is implemented by having a field `initial_sync_state` in the
fabricd datastructure which tracks whether an initial sync is still
pending, currently in progress, or complete.
When an initial sync is pending, the state will transition to the
in-progress state when the first IIH is received.
During this state, all IIHs from other routers are ignored. Any
IIHs transmitted on any link other than the one to the router with
which we are performing the initial sync will always report the far
end as DOWN in their threeway handshake state, avoiding the formation of
additional adjacencies.
The state will be left if all the SRM and SSN flags on the
initial-sync circuit are cleared (meaning that initial sync has
completed). This is checked in `lsp_tick`. When this condition occurrs,
we progress to the initial-sync-complete state, allowing other
adjacencies to form.
The state can also be left if the initial synchronization is taking too
long to succeed, for whatever reason. In that case, we fall back to the
initial-sync-pending state and will reattempt initial synchronization
with a different neighbor.
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
2018-04-02 17:55:26 +02:00
|
|
|
#include "isisd/fabricd.h"
|
2019-10-17 20:33:53 +02:00
|
|
|
#include "isisd/isis_nb.h"
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2021-03-22 18:27:58 +01:00
|
|
|
DEFINE_MTYPE_STATIC(ISISD, ISIS_ADJACENCY, "ISIS adjacency");
|
|
|
|
DEFINE_MTYPE(ISISD, ISIS_ADJACENCY_INFO, "ISIS adjacency info");
|
|
|
|
|
2020-09-15 22:46:15 +02:00
|
|
|
static struct isis_adjacency *adj_alloc(struct isis_circuit *circuit,
|
|
|
|
const uint8_t *id)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2004-09-10 22:48:21 +02:00
|
|
|
struct isis_adjacency *adj;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2005-09-01 19:52:33 +02:00
|
|
|
adj = XCALLOC(MTYPE_ISIS_ADJACENCY, sizeof(struct isis_adjacency));
|
2004-09-10 22:48:21 +02:00
|
|
|
memcpy(adj->sysid, id, ISIS_SYS_ID_LEN);
|
|
|
|
|
2020-09-15 22:46:15 +02:00
|
|
|
adj->snmp_idx = ++circuit->snmp_adj_idx_gen;
|
|
|
|
|
|
|
|
if (circuit->snmp_adj_list == NULL)
|
|
|
|
circuit->snmp_adj_list = list_new();
|
|
|
|
|
|
|
|
adj->snmp_list_node = listnode_add(circuit->snmp_adj_list, adj);
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
return adj;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
struct isis_adjacency *isis_new_adj(const uint8_t *id, const uint8_t *snpa,
|
2003-12-23 09:09:43 +01:00
|
|
|
int level, struct isis_circuit *circuit)
|
|
|
|
{
|
|
|
|
struct isis_adjacency *adj;
|
2004-09-10 22:48:21 +02:00
|
|
|
int i;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-09-15 22:46:15 +02:00
|
|
|
adj = adj_alloc(circuit, id); /* P2P kludge */
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if (snpa) {
|
|
|
|
memcpy(adj->snpa, snpa, ETH_ALEN);
|
|
|
|
} else {
|
|
|
|
memset(adj->snpa, ' ', ETH_ALEN);
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
adj->circuit = circuit;
|
|
|
|
adj->level = level;
|
|
|
|
adj->flaps = 0;
|
|
|
|
adj->last_flap = time(NULL);
|
2018-03-05 21:00:40 +01:00
|
|
|
adj->threeway_state = ISIS_THREEWAY_DOWN;
|
2012-03-24 16:35:20 +01:00
|
|
|
if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
|
2012-03-28 08:48:05 +02:00
|
|
|
listnode_add(circuit->u.bc.adjdb[level - 1], adj);
|
2012-03-24 16:35:20 +01:00
|
|
|
adj->dischanges[level - 1] = 0;
|
2004-09-10 22:48:21 +02:00
|
|
|
for (i = 0; i < DIS_RECORDS;
|
|
|
|
i++) /* clear N DIS state change records */
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
2004-09-10 22:48:21 +02:00
|
|
|
adj->dis_record[(i * ISIS_LEVELS) + level - 1].dis =
|
2003-12-23 09:09:43 +01:00
|
|
|
ISIS_UNKNOWN_DIS;
|
2004-09-10 22:48:21 +02:00
|
|
|
adj->dis_record[(i * ISIS_LEVELS) + level - 1]
|
2003-12-23 09:09:43 +01:00
|
|
|
.last_dis_change = time(NULL);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
}
|
2019-08-04 03:02:37 +02:00
|
|
|
adj->adj_sids = list_new();
|
2023-06-03 02:14:42 +02:00
|
|
|
adj->srv6_endx_sids = list_new();
|
2020-08-11 04:09:12 +02:00
|
|
|
listnode_add(circuit->area->adjacency_list, adj);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return adj;
|
|
|
|
}
|
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
struct isis_adjacency *isis_adj_lookup(const uint8_t *sysid, struct list *adjdb)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_adjacency *adj;
|
|
|
|
struct listnode *node;
|
|
|
|
|
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(adjdb, node, adj))
|
|
|
|
if (memcmp(adj->sysid, sysid, ISIS_SYS_ID_LEN) == 0)
|
|
|
|
return adj;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
struct isis_adjacency *isis_adj_lookup_snpa(const uint8_t *ssnpa,
|
2015-11-10 18:04:43 +01:00
|
|
|
struct list *adjdb)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
struct isis_adjacency *adj;
|
|
|
|
|
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(adjdb, node, adj))
|
|
|
|
if (memcmp(adj->snpa, ssnpa, ETH_ALEN) == 0)
|
|
|
|
return adj;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-08-11 04:09:12 +02:00
|
|
|
struct isis_adjacency *isis_adj_find(const struct isis_area *area, int level,
|
|
|
|
const uint8_t *sysid)
|
2019-08-04 03:02:37 +02:00
|
|
|
{
|
2020-08-11 04:09:12 +02:00
|
|
|
struct isis_adjacency *adj;
|
2019-08-04 03:02:37 +02:00
|
|
|
struct listnode *node;
|
|
|
|
|
2020-08-11 04:09:12 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO(area->adjacency_list, node, adj)) {
|
|
|
|
if (!(adj->level & level))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!memcmp(adj->sysid, sysid, ISIS_SYS_ID_LEN))
|
|
|
|
return adj;
|
2019-08-04 03:02:37 +02:00
|
|
|
}
|
|
|
|
|
2020-08-11 04:09:12 +02:00
|
|
|
return NULL;
|
2019-08-04 03:02:37 +02:00
|
|
|
}
|
|
|
|
|
2018-09-27 14:23:06 +02:00
|
|
|
DEFINE_HOOK(isis_adj_state_change_hook, (struct isis_adjacency *adj), (adj));
|
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
void isis_delete_adj(void *arg)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
struct isis_adjacency *adj = arg;
|
|
|
|
|
2005-09-28 20:45:54 +02:00
|
|
|
if (!adj)
|
|
|
|
return;
|
2020-09-15 22:46:15 +02:00
|
|
|
/* Remove self from snmp list without walking the list*/
|
|
|
|
list_delete_node(adj->circuit->snmp_adj_list, adj->snmp_list_node);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2022-12-25 16:26:52 +01:00
|
|
|
EVENT_OFF(adj->t_expire);
|
2020-05-19 13:52:04 +02:00
|
|
|
if (adj->adj_state != ISIS_ADJ_DOWN)
|
2018-09-27 14:23:06 +02:00
|
|
|
adj->adj_state = ISIS_ADJ_DOWN;
|
2012-03-24 16:35:20 +01:00
|
|
|
|
2020-05-19 13:52:04 +02:00
|
|
|
hook_call(isis_adj_state_change_hook, adj);
|
|
|
|
|
2019-02-25 21:18:13 +01:00
|
|
|
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->area_addresses);
|
|
|
|
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv4_addresses);
|
2021-06-30 17:23:56 +02:00
|
|
|
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ll_ipv6_addrs);
|
2022-07-28 18:21:24 +02:00
|
|
|
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->global_ipv6_addrs);
|
2017-04-27 13:56:41 +02:00
|
|
|
adj_mt_finish(adj);
|
2019-08-04 03:02:37 +02:00
|
|
|
list_delete(&adj->adj_sids);
|
2023-06-03 02:14:42 +02:00
|
|
|
list_delete(&adj->srv6_endx_sids);
|
2017-04-27 13:56:41 +02:00
|
|
|
|
2020-08-11 04:09:12 +02:00
|
|
|
listnode_delete(adj->circuit->area->adjacency_list, adj);
|
2005-09-28 20:45:54 +02:00
|
|
|
XFREE(MTYPE_ISIS_ADJACENCY, adj);
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
static const char *adj_state2string(int state)
|
|
|
|
{
|
|
|
|
|
|
|
|
switch (state) {
|
|
|
|
case ISIS_ADJ_INITIALIZING:
|
|
|
|
return "Initializing";
|
|
|
|
case ISIS_ADJ_UP:
|
|
|
|
return "Up";
|
|
|
|
case ISIS_ADJ_DOWN:
|
|
|
|
return "Down";
|
|
|
|
default:
|
|
|
|
return "Unknown";
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
return NULL; /* not reached */
|
|
|
|
}
|
|
|
|
|
2020-07-01 19:37:16 +02:00
|
|
|
static const char *adj_level2string(int level)
|
|
|
|
{
|
|
|
|
switch (level) {
|
|
|
|
case IS_LEVEL_1:
|
|
|
|
return "level-1";
|
|
|
|
case IS_LEVEL_2:
|
|
|
|
return "level-2";
|
|
|
|
case IS_LEVEL_1_AND_2:
|
|
|
|
return "level-1-2";
|
|
|
|
default:
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL; /* not reached */
|
|
|
|
}
|
|
|
|
|
2022-03-21 17:59:27 +01:00
|
|
|
static void isis_adj_route_switchover(struct isis_adjacency *adj)
|
|
|
|
{
|
|
|
|
union g_addr ip = {};
|
|
|
|
ifindex_t ifindex;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
if (!adj->circuit || !adj->circuit->interface)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ifindex = adj->circuit->interface->ifindex;
|
|
|
|
|
|
|
|
for (i = 0; i < adj->ipv4_address_count; i++) {
|
|
|
|
ip.ipv4 = adj->ipv4_addresses[i];
|
|
|
|
isis_circuit_switchover_routes(adj->circuit, AF_INET, &ip,
|
|
|
|
ifindex);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < adj->ll_ipv6_count; i++) {
|
|
|
|
ip.ipv6 = adj->ll_ipv6_addrs[i];
|
|
|
|
isis_circuit_switchover_routes(adj->circuit, AF_INET6, &ip,
|
|
|
|
ifindex);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < adj->global_ipv6_count; i++) {
|
|
|
|
ip.ipv6 = adj->global_ipv6_addrs[i];
|
|
|
|
isis_circuit_switchover_routes(adj->circuit, AF_INET6, &ip,
|
|
|
|
ifindex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-09 16:08:21 +02:00
|
|
|
void isis_adj_process_threeway(struct isis_adjacency **padj,
|
2018-03-05 21:00:40 +01:00
|
|
|
struct isis_threeway_adj *tw_adj,
|
|
|
|
enum isis_adj_usage adj_usage)
|
|
|
|
{
|
|
|
|
enum isis_threeway_state next_tw_state = ISIS_THREEWAY_DOWN;
|
2024-08-09 16:08:21 +02:00
|
|
|
struct isis_adjacency *adj = *padj;
|
2018-03-05 21:00:40 +01:00
|
|
|
|
2018-03-05 21:29:15 +01:00
|
|
|
if (tw_adj && !adj->circuit->disable_threeway_adj) {
|
2018-03-05 21:00:40 +01:00
|
|
|
if (tw_adj->state == ISIS_THREEWAY_DOWN) {
|
|
|
|
next_tw_state = ISIS_THREEWAY_INITIALIZING;
|
|
|
|
} else if (tw_adj->state == ISIS_THREEWAY_INITIALIZING) {
|
|
|
|
next_tw_state = ISIS_THREEWAY_UP;
|
|
|
|
} else if (tw_adj->state == ISIS_THREEWAY_UP) {
|
|
|
|
if (adj->threeway_state == ISIS_THREEWAY_DOWN)
|
|
|
|
next_tw_state = ISIS_THREEWAY_DOWN;
|
|
|
|
else
|
|
|
|
next_tw_state = ISIS_THREEWAY_UP;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
next_tw_state = ISIS_THREEWAY_UP;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (next_tw_state != adj->threeway_state) {
|
2020-06-19 21:04:33 +02:00
|
|
|
if (IS_DEBUG_ADJ_PACKETS) {
|
2018-03-05 21:00:40 +01:00
|
|
|
zlog_info("ISIS-Adj (%s): Threeway state change %s to %s",
|
|
|
|
adj->circuit->area->area_tag,
|
|
|
|
isis_threeway_state_name(adj->threeway_state),
|
|
|
|
isis_threeway_state_name(next_tw_state));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
fabricd: adjacency formation optimization as per section 2.4
OpenFabric changes IS-IS's initial database synchronization. While
regular IS-IS will simultaneuously exchange LSPs with all neighboring
routers during startup, this is considered too much churn for a densely
connected fabric.
To mitigate this, OpenFabric prescribes that a router should only
bring up an adjacency with a single neighbor and perform a full
synchronization with that neighbor, before bringing up further
adjacencies.
This is implemented by having a field `initial_sync_state` in the
fabricd datastructure which tracks whether an initial sync is still
pending, currently in progress, or complete.
When an initial sync is pending, the state will transition to the
in-progress state when the first IIH is received.
During this state, all IIHs from other routers are ignored. Any
IIHs transmitted on any link other than the one to the router with
which we are performing the initial sync will always report the far
end as DOWN in their threeway handshake state, avoiding the formation of
additional adjacencies.
The state will be left if all the SRM and SSN flags on the
initial-sync circuit are cleared (meaning that initial sync has
completed). This is checked in `lsp_tick`. When this condition occurrs,
we progress to the initial-sync-complete state, allowing other
adjacencies to form.
The state can also be left if the initial synchronization is taking too
long to succeed, for whatever reason. In that case, we fall back to the
initial-sync-pending state and will reattempt initial synchronization
with a different neighbor.
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
2018-04-02 17:55:26 +02:00
|
|
|
if (next_tw_state != ISIS_THREEWAY_DOWN)
|
|
|
|
fabricd_initial_sync_hello(adj->circuit);
|
|
|
|
|
2018-03-05 21:00:40 +01:00
|
|
|
if (next_tw_state == ISIS_THREEWAY_DOWN) {
|
2024-08-09 16:08:21 +02:00
|
|
|
isis_adj_state_change(padj, ISIS_ADJ_DOWN, "Neighbor restarted");
|
2018-03-05 21:00:40 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (next_tw_state == ISIS_THREEWAY_UP) {
|
|
|
|
if (adj->adj_state != ISIS_ADJ_UP) {
|
2024-08-09 16:08:21 +02:00
|
|
|
isis_adj_state_change(padj, ISIS_ADJ_UP, NULL);
|
2018-03-05 21:00:40 +01:00
|
|
|
adj->adj_usage = adj_usage;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-10 16:00:16 +02:00
|
|
|
if (adj->threeway_state != next_tw_state) {
|
|
|
|
send_hello_sched(adj->circuit, 0, TRIGGERED_IIH_DELAY);
|
|
|
|
}
|
|
|
|
|
2018-03-05 21:00:40 +01:00
|
|
|
adj->threeway_state = next_tw_state;
|
|
|
|
}
|
2021-03-18 12:45:23 +01:00
|
|
|
const char *isis_adj_name(const struct isis_adjacency *adj)
|
2020-07-01 19:37:16 +02:00
|
|
|
{
|
2023-01-26 17:47:04 +01:00
|
|
|
static char buf[ISO_SYSID_STRLEN];
|
|
|
|
|
2021-03-18 12:45:23 +01:00
|
|
|
if (!adj)
|
|
|
|
return "NONE";
|
|
|
|
|
2020-07-01 19:37:16 +02:00
|
|
|
struct isis_dynhn *dyn;
|
|
|
|
|
2021-06-11 17:27:46 +02:00
|
|
|
dyn = dynhn_find_by_id(adj->circuit->isis, adj->sysid);
|
2024-06-21 08:26:44 +02:00
|
|
|
if (adj->circuit->area->dynhostname && dyn)
|
2021-03-18 12:45:23 +01:00
|
|
|
return dyn->hostname;
|
2023-01-26 17:47:04 +01:00
|
|
|
|
|
|
|
snprintfrr(buf, sizeof(buf), "%pSY", adj->sysid);
|
|
|
|
return buf;
|
2021-03-18 12:45:23 +01:00
|
|
|
}
|
|
|
|
void isis_log_adj_change(struct isis_adjacency *adj,
|
|
|
|
enum isis_adj_state old_state,
|
|
|
|
enum isis_adj_state new_state, const char *reason)
|
|
|
|
{
|
2020-07-01 19:37:16 +02:00
|
|
|
zlog_info(
|
|
|
|
"%%ADJCHANGE: Adjacency to %s (%s) for %s changed from %s to %s, %s",
|
2021-03-18 12:45:23 +01:00
|
|
|
isis_adj_name(adj), adj->circuit->interface->name,
|
2020-07-01 19:37:16 +02:00
|
|
|
adj_level2string(adj->level), adj_state2string(old_state),
|
|
|
|
adj_state2string(new_state), reason ? reason : "unspecified");
|
|
|
|
}
|
2020-04-18 02:06:07 +02:00
|
|
|
void isis_adj_state_change(struct isis_adjacency **padj,
|
2012-03-24 16:35:20 +01:00
|
|
|
enum isis_adj_state new_state, const char *reason)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2020-04-18 02:06:07 +02:00
|
|
|
struct isis_adjacency *adj = *padj;
|
2018-10-10 16:00:16 +02:00
|
|
|
enum isis_adj_state old_state = adj->adj_state;
|
|
|
|
struct isis_circuit *circuit = adj->circuit;
|
2020-04-18 02:06:07 +02:00
|
|
|
bool del = false;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-06-08 18:00:42 +02:00
|
|
|
if (new_state == old_state)
|
|
|
|
return;
|
|
|
|
|
2022-05-20 15:29:21 +02:00
|
|
|
if (old_state == ISIS_ADJ_UP &&
|
|
|
|
!CHECK_FLAG(adj->circuit->flags, ISIS_CIRCUIT_IF_DOWN_FROM_Z)) {
|
2022-03-21 17:59:27 +01:00
|
|
|
if (IS_DEBUG_EVENTS)
|
|
|
|
zlog_debug(
|
|
|
|
"ISIS-Adj (%s): Starting fast-reroute on state change %d->%d: %s",
|
|
|
|
circuit->area->area_tag, old_state, new_state,
|
|
|
|
reason ? reason : "unspecified");
|
|
|
|
isis_adj_route_switchover(adj);
|
|
|
|
}
|
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
adj->adj_state = new_state;
|
2020-06-08 18:00:42 +02:00
|
|
|
send_hello_sched(circuit, adj->level, TRIGGERED_IIH_DELAY);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-06-19 21:04:33 +02:00
|
|
|
if (IS_DEBUG_ADJ_PACKETS) {
|
2004-12-24 01:14:50 +01:00
|
|
|
zlog_debug("ISIS-Adj (%s): Adjacency state change %d->%d: %s",
|
2004-09-10 22:48:21 +02:00
|
|
|
circuit->area->area_tag, old_state, new_state,
|
2012-03-24 16:35:20 +01:00
|
|
|
reason ? reason : "unspecified");
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-07-01 19:37:16 +02:00
|
|
|
if (circuit->area->log_adj_changes)
|
|
|
|
isis_log_adj_change(adj, old_state, new_state, reason);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-11-14 15:24:00 +01:00
|
|
|
#ifndef FABRICD
|
|
|
|
/* send northbound notification */
|
|
|
|
isis_notif_adj_state_change(adj, new_state, reason);
|
|
|
|
#endif /* ifndef FABRICD */
|
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
|
2018-10-10 16:00:16 +02:00
|
|
|
for (int level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) {
|
2012-03-24 16:35:20 +01:00
|
|
|
if ((adj->level & level) == 0)
|
|
|
|
continue;
|
|
|
|
if (new_state == ISIS_ADJ_UP) {
|
2020-09-15 22:46:15 +02:00
|
|
|
circuit->adj_state_changes++;
|
2012-03-28 08:48:05 +02:00
|
|
|
circuit->upadjcount[level - 1]++;
|
|
|
|
/* update counter & timers for debugging
|
|
|
|
* purposes */
|
|
|
|
adj->last_flap = time(NULL);
|
|
|
|
adj->flaps++;
|
2024-04-09 15:04:39 +02:00
|
|
|
} else {
|
|
|
|
if (old_state == ISIS_ADJ_UP) {
|
|
|
|
circuit->adj_state_changes++;
|
|
|
|
|
|
|
|
circuit->upadjcount[level - 1]--;
|
|
|
|
if (circuit->upadjcount[level - 1] == 0)
|
|
|
|
isis_tx_queue_clean(
|
|
|
|
circuit->tx_queue);
|
|
|
|
}
|
2017-10-03 01:42:22 +02:00
|
|
|
|
2021-12-14 14:28:08 +01:00
|
|
|
if (new_state == ISIS_ADJ_DOWN) {
|
|
|
|
listnode_delete(
|
|
|
|
circuit->u.bc.adjdb[level - 1],
|
|
|
|
adj);
|
|
|
|
|
2020-06-08 18:00:42 +02:00
|
|
|
del = true;
|
2021-12-14 14:28:08 +01:00
|
|
|
}
|
2012-03-28 08:48:05 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2012-03-28 08:48:05 +02:00
|
|
|
if (circuit->u.bc.lan_neighs[level - 1]) {
|
|
|
|
list_delete_all_node(
|
|
|
|
circuit->u.bc.lan_neighs[level - 1]);
|
|
|
|
isis_adj_build_neigh_list(
|
|
|
|
circuit->u.bc.adjdb[level - 1],
|
|
|
|
circuit->u.bc.lan_neighs[level - 1]);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
/* On adjacency state change send new pseudo LSP if we
|
|
|
|
* are the DR */
|
|
|
|
if (circuit->u.bc.is_dr[level - 1])
|
|
|
|
lsp_regenerate_schedule_pseudo(circuit, level);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
} else if (circuit->circ_type == CIRCUIT_T_P2P) {
|
2018-10-10 16:00:16 +02:00
|
|
|
for (int level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) {
|
2012-03-24 16:35:20 +01:00
|
|
|
if ((adj->level & level) == 0)
|
|
|
|
continue;
|
|
|
|
if (new_state == ISIS_ADJ_UP) {
|
2012-03-28 08:48:05 +02:00
|
|
|
circuit->upadjcount[level - 1]++;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2012-03-28 08:48:05 +02:00
|
|
|
/* update counter & timers for debugging
|
|
|
|
* purposes */
|
|
|
|
adj->last_flap = time(NULL);
|
|
|
|
adj->flaps++;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
fabricd: adjacency formation optimization as per section 2.4
OpenFabric changes IS-IS's initial database synchronization. While
regular IS-IS will simultaneuously exchange LSPs with all neighboring
routers during startup, this is considered too much churn for a densely
connected fabric.
To mitigate this, OpenFabric prescribes that a router should only
bring up an adjacency with a single neighbor and perform a full
synchronization with that neighbor, before bringing up further
adjacencies.
This is implemented by having a field `initial_sync_state` in the
fabricd datastructure which tracks whether an initial sync is still
pending, currently in progress, or complete.
When an initial sync is pending, the state will transition to the
in-progress state when the first IIH is received.
During this state, all IIHs from other routers are ignored. Any
IIHs transmitted on any link other than the one to the router with
which we are performing the initial sync will always report the far
end as DOWN in their threeway handshake state, avoiding the formation of
additional adjacencies.
The state will be left if all the SRM and SSN flags on the
initial-sync circuit are cleared (meaning that initial sync has
completed). This is checked in `lsp_tick`. When this condition occurrs,
we progress to the initial-sync-complete state, allowing other
adjacencies to form.
The state can also be left if the initial synchronization is taking too
long to succeed, for whatever reason. In that case, we fall back to the
initial-sync-pending state and will reattempt initial synchronization
with a different neighbor.
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
2018-04-02 17:55:26 +02:00
|
|
|
if (level == IS_LEVEL_1) {
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_timer(
|
|
|
|
master, send_l1_csnp, circuit,
|
|
|
|
0, &circuit->t_send_csnp[0]);
|
fabricd: adjacency formation optimization as per section 2.4
OpenFabric changes IS-IS's initial database synchronization. While
regular IS-IS will simultaneuously exchange LSPs with all neighboring
routers during startup, this is considered too much churn for a densely
connected fabric.
To mitigate this, OpenFabric prescribes that a router should only
bring up an adjacency with a single neighbor and perform a full
synchronization with that neighbor, before bringing up further
adjacencies.
This is implemented by having a field `initial_sync_state` in the
fabricd datastructure which tracks whether an initial sync is still
pending, currently in progress, or complete.
When an initial sync is pending, the state will transition to the
in-progress state when the first IIH is received.
During this state, all IIHs from other routers are ignored. Any
IIHs transmitted on any link other than the one to the router with
which we are performing the initial sync will always report the far
end as DOWN in their threeway handshake state, avoiding the formation of
additional adjacencies.
The state will be left if all the SRM and SSN flags on the
initial-sync circuit are cleared (meaning that initial sync has
completed). This is checked in `lsp_tick`. When this condition occurrs,
we progress to the initial-sync-complete state, allowing other
adjacencies to form.
The state can also be left if the initial synchronization is taking too
long to succeed, for whatever reason. In that case, we fall back to the
initial-sync-pending state and will reattempt initial synchronization
with a different neighbor.
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
2018-04-02 17:55:26 +02:00
|
|
|
} else {
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_timer(
|
|
|
|
master, send_l2_csnp, circuit,
|
|
|
|
0, &circuit->t_send_csnp[1]);
|
fabricd: adjacency formation optimization as per section 2.4
OpenFabric changes IS-IS's initial database synchronization. While
regular IS-IS will simultaneuously exchange LSPs with all neighboring
routers during startup, this is considered too much churn for a densely
connected fabric.
To mitigate this, OpenFabric prescribes that a router should only
bring up an adjacency with a single neighbor and perform a full
synchronization with that neighbor, before bringing up further
adjacencies.
This is implemented by having a field `initial_sync_state` in the
fabricd datastructure which tracks whether an initial sync is still
pending, currently in progress, or complete.
When an initial sync is pending, the state will transition to the
in-progress state when the first IIH is received.
During this state, all IIHs from other routers are ignored. Any
IIHs transmitted on any link other than the one to the router with
which we are performing the initial sync will always report the far
end as DOWN in their threeway handshake state, avoiding the formation of
additional adjacencies.
The state will be left if all the SRM and SSN flags on the
initial-sync circuit are cleared (meaning that initial sync has
completed). This is checked in `lsp_tick`. When this condition occurrs,
we progress to the initial-sync-complete state, allowing other
adjacencies to form.
The state can also be left if the initial synchronization is taking too
long to succeed, for whatever reason. In that case, we fall back to the
initial-sync-pending state and will reattempt initial synchronization
with a different neighbor.
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
2018-04-02 17:55:26 +02:00
|
|
|
}
|
2024-04-09 15:04:39 +02:00
|
|
|
} else {
|
|
|
|
if (old_state == ISIS_ADJ_UP) {
|
|
|
|
circuit->upadjcount[level - 1]--;
|
|
|
|
if (circuit->upadjcount[level - 1] == 0)
|
|
|
|
isis_tx_queue_clean(
|
|
|
|
circuit->tx_queue);
|
|
|
|
}
|
2017-10-03 01:42:22 +02:00
|
|
|
|
2021-12-14 14:28:08 +01:00
|
|
|
if (new_state == ISIS_ADJ_DOWN) {
|
|
|
|
if (adj->circuit->u.p2p.neighbor == adj)
|
|
|
|
adj->circuit->u.p2p.neighbor =
|
|
|
|
NULL;
|
|
|
|
|
2020-06-08 18:00:42 +02:00
|
|
|
del = true;
|
2021-12-14 14:28:08 +01:00
|
|
|
}
|
2012-03-28 08:48:05 +02:00
|
|
|
}
|
2012-03-24 16:35:20 +01:00
|
|
|
}
|
2020-04-18 02:06:07 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-09-23 16:37:21 +02:00
|
|
|
hook_call(isis_adj_state_change_hook, adj);
|
|
|
|
|
2020-04-18 02:06:07 +02:00
|
|
|
if (del) {
|
|
|
|
isis_delete_adj(adj);
|
|
|
|
*padj = NULL;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void isis_adj_print(struct isis_adjacency *adj)
|
|
|
|
{
|
|
|
|
struct isis_dynhn *dyn;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if (!adj)
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
2021-06-11 17:27:46 +02:00
|
|
|
dyn = dynhn_find_by_id(adj->circuit->isis, adj->sysid);
|
2003-12-23 09:09:43 +01:00
|
|
|
if (dyn)
|
2017-07-05 18:37:36 +02:00
|
|
|
zlog_debug("%s", dyn->hostname);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2023-01-26 17:47:04 +01:00
|
|
|
zlog_debug("SystemId %20pSY SNPA %pSY, level %d; Holding Time %d",
|
|
|
|
adj->sysid, adj->snpa, adj->level, adj->hold_time);
|
2017-06-21 15:21:00 +02:00
|
|
|
if (adj->ipv4_address_count) {
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_debug("IPv4 Address(es):");
|
2017-06-21 15:21:00 +02:00
|
|
|
for (unsigned int i = 0; i < adj->ipv4_address_count; i++)
|
2020-10-22 20:30:34 +02:00
|
|
|
zlog_debug("%pI4", &adj->ipv4_addresses[i]);
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-06-30 17:23:56 +02:00
|
|
|
if (adj->ll_ipv6_count) {
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_debug("IPv6 Address(es):");
|
2021-06-30 17:23:56 +02:00
|
|
|
for (unsigned int i = 0; i < adj->ll_ipv6_count; i++) {
|
2017-06-21 15:21:00 +02:00
|
|
|
char buf[INET6_ADDRSTRLEN];
|
2021-06-30 17:23:56 +02:00
|
|
|
inet_ntop(AF_INET6, &adj->ll_ipv6_addrs[i], buf,
|
2017-06-21 15:21:00 +02:00
|
|
|
sizeof(buf));
|
|
|
|
zlog_debug("%s", buf);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2004-12-24 01:14:50 +01:00
|
|
|
zlog_debug("Speaks: %s", nlpid2string(&adj->nlpids));
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-10-17 20:33:53 +02:00
|
|
|
const char *isis_adj_yang_state(enum isis_adj_state state)
|
|
|
|
{
|
|
|
|
switch (state) {
|
|
|
|
case ISIS_ADJ_DOWN:
|
|
|
|
return "down";
|
|
|
|
case ISIS_ADJ_UP:
|
|
|
|
return "up";
|
|
|
|
case ISIS_ADJ_INITIALIZING:
|
|
|
|
return "init";
|
2023-01-30 16:08:47 +01:00
|
|
|
case ISIS_ADJ_UNKNOWN:
|
2019-10-17 20:33:53 +02:00
|
|
|
return "failed";
|
|
|
|
}
|
2023-01-30 16:08:47 +01:00
|
|
|
|
|
|
|
assert(!"Reached end of function where we are not expecting to");
|
2019-10-17 20:33:53 +02:00
|
|
|
}
|
|
|
|
|
2022-03-01 22:18:12 +01:00
|
|
|
void isis_adj_expire(struct event *thread)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_adjacency *adj;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the adjacency
|
|
|
|
*/
|
2022-12-25 16:26:52 +01:00
|
|
|
adj = EVENT_ARG(thread);
|
2003-12-23 09:09:43 +01:00
|
|
|
assert(adj);
|
2004-02-09 12:09:39 +01:00
|
|
|
adj->t_expire = NULL;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
/* trigger the adj expire event */
|
2020-04-18 02:06:07 +02:00
|
|
|
isis_adj_state_change(&adj, ISIS_ADJ_DOWN, "holding time expired");
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2022-02-24 09:33:53 +01:00
|
|
|
/*
|
|
|
|
* show isis neighbor [detail] json
|
|
|
|
*/
|
|
|
|
void isis_adj_print_json(struct isis_adjacency *adj, struct json_object *json,
|
|
|
|
char detail)
|
|
|
|
{
|
|
|
|
json_object *iface_json, *ipv4_addr_json, *ipv6_link_json,
|
|
|
|
*ipv6_non_link_json, *topo_json, *dis_flaps_json,
|
|
|
|
*area_addr_json, *adj_sid_json;
|
|
|
|
time_t now;
|
|
|
|
struct isis_dynhn *dyn;
|
|
|
|
int level;
|
|
|
|
char buf[256];
|
|
|
|
|
|
|
|
json_object_string_add(json, "adj", isis_adj_name(adj));
|
|
|
|
|
|
|
|
if (detail == ISIS_UI_LEVEL_BRIEF) {
|
|
|
|
if (adj->circuit)
|
|
|
|
json_object_string_add(json, "interface",
|
|
|
|
adj->circuit->interface->name);
|
|
|
|
else
|
|
|
|
json_object_string_add(json, "interface",
|
|
|
|
"NULL circuit!");
|
|
|
|
json_object_int_add(json, "level", adj->level);
|
|
|
|
json_object_string_add(json, "state",
|
|
|
|
adj_state2string(adj->adj_state));
|
|
|
|
now = time(NULL);
|
|
|
|
if (adj->last_upd) {
|
|
|
|
if (adj->last_upd + adj->hold_time < now)
|
|
|
|
json_object_string_add(json, "last-upd",
|
|
|
|
"expiring");
|
|
|
|
else
|
|
|
|
json_object_string_add(
|
|
|
|
json, "expires-in",
|
|
|
|
time2string(adj->last_upd +
|
|
|
|
adj->hold_time - now));
|
|
|
|
}
|
2023-01-26 17:47:04 +01:00
|
|
|
json_object_string_addf(json, "snpa", "%pSY", adj->snpa);
|
2022-02-24 09:33:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (detail == ISIS_UI_LEVEL_DETAIL) {
|
|
|
|
struct sr_adjacency *sra;
|
|
|
|
struct listnode *anode;
|
|
|
|
|
|
|
|
level = adj->level;
|
|
|
|
iface_json = json_object_new_object();
|
|
|
|
json_object_object_add(json, "interface", iface_json);
|
|
|
|
if (adj->circuit)
|
|
|
|
json_object_string_add(iface_json, "name",
|
|
|
|
adj->circuit->interface->name);
|
|
|
|
else
|
|
|
|
json_object_string_add(iface_json, "name",
|
|
|
|
"null-circuit");
|
|
|
|
json_object_int_add(json, "level", adj->level);
|
|
|
|
json_object_string_add(iface_json, "state",
|
|
|
|
adj_state2string(adj->adj_state));
|
|
|
|
now = time(NULL);
|
|
|
|
if (adj->last_upd) {
|
|
|
|
if (adj->last_upd + adj->hold_time < now)
|
|
|
|
json_object_string_add(iface_json, "last-upd",
|
|
|
|
"expiring");
|
|
|
|
else
|
|
|
|
json_object_string_add(
|
|
|
|
json, "expires-in",
|
|
|
|
time2string(adj->last_upd +
|
|
|
|
adj->hold_time - now));
|
|
|
|
} else
|
|
|
|
json_object_string_add(json, "expires-in",
|
|
|
|
time2string(adj->hold_time));
|
|
|
|
json_object_int_add(iface_json, "adj-flaps", adj->flaps);
|
|
|
|
json_object_string_add(iface_json, "last-ago",
|
|
|
|
time2string(now - adj->last_flap));
|
|
|
|
json_object_string_add(iface_json, "circuit-type",
|
|
|
|
circuit_t2string(adj->circuit_t));
|
|
|
|
json_object_string_add(iface_json, "speaks",
|
|
|
|
nlpid2string(&adj->nlpids));
|
|
|
|
if (adj->mt_count != 1 ||
|
|
|
|
adj->mt_set[0] != ISIS_MT_IPV4_UNICAST) {
|
|
|
|
topo_json = json_object_new_object();
|
|
|
|
json_object_object_add(iface_json, "topologies",
|
|
|
|
topo_json);
|
|
|
|
for (unsigned int i = 0; i < adj->mt_count; i++) {
|
|
|
|
snprintfrr(buf, sizeof(buf), "topo-%d", i);
|
|
|
|
json_object_string_add(
|
|
|
|
topo_json, buf,
|
|
|
|
isis_mtid2str(adj->mt_set[i]));
|
|
|
|
}
|
|
|
|
}
|
2023-01-26 17:47:04 +01:00
|
|
|
json_object_string_addf(iface_json, "snpa", "%pSY", adj->snpa);
|
2022-02-24 09:33:53 +01:00
|
|
|
if (adj->circuit &&
|
|
|
|
(adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) {
|
|
|
|
dyn = dynhn_find_by_id(adj->circuit->isis, adj->lanid);
|
|
|
|
if (dyn) {
|
|
|
|
snprintfrr(buf, sizeof(buf), "%s-%02x",
|
|
|
|
dyn->hostname,
|
|
|
|
adj->lanid[ISIS_SYS_ID_LEN]);
|
|
|
|
json_object_string_add(iface_json, "lan-id",
|
|
|
|
buf);
|
|
|
|
} else {
|
2023-01-26 17:47:04 +01:00
|
|
|
json_object_string_addf(iface_json, "lan-id",
|
|
|
|
"%pSY", adj->lanid);
|
2022-02-24 09:33:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
json_object_int_add(iface_json, "lan-prio",
|
|
|
|
adj->prio[adj->level - 1]);
|
|
|
|
|
|
|
|
dis_flaps_json = json_object_new_object();
|
|
|
|
json_object_object_add(iface_json, "dis-flaps",
|
|
|
|
dis_flaps_json);
|
|
|
|
json_object_string_add(
|
|
|
|
dis_flaps_json, "dis-record",
|
|
|
|
isis_disflag2string(
|
|
|
|
adj->dis_record[ISIS_LEVELS + level - 1]
|
|
|
|
.dis));
|
|
|
|
json_object_int_add(dis_flaps_json, "last",
|
|
|
|
adj->dischanges[level - 1]);
|
|
|
|
json_object_string_add(
|
|
|
|
dis_flaps_json, "ago",
|
|
|
|
time2string(now - (adj->dis_record[ISIS_LEVELS +
|
|
|
|
level - 1]
|
|
|
|
.last_dis_change)));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (adj->area_address_count) {
|
|
|
|
area_addr_json = json_object_new_object();
|
|
|
|
json_object_object_add(iface_json, "area-address",
|
|
|
|
area_addr_json);
|
|
|
|
for (unsigned int i = 0; i < adj->area_address_count;
|
|
|
|
i++) {
|
2023-01-26 17:47:04 +01:00
|
|
|
json_object_string_addf(
|
|
|
|
area_addr_json, "isonet", "%pIS",
|
|
|
|
&adj->area_addresses[i]);
|
2022-02-24 09:33:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (adj->ipv4_address_count) {
|
|
|
|
ipv4_addr_json = json_object_new_object();
|
|
|
|
json_object_object_add(iface_json, "ipv4-address",
|
|
|
|
ipv4_addr_json);
|
|
|
|
for (unsigned int i = 0; i < adj->ipv4_address_count;
|
|
|
|
i++){
|
|
|
|
inet_ntop(AF_INET, &adj->ipv4_addresses[i], buf,
|
|
|
|
sizeof(buf));
|
|
|
|
json_object_string_add(ipv4_addr_json, "ipv4", buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (adj->ll_ipv6_count) {
|
|
|
|
ipv6_link_json = json_object_new_object();
|
|
|
|
json_object_object_add(iface_json, "ipv6-link-local",
|
|
|
|
ipv6_link_json);
|
|
|
|
for (unsigned int i = 0; i < adj->ll_ipv6_count; i++) {
|
|
|
|
inet_ntop(AF_INET6, &adj->ll_ipv6_addrs[i], buf,
|
|
|
|
sizeof(buf));
|
|
|
|
json_object_string_add(ipv6_link_json, "ipv6",
|
|
|
|
buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (adj->global_ipv6_count) {
|
|
|
|
ipv6_non_link_json = json_object_new_object();
|
|
|
|
json_object_object_add(iface_json, "ipv6-global",
|
|
|
|
ipv6_non_link_json);
|
|
|
|
for (unsigned int i = 0; i < adj->global_ipv6_count;
|
|
|
|
i++) {
|
|
|
|
inet_ntop(AF_INET6, &adj->global_ipv6_addrs[i],
|
|
|
|
buf, sizeof(buf));
|
|
|
|
json_object_string_add(ipv6_non_link_json,
|
|
|
|
"ipv6", buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
adj_sid_json = json_object_new_object();
|
|
|
|
json_object_object_add(iface_json, "adj-sid", adj_sid_json);
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(adj->adj_sids, anode, sra)) {
|
|
|
|
const char *adj_type;
|
|
|
|
const char *backup;
|
|
|
|
uint32_t sid;
|
|
|
|
|
|
|
|
switch (sra->adj->circuit->circ_type) {
|
|
|
|
case CIRCUIT_T_BROADCAST:
|
|
|
|
adj_type = "LAN Adjacency-SID";
|
|
|
|
sid = sra->u.ladj_sid->sid;
|
|
|
|
break;
|
|
|
|
case CIRCUIT_T_P2P:
|
|
|
|
adj_type = "Adjacency-SID";
|
|
|
|
sid = sra->u.adj_sid->sid;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
2024-04-03 15:58:05 +02:00
|
|
|
backup = (sra->type == ISIS_SR_ADJ_BACKUP) ? " (backup)"
|
2022-02-24 09:33:53 +01:00
|
|
|
: "";
|
|
|
|
|
|
|
|
json_object_string_add(adj_sid_json, "nexthop",
|
|
|
|
(sra->nexthop.family == AF_INET)
|
|
|
|
? "IPv4"
|
|
|
|
: "IPv6");
|
|
|
|
json_object_string_add(adj_sid_json, "adj-type",
|
|
|
|
adj_type);
|
|
|
|
json_object_string_add(adj_sid_json, "is-backup",
|
|
|
|
backup);
|
|
|
|
json_object_int_add(adj_sid_json, "sid", sid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/*
|
2012-03-24 16:35:20 +01:00
|
|
|
* show isis neighbor [detail]
|
2003-12-23 09:09:43 +01:00
|
|
|
*/
|
2012-03-24 16:35:20 +01:00
|
|
|
void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
|
|
|
|
char detail)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
time_t now;
|
|
|
|
struct isis_dynhn *dyn;
|
2004-09-10 22:48:21 +02:00
|
|
|
int level;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-03-18 12:45:23 +01:00
|
|
|
vty_out(vty, " %-20s", isis_adj_name(adj));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if (detail == ISIS_UI_LEVEL_BRIEF) {
|
|
|
|
if (adj->circuit)
|
2012-03-24 16:35:20 +01:00
|
|
|
vty_out(vty, "%-12s", adj->circuit->interface->name);
|
2017-05-06 15:50:45 +02:00
|
|
|
else
|
2017-07-13 17:49:13 +02:00
|
|
|
vty_out(vty, "NULL circuit!");
|
2012-03-24 16:35:20 +01:00
|
|
|
vty_out(vty, "%-3u", adj->level); /* level */
|
|
|
|
vty_out(vty, "%-13s", adj_state2string(adj->adj_state));
|
|
|
|
now = time(NULL);
|
2020-09-23 16:46:44 +02:00
|
|
|
if (adj->last_upd) {
|
2021-11-03 10:40:40 +01:00
|
|
|
if (adj->last_upd + adj->hold_time < now)
|
2024-05-03 17:04:05 +02:00
|
|
|
vty_out(vty, " Expiring ");
|
2020-09-23 16:46:44 +02:00
|
|
|
else
|
|
|
|
vty_out(vty, " %-9llu",
|
|
|
|
(unsigned long long)adj->last_upd
|
|
|
|
+ adj->hold_time - now);
|
|
|
|
} else
|
2024-05-03 17:04:05 +02:00
|
|
|
vty_out(vty, " - ");
|
2023-01-26 17:47:04 +01:00
|
|
|
vty_out(vty, "%-10pSY", adj->snpa);
|
2017-07-13 17:49:13 +02:00
|
|
|
vty_out(vty, "\n");
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if (detail == ISIS_UI_LEVEL_DETAIL) {
|
2019-08-04 03:02:37 +02:00
|
|
|
struct sr_adjacency *sra;
|
|
|
|
struct listnode *anode;
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
level = adj->level;
|
2017-07-13 19:04:25 +02:00
|
|
|
vty_out(vty, "\n");
|
2004-09-10 22:48:21 +02:00
|
|
|
if (adj->circuit)
|
2012-03-24 16:35:20 +01:00
|
|
|
vty_out(vty, " Interface: %s",
|
2004-09-10 22:48:21 +02:00
|
|
|
adj->circuit->interface->name);
|
2017-07-17 14:03:14 +02:00
|
|
|
else
|
2012-03-24 16:35:20 +01:00
|
|
|
vty_out(vty, " Interface: NULL circuit");
|
2004-09-10 22:48:21 +02:00
|
|
|
vty_out(vty, ", Level: %u", adj->level); /* level */
|
|
|
|
vty_out(vty, ", State: %s", adj_state2string(adj->adj_state));
|
|
|
|
now = time(NULL);
|
2020-09-23 16:46:44 +02:00
|
|
|
if (adj->last_upd) {
|
2021-11-03 10:40:40 +01:00
|
|
|
if (adj->last_upd + adj->hold_time < now)
|
2020-09-23 16:46:44 +02:00
|
|
|
vty_out(vty, " Expiring");
|
|
|
|
else
|
|
|
|
vty_out(vty, ", Expires in %s",
|
|
|
|
time2string(adj->last_upd
|
|
|
|
+ adj->hold_time - now));
|
|
|
|
} else
|
2004-09-10 22:48:21 +02:00
|
|
|
vty_out(vty, ", Expires in %s",
|
|
|
|
time2string(adj->hold_time));
|
2017-07-13 19:04:25 +02:00
|
|
|
vty_out(vty, "\n");
|
2012-03-24 16:35:20 +01:00
|
|
|
vty_out(vty, " Adjacency flaps: %u", adj->flaps);
|
2004-09-10 22:48:21 +02:00
|
|
|
vty_out(vty, ", Last: %s ago",
|
|
|
|
time2string(now - adj->last_flap));
|
2017-07-13 19:04:25 +02:00
|
|
|
vty_out(vty, "\n");
|
2012-03-24 16:35:20 +01:00
|
|
|
vty_out(vty, " Circuit type: %s",
|
2012-11-27 02:10:30 +01:00
|
|
|
circuit_t2string(adj->circuit_t));
|
2004-09-10 22:48:21 +02:00
|
|
|
vty_out(vty, ", Speaks: %s", nlpid2string(&adj->nlpids));
|
2017-07-13 19:04:25 +02:00
|
|
|
vty_out(vty, "\n");
|
2004-09-10 22:48:21 +02:00
|
|
|
if (adj->mt_count != 1
|
2017-05-06 15:50:45 +02:00
|
|
|
|| adj->mt_set[0] != ISIS_MT_IPV4_UNICAST) {
|
2017-07-13 17:49:13 +02:00
|
|
|
vty_out(vty, " Topologies:\n");
|
2017-05-06 15:50:45 +02:00
|
|
|
for (unsigned int i = 0; i < adj->mt_count; i++)
|
2017-07-13 17:49:13 +02:00
|
|
|
vty_out(vty, " %s\n",
|
|
|
|
isis_mtid2str(adj->mt_set[i]));
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2023-01-26 17:47:04 +01:00
|
|
|
vty_out(vty, " SNPA: %pSY", adj->snpa);
|
2012-11-27 02:10:30 +01:00
|
|
|
if (adj->circuit
|
|
|
|
&& (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) {
|
2021-06-11 17:27:46 +02:00
|
|
|
dyn = dynhn_find_by_id(adj->circuit->isis, adj->lanid);
|
2017-07-17 14:03:14 +02:00
|
|
|
if (dyn)
|
2017-07-05 18:37:36 +02:00
|
|
|
vty_out(vty, ", LAN id: %s.%02x", dyn->hostname,
|
2012-03-24 16:35:20 +01:00
|
|
|
adj->lanid[ISIS_SYS_ID_LEN]);
|
2017-07-17 14:03:14 +02:00
|
|
|
else
|
2023-01-26 17:47:04 +01:00
|
|
|
vty_out(vty, ", LAN id: %pPN", adj->lanid);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-07-13 19:04:25 +02:00
|
|
|
vty_out(vty, "\n");
|
2012-03-24 16:35:20 +01:00
|
|
|
vty_out(vty, " LAN Priority: %u",
|
|
|
|
adj->prio[adj->level - 1]);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
vty_out(vty, ", %s, DIS flaps: %u, Last: %s ago",
|
2012-03-24 16:35:20 +01:00
|
|
|
isis_disflag2string(
|
|
|
|
adj->dis_record[ISIS_LEVELS + level - 1]
|
2017-07-17 14:03:14 +02:00
|
|
|
.dis),
|
2012-03-24 16:35:20 +01:00
|
|
|
adj->dischanges[level - 1],
|
2017-07-22 14:52:33 +02:00
|
|
|
time2string(now - (adj->dis_record[ISIS_LEVELS
|
|
|
|
+ level - 1]
|
|
|
|
.last_dis_change)));
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2017-07-13 19:04:25 +02:00
|
|
|
vty_out(vty, "\n");
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-06-21 15:21:00 +02:00
|
|
|
if (adj->area_address_count) {
|
2017-07-13 17:49:13 +02:00
|
|
|
vty_out(vty, " Area Address(es):\n");
|
2017-06-21 15:21:00 +02:00
|
|
|
for (unsigned int i = 0; i < adj->area_address_count;
|
|
|
|
i++) {
|
2023-01-26 17:47:04 +01:00
|
|
|
vty_out(vty, " %pIS\n",
|
|
|
|
&adj->area_addresses[i]);
|
2017-06-21 15:21:00 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2017-06-21 15:21:00 +02:00
|
|
|
if (adj->ipv4_address_count) {
|
2017-07-13 17:49:13 +02:00
|
|
|
vty_out(vty, " IPv4 Address(es):\n");
|
2017-06-21 15:21:00 +02:00
|
|
|
for (unsigned int i = 0; i < adj->ipv4_address_count;
|
|
|
|
i++)
|
2020-10-22 20:30:34 +02:00
|
|
|
vty_out(vty, " %pI4\n",
|
|
|
|
&adj->ipv4_addresses[i]);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2021-06-30 17:23:56 +02:00
|
|
|
if (adj->ll_ipv6_count) {
|
2017-07-13 17:49:13 +02:00
|
|
|
vty_out(vty, " IPv6 Address(es):\n");
|
2021-06-30 17:23:56 +02:00
|
|
|
for (unsigned int i = 0; i < adj->ll_ipv6_count; i++) {
|
|
|
|
char buf[INET6_ADDRSTRLEN];
|
|
|
|
inet_ntop(AF_INET6, &adj->ll_ipv6_addrs[i],
|
|
|
|
buf, sizeof(buf));
|
|
|
|
vty_out(vty, " %s\n", buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (adj->global_ipv6_count) {
|
|
|
|
vty_out(vty, " Global IPv6 Address(es):\n");
|
|
|
|
for (unsigned int i = 0; i < adj->global_ipv6_count;
|
2017-06-21 15:21:00 +02:00
|
|
|
i++) {
|
|
|
|
char buf[INET6_ADDRSTRLEN];
|
2021-06-30 17:23:56 +02:00
|
|
|
inet_ntop(AF_INET6, &adj->global_ipv6_addrs[i],
|
2017-06-21 15:21:00 +02:00
|
|
|
buf, sizeof(buf));
|
|
|
|
vty_out(vty, " %s\n", buf);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2022-04-07 12:25:12 +02:00
|
|
|
if (adj->circuit && adj->circuit->bfd_config.enabled) {
|
|
|
|
vty_out(vty, " BFD is %s%s\n",
|
|
|
|
adj->bfd_session ? "active, status "
|
|
|
|
: "configured",
|
|
|
|
!adj->bfd_session
|
|
|
|
? ""
|
|
|
|
: bfd_get_status_str(bfd_sess_status(
|
|
|
|
adj->bfd_session)));
|
|
|
|
}
|
2019-08-04 03:02:37 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO(adj->adj_sids, anode, sra)) {
|
|
|
|
const char *adj_type;
|
|
|
|
const char *backup;
|
|
|
|
uint32_t sid;
|
|
|
|
|
|
|
|
switch (sra->adj->circuit->circ_type) {
|
|
|
|
case CIRCUIT_T_BROADCAST:
|
|
|
|
adj_type = "LAN Adjacency-SID";
|
|
|
|
sid = sra->u.ladj_sid->sid;
|
|
|
|
break;
|
|
|
|
case CIRCUIT_T_P2P:
|
|
|
|
adj_type = "Adjacency-SID";
|
|
|
|
sid = sra->u.adj_sid->sid;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
2024-04-03 15:58:05 +02:00
|
|
|
backup = (sra->type == ISIS_SR_ADJ_BACKUP) ? " (backup)"
|
2019-08-04 03:02:37 +02:00
|
|
|
: "";
|
|
|
|
|
|
|
|
vty_out(vty, " %s %s%s: %u\n",
|
|
|
|
(sra->nexthop.family == AF_INET) ? "IPv4"
|
|
|
|
: "IPv6",
|
|
|
|
adj_type, backup, sid);
|
|
|
|
}
|
2017-07-13 19:04:25 +02:00
|
|
|
vty_out(vty, "\n");
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void isis_adj_build_neigh_list(struct list *adjdb, struct list *list)
|
|
|
|
{
|
|
|
|
struct isis_adjacency *adj;
|
|
|
|
struct listnode *node;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if (!list) {
|
2022-08-29 08:53:46 +02:00
|
|
|
zlog_warn("%s: NULL list", __func__);
|
2004-09-10 22:48:21 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
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(adjdb, node, adj)) {
|
2004-09-10 22:48:21 +02:00
|
|
|
if (!adj) {
|
2022-08-29 08:53:46 +02:00
|
|
|
zlog_warn("%s: NULL adj", __func__);
|
2017-07-17 14:03:14 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if ((adj->adj_state == ISIS_ADJ_UP
|
|
|
|
|| adj->adj_state == ISIS_ADJ_INITIALIZING))
|
|
|
|
listnode_add(list, adj->snpa);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void isis_adj_build_up_list(struct list *adjdb, struct list *list)
|
|
|
|
{
|
|
|
|
struct isis_adjacency *adj;
|
|
|
|
struct listnode *node;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
isisd: Segmentation fault on isis daemon fixes
I have a fix for 2 segmentation fault scenarios on the isis daemon:
1. When running a command "isis passive" on an interface in the
following context:
"end"
"configure terminal "
"interface dummy0"
"isis passive"
The trace back collected:
isis_adjacency.c:521
family=2,
root_sysid=0x20aee6d0 "", parent=0x20af4d68) at isis_spf.c:999
sysid=0x20aee6d0 "")
at isis_spf.c:1217
isis_spf.c:1372
isis_lsp.c:416
isis_lsp.c:1660
isis_main.c:368
The fix location:
file name: isisd/isis_adjacency.c
routine name: isis_adj_build_up_list
2. When deleting the existing isis router instance:
"end"
"configure terminal "
"no router isis DEAD"
The fix location:
isisd/isis_events.c, routine circuit_resign_level
isisd/isis_lsp.c, routine lsp_destroy
isisd/isis_route.c, isis_route_validate
The trace back collection:
"DEAD") at isisd.c:252
argc=1, argv=0xbfc39054) at isisd.c:1520
vty=0x20d6f528, cmd=0x0) at command.c:2121
cmd=0x0, vtysh=0) at command.c:2155
isis DEAD") at vty.c:433
isis_main.c:368
and
"DEAD") at isisd.c:260
argc=1, argv=0xbfd6cf54) at isisd.c:1520
vty=0x208cb528, cmd=0x0) at command.c:2121
cmd=0x0, vtysh=0) at command.c:2155
isis DEAD") at vty.c:433
isis_main.c:368
The patch is included.
patchwork #833: http://patchwork.quagga.net/patch/833/
2013-04-26 20:38:34 +02:00
|
|
|
if (adjdb == NULL) {
|
2022-08-29 08:53:46 +02:00
|
|
|
zlog_warn("%s: adjacency DB is empty", __func__);
|
isisd: Segmentation fault on isis daemon fixes
I have a fix for 2 segmentation fault scenarios on the isis daemon:
1. When running a command "isis passive" on an interface in the
following context:
"end"
"configure terminal "
"interface dummy0"
"isis passive"
The trace back collected:
isis_adjacency.c:521
family=2,
root_sysid=0x20aee6d0 "", parent=0x20af4d68) at isis_spf.c:999
sysid=0x20aee6d0 "")
at isis_spf.c:1217
isis_spf.c:1372
isis_lsp.c:416
isis_lsp.c:1660
isis_main.c:368
The fix location:
file name: isisd/isis_adjacency.c
routine name: isis_adj_build_up_list
2. When deleting the existing isis router instance:
"end"
"configure terminal "
"no router isis DEAD"
The fix location:
isisd/isis_events.c, routine circuit_resign_level
isisd/isis_lsp.c, routine lsp_destroy
isisd/isis_route.c, isis_route_validate
The trace back collection:
"DEAD") at isisd.c:252
argc=1, argv=0xbfc39054) at isisd.c:1520
vty=0x20d6f528, cmd=0x0) at command.c:2121
cmd=0x0, vtysh=0) at command.c:2155
isis DEAD") at vty.c:433
isis_main.c:368
and
"DEAD") at isisd.c:260
argc=1, argv=0xbfd6cf54) at isisd.c:1520
vty=0x208cb528, cmd=0x0) at command.c:2121
cmd=0x0, vtysh=0) at command.c:2155
isis DEAD") at vty.c:433
isis_main.c:368
The patch is included.
patchwork #833: http://patchwork.quagga.net/patch/833/
2013-04-26 20:38:34 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if (!list) {
|
2022-08-29 08:53:46 +02:00
|
|
|
zlog_warn("%s: NULL list", __func__);
|
2004-09-10 22:48:21 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj)) {
|
|
|
|
if (!adj) {
|
2022-08-29 08:53:46 +02:00
|
|
|
zlog_warn("%s: NULL adj", __func__);
|
2017-07-17 14:03:14 +02:00
|
|
|
return;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (adj->adj_state == ISIS_ADJ_UP)
|
|
|
|
listnode_add(list, adj);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
2017-04-27 13:56:41 +02:00
|
|
|
|
|
|
|
int isis_adj_usage2levels(enum isis_adj_usage usage)
|
|
|
|
{
|
|
|
|
switch (usage) {
|
|
|
|
case ISIS_ADJ_LEVEL1:
|
|
|
|
return IS_LEVEL_1;
|
|
|
|
case ISIS_ADJ_LEVEL2:
|
|
|
|
return IS_LEVEL_2;
|
|
|
|
case ISIS_ADJ_LEVEL1AND2:
|
|
|
|
return IS_LEVEL_1 | IS_LEVEL_2;
|
2023-01-30 16:08:47 +01:00
|
|
|
case ISIS_ADJ_NONE:
|
|
|
|
return 0;
|
2017-04-27 13:56:41 +02:00
|
|
|
}
|
2023-01-30 16:08:47 +01:00
|
|
|
|
|
|
|
assert(!"Reached end of function where we are not expecting to");
|
2017-04-27 13:56:41 +02:00
|
|
|
}
|