2 * IS-IS Rout(e)ing protocol - isis_adjacency.c
3 * handling of IS-IS adjacencies
5 * Copyright (C) 2001,2002 Sampo Saaristo
6 * Tampere University of Technology
7 * Institute of Communications Engineering
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public Licenseas published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
14 * This program is distributed in the hope that it will be useful,but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * You should have received a copy of the GNU General Public License along
20 * with this program; see the file COPYING; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include "isisd/isis_constants.h"
37 #include "isisd/isis_common.h"
38 #include "isisd/isis_flags.h"
39 #include "isisd/isisd.h"
40 #include "isisd/isis_circuit.h"
41 #include "isisd/isis_adjacency.h"
42 #include "isisd/isis_misc.h"
43 #include "isisd/isis_dr.h"
44 #include "isisd/isis_dynhn.h"
45 #include "isisd/isis_pdu.h"
46 #include "isisd/isis_lsp.h"
47 #include "isisd/isis_events.h"
48 #include "isisd/isis_mt.h"
49 #include "isisd/isis_tlvs.h"
50 #include "isisd/fabricd.h"
51 #include "isisd/isis_nb.h"
53 DEFINE_MTYPE_STATIC(ISISD
, ISIS_ADJACENCY
, "ISIS adjacency");
54 DEFINE_MTYPE(ISISD
, ISIS_ADJACENCY_INFO
, "ISIS adjacency info");
56 static struct isis_adjacency
*adj_alloc(struct isis_circuit
*circuit
,
59 struct isis_adjacency
*adj
;
61 adj
= XCALLOC(MTYPE_ISIS_ADJACENCY
, sizeof(struct isis_adjacency
));
62 memcpy(adj
->sysid
, id
, ISIS_SYS_ID_LEN
);
64 adj
->snmp_idx
= ++circuit
->snmp_adj_idx_gen
;
66 if (circuit
->snmp_adj_list
== NULL
)
67 circuit
->snmp_adj_list
= list_new();
69 adj
->snmp_list_node
= listnode_add(circuit
->snmp_adj_list
, adj
);
74 struct isis_adjacency
*isis_new_adj(const uint8_t *id
, const uint8_t *snpa
,
75 int level
, struct isis_circuit
*circuit
)
77 struct isis_adjacency
*adj
;
80 adj
= adj_alloc(circuit
, id
); /* P2P kludge */
83 memcpy(adj
->snpa
, snpa
, ETH_ALEN
);
85 memset(adj
->snpa
, ' ', ETH_ALEN
);
88 adj
->circuit
= circuit
;
91 adj
->last_flap
= time(NULL
);
92 adj
->threeway_state
= ISIS_THREEWAY_DOWN
;
93 if (circuit
->circ_type
== CIRCUIT_T_BROADCAST
) {
94 listnode_add(circuit
->u
.bc
.adjdb
[level
- 1], adj
);
95 adj
->dischanges
[level
- 1] = 0;
96 for (i
= 0; i
< DIS_RECORDS
;
97 i
++) /* clear N DIS state change records */
99 adj
->dis_record
[(i
* ISIS_LEVELS
) + level
- 1].dis
=
101 adj
->dis_record
[(i
* ISIS_LEVELS
) + level
- 1]
102 .last_dis_change
= time(NULL
);
105 adj
->adj_sids
= list_new();
106 listnode_add(circuit
->area
->adjacency_list
, adj
);
111 struct isis_adjacency
*isis_adj_lookup(const uint8_t *sysid
, struct list
*adjdb
)
113 struct isis_adjacency
*adj
;
114 struct listnode
*node
;
116 for (ALL_LIST_ELEMENTS_RO(adjdb
, node
, adj
))
117 if (memcmp(adj
->sysid
, sysid
, ISIS_SYS_ID_LEN
) == 0)
123 struct isis_adjacency
*isis_adj_lookup_snpa(const uint8_t *ssnpa
,
126 struct listnode
*node
;
127 struct isis_adjacency
*adj
;
129 for (ALL_LIST_ELEMENTS_RO(adjdb
, node
, adj
))
130 if (memcmp(adj
->snpa
, ssnpa
, ETH_ALEN
) == 0)
136 struct isis_adjacency
*isis_adj_find(const struct isis_area
*area
, int level
,
137 const uint8_t *sysid
)
139 struct isis_adjacency
*adj
;
140 struct listnode
*node
;
142 for (ALL_LIST_ELEMENTS_RO(area
->adjacency_list
, node
, adj
)) {
143 if (!(adj
->level
& level
))
146 if (!memcmp(adj
->sysid
, sysid
, ISIS_SYS_ID_LEN
))
153 DEFINE_HOOK(isis_adj_state_change_hook
, (struct isis_adjacency
*adj
), (adj
));
155 void isis_delete_adj(void *arg
)
157 struct isis_adjacency
*adj
= arg
;
161 /* Remove self from snmp list without walking the list*/
162 list_delete_node(adj
->circuit
->snmp_adj_list
, adj
->snmp_list_node
);
164 thread_cancel(&adj
->t_expire
);
165 if (adj
->adj_state
!= ISIS_ADJ_DOWN
)
166 adj
->adj_state
= ISIS_ADJ_DOWN
;
168 hook_call(isis_adj_state_change_hook
, adj
);
170 XFREE(MTYPE_ISIS_ADJACENCY_INFO
, adj
->area_addresses
);
171 XFREE(MTYPE_ISIS_ADJACENCY_INFO
, adj
->ipv4_addresses
);
172 XFREE(MTYPE_ISIS_ADJACENCY_INFO
, adj
->ll_ipv6_addrs
);
175 list_delete(&adj
->adj_sids
);
177 listnode_delete(adj
->circuit
->area
->adjacency_list
, adj
);
178 XFREE(MTYPE_ISIS_ADJACENCY
, adj
);
182 static const char *adj_state2string(int state
)
186 case ISIS_ADJ_INITIALIZING
:
187 return "Initializing";
196 return NULL
; /* not reached */
199 static const char *adj_level2string(int level
)
206 case IS_LEVEL_1_AND_2
:
212 return NULL
; /* not reached */
215 void isis_adj_process_threeway(struct isis_adjacency
*adj
,
216 struct isis_threeway_adj
*tw_adj
,
217 enum isis_adj_usage adj_usage
)
219 enum isis_threeway_state next_tw_state
= ISIS_THREEWAY_DOWN
;
221 if (tw_adj
&& !adj
->circuit
->disable_threeway_adj
) {
222 if (tw_adj
->state
== ISIS_THREEWAY_DOWN
) {
223 next_tw_state
= ISIS_THREEWAY_INITIALIZING
;
224 } else if (tw_adj
->state
== ISIS_THREEWAY_INITIALIZING
) {
225 next_tw_state
= ISIS_THREEWAY_UP
;
226 } else if (tw_adj
->state
== ISIS_THREEWAY_UP
) {
227 if (adj
->threeway_state
== ISIS_THREEWAY_DOWN
)
228 next_tw_state
= ISIS_THREEWAY_DOWN
;
230 next_tw_state
= ISIS_THREEWAY_UP
;
233 next_tw_state
= ISIS_THREEWAY_UP
;
236 if (next_tw_state
!= adj
->threeway_state
) {
237 if (IS_DEBUG_ADJ_PACKETS
) {
238 zlog_info("ISIS-Adj (%s): Threeway state change %s to %s",
239 adj
->circuit
->area
->area_tag
,
240 isis_threeway_state_name(adj
->threeway_state
),
241 isis_threeway_state_name(next_tw_state
));
245 if (next_tw_state
!= ISIS_THREEWAY_DOWN
)
246 fabricd_initial_sync_hello(adj
->circuit
);
248 if (next_tw_state
== ISIS_THREEWAY_DOWN
) {
249 isis_adj_state_change(&adj
, ISIS_ADJ_DOWN
,
250 "Neighbor restarted");
254 if (next_tw_state
== ISIS_THREEWAY_UP
) {
255 if (adj
->adj_state
!= ISIS_ADJ_UP
) {
256 isis_adj_state_change(&adj
, ISIS_ADJ_UP
, NULL
);
257 adj
->adj_usage
= adj_usage
;
261 if (adj
->threeway_state
!= next_tw_state
) {
262 send_hello_sched(adj
->circuit
, 0, TRIGGERED_IIH_DELAY
);
265 adj
->threeway_state
= next_tw_state
;
267 const char *isis_adj_name(const struct isis_adjacency
*adj
)
272 struct isis_dynhn
*dyn
;
274 dyn
= dynhn_find_by_id(adj
->circuit
->isis
, adj
->sysid
);
276 return dyn
->hostname
;
278 return sysid_print(adj
->sysid
);
280 void isis_log_adj_change(struct isis_adjacency
*adj
,
281 enum isis_adj_state old_state
,
282 enum isis_adj_state new_state
, const char *reason
)
285 "%%ADJCHANGE: Adjacency to %s (%s) for %s changed from %s to %s, %s",
286 isis_adj_name(adj
), adj
->circuit
->interface
->name
,
287 adj_level2string(adj
->level
), adj_state2string(old_state
),
288 adj_state2string(new_state
), reason
? reason
: "unspecified");
290 void isis_adj_state_change(struct isis_adjacency
**padj
,
291 enum isis_adj_state new_state
, const char *reason
)
293 struct isis_adjacency
*adj
= *padj
;
294 enum isis_adj_state old_state
= adj
->adj_state
;
295 struct isis_circuit
*circuit
= adj
->circuit
;
298 if (new_state
== old_state
)
301 adj
->adj_state
= new_state
;
302 send_hello_sched(circuit
, adj
->level
, TRIGGERED_IIH_DELAY
);
304 if (IS_DEBUG_ADJ_PACKETS
) {
305 zlog_debug("ISIS-Adj (%s): Adjacency state change %d->%d: %s",
306 circuit
->area
->area_tag
, old_state
, new_state
,
307 reason
? reason
: "unspecified");
310 if (circuit
->area
->log_adj_changes
)
311 isis_log_adj_change(adj
, old_state
, new_state
, reason
);
314 /* send northbound notification */
315 isis_notif_adj_state_change(adj
, new_state
, reason
);
316 #endif /* ifndef FABRICD */
318 if (circuit
->circ_type
== CIRCUIT_T_BROADCAST
) {
319 for (int level
= IS_LEVEL_1
; level
<= IS_LEVEL_2
; level
++) {
320 if ((adj
->level
& level
) == 0)
322 if (new_state
== ISIS_ADJ_UP
) {
323 circuit
->adj_state_changes
++;
324 circuit
->upadjcount
[level
- 1]++;
325 /* update counter & timers for debugging
327 adj
->last_flap
= time(NULL
);
329 } else if (old_state
== ISIS_ADJ_UP
) {
330 circuit
->adj_state_changes
++;
332 circuit
->upadjcount
[level
- 1]--;
333 if (circuit
->upadjcount
[level
- 1] == 0)
334 isis_tx_queue_clean(circuit
->tx_queue
);
336 if (new_state
== ISIS_ADJ_DOWN
) {
338 circuit
->u
.bc
.adjdb
[level
- 1],
345 if (circuit
->u
.bc
.lan_neighs
[level
- 1]) {
346 list_delete_all_node(
347 circuit
->u
.bc
.lan_neighs
[level
- 1]);
348 isis_adj_build_neigh_list(
349 circuit
->u
.bc
.adjdb
[level
- 1],
350 circuit
->u
.bc
.lan_neighs
[level
- 1]);
353 /* On adjacency state change send new pseudo LSP if we
355 if (circuit
->u
.bc
.is_dr
[level
- 1])
356 lsp_regenerate_schedule_pseudo(circuit
, level
);
359 } else if (circuit
->circ_type
== CIRCUIT_T_P2P
) {
360 for (int level
= IS_LEVEL_1
; level
<= IS_LEVEL_2
; level
++) {
361 if ((adj
->level
& level
) == 0)
363 if (new_state
== ISIS_ADJ_UP
) {
364 circuit
->upadjcount
[level
- 1]++;
366 /* update counter & timers for debugging
368 adj
->last_flap
= time(NULL
);
371 if (level
== IS_LEVEL_1
) {
372 thread_add_timer(master
, send_l1_csnp
,
374 &circuit
->t_send_csnp
[0]);
376 thread_add_timer(master
, send_l2_csnp
,
378 &circuit
->t_send_csnp
[1]);
380 } else if (old_state
== ISIS_ADJ_UP
) {
381 circuit
->upadjcount
[level
- 1]--;
382 if (circuit
->upadjcount
[level
- 1] == 0)
383 isis_tx_queue_clean(circuit
->tx_queue
);
385 if (new_state
== ISIS_ADJ_DOWN
) {
386 if (adj
->circuit
->u
.p2p
.neighbor
== adj
)
387 adj
->circuit
->u
.p2p
.neighbor
=
396 hook_call(isis_adj_state_change_hook
, adj
);
399 isis_delete_adj(adj
);
405 void isis_adj_print(struct isis_adjacency
*adj
)
407 struct isis_dynhn
*dyn
;
411 dyn
= dynhn_find_by_id(adj
->circuit
->isis
, adj
->sysid
);
413 zlog_debug("%s", dyn
->hostname
);
415 zlog_debug("SystemId %20s SNPA %s, level %d; Holding Time %d",
416 sysid_print(adj
->sysid
), snpa_print(adj
->snpa
), adj
->level
,
418 if (adj
->ipv4_address_count
) {
419 zlog_debug("IPv4 Address(es):");
420 for (unsigned int i
= 0; i
< adj
->ipv4_address_count
; i
++)
421 zlog_debug("%pI4", &adj
->ipv4_addresses
[i
]);
424 if (adj
->ll_ipv6_count
) {
425 zlog_debug("IPv6 Address(es):");
426 for (unsigned int i
= 0; i
< adj
->ll_ipv6_count
; i
++) {
427 char buf
[INET6_ADDRSTRLEN
];
428 inet_ntop(AF_INET6
, &adj
->ll_ipv6_addrs
[i
], buf
,
430 zlog_debug("%s", buf
);
433 zlog_debug("Speaks: %s", nlpid2string(&adj
->nlpids
));
438 const char *isis_adj_yang_state(enum isis_adj_state state
)
445 case ISIS_ADJ_INITIALIZING
:
452 void isis_adj_expire(struct thread
*thread
)
454 struct isis_adjacency
*adj
;
459 adj
= THREAD_ARG(thread
);
461 adj
->t_expire
= NULL
;
463 /* trigger the adj expire event */
464 isis_adj_state_change(&adj
, ISIS_ADJ_DOWN
, "holding time expired");
468 * show isis neighbor [detail] json
470 void isis_adj_print_json(struct isis_adjacency
*adj
, struct json_object
*json
,
473 json_object
*iface_json
, *ipv4_addr_json
, *ipv6_link_json
,
474 *ipv6_non_link_json
, *topo_json
, *dis_flaps_json
,
475 *area_addr_json
, *adj_sid_json
;
477 struct isis_dynhn
*dyn
;
481 json_object_string_add(json
, "adj", isis_adj_name(adj
));
483 if (detail
== ISIS_UI_LEVEL_BRIEF
) {
485 json_object_string_add(json
, "interface",
486 adj
->circuit
->interface
->name
);
488 json_object_string_add(json
, "interface",
490 json_object_int_add(json
, "level", adj
->level
);
491 json_object_string_add(json
, "state",
492 adj_state2string(adj
->adj_state
));
495 if (adj
->last_upd
+ adj
->hold_time
< now
)
496 json_object_string_add(json
, "last-upd",
499 json_object_string_add(
501 time2string(adj
->last_upd
+
502 adj
->hold_time
- now
));
504 json_object_string_add(json
, "snpa", snpa_print(adj
->snpa
));
507 if (detail
== ISIS_UI_LEVEL_DETAIL
) {
508 struct sr_adjacency
*sra
;
509 struct listnode
*anode
;
512 iface_json
= json_object_new_object();
513 json_object_object_add(json
, "interface", iface_json
);
515 json_object_string_add(iface_json
, "name",
516 adj
->circuit
->interface
->name
);
518 json_object_string_add(iface_json
, "name",
520 json_object_int_add(json
, "level", adj
->level
);
521 json_object_string_add(iface_json
, "state",
522 adj_state2string(adj
->adj_state
));
525 if (adj
->last_upd
+ adj
->hold_time
< now
)
526 json_object_string_add(iface_json
, "last-upd",
529 json_object_string_add(
531 time2string(adj
->last_upd
+
532 adj
->hold_time
- now
));
534 json_object_string_add(json
, "expires-in",
535 time2string(adj
->hold_time
));
536 json_object_int_add(iface_json
, "adj-flaps", adj
->flaps
);
537 json_object_string_add(iface_json
, "last-ago",
538 time2string(now
- adj
->last_flap
));
539 json_object_string_add(iface_json
, "circuit-type",
540 circuit_t2string(adj
->circuit_t
));
541 json_object_string_add(iface_json
, "speaks",
542 nlpid2string(&adj
->nlpids
));
543 if (adj
->mt_count
!= 1 ||
544 adj
->mt_set
[0] != ISIS_MT_IPV4_UNICAST
) {
545 topo_json
= json_object_new_object();
546 json_object_object_add(iface_json
, "topologies",
548 for (unsigned int i
= 0; i
< adj
->mt_count
; i
++) {
549 snprintfrr(buf
, sizeof(buf
), "topo-%d", i
);
550 json_object_string_add(
552 isis_mtid2str(adj
->mt_set
[i
]));
555 json_object_string_add(iface_json
, "snpa",
556 snpa_print(adj
->snpa
));
558 (adj
->circuit
->circ_type
== CIRCUIT_T_BROADCAST
)) {
559 dyn
= dynhn_find_by_id(adj
->circuit
->isis
, adj
->lanid
);
561 snprintfrr(buf
, sizeof(buf
), "%s-%02x",
563 adj
->lanid
[ISIS_SYS_ID_LEN
]);
564 json_object_string_add(iface_json
, "lan-id",
567 snprintfrr(buf
, sizeof(buf
), "%s-%02x",
568 sysid_print(adj
->lanid
),
569 adj
->lanid
[ISIS_SYS_ID_LEN
]);
570 json_object_string_add(iface_json
, "lan-id",
574 json_object_int_add(iface_json
, "lan-prio",
575 adj
->prio
[adj
->level
- 1]);
577 dis_flaps_json
= json_object_new_object();
578 json_object_object_add(iface_json
, "dis-flaps",
580 json_object_string_add(
581 dis_flaps_json
, "dis-record",
583 adj
->dis_record
[ISIS_LEVELS
+ level
- 1]
585 json_object_int_add(dis_flaps_json
, "last",
586 adj
->dischanges
[level
- 1]);
587 json_object_string_add(
588 dis_flaps_json
, "ago",
589 time2string(now
- (adj
->dis_record
[ISIS_LEVELS
+
594 if (adj
->area_address_count
) {
595 area_addr_json
= json_object_new_object();
596 json_object_object_add(iface_json
, "area-address",
598 for (unsigned int i
= 0; i
< adj
->area_address_count
;
600 json_object_string_add(
601 area_addr_json
, "isonet",
602 isonet_print(adj
->area_addresses
[i
]
604 adj
->area_addresses
[i
]
608 if (adj
->ipv4_address_count
) {
609 ipv4_addr_json
= json_object_new_object();
610 json_object_object_add(iface_json
, "ipv4-address",
612 for (unsigned int i
= 0; i
< adj
->ipv4_address_count
;
614 inet_ntop(AF_INET
, &adj
->ipv4_addresses
[i
], buf
,
616 json_object_string_add(ipv4_addr_json
, "ipv4", buf
);
619 if (adj
->ll_ipv6_count
) {
620 ipv6_link_json
= json_object_new_object();
621 json_object_object_add(iface_json
, "ipv6-link-local",
623 for (unsigned int i
= 0; i
< adj
->ll_ipv6_count
; i
++) {
624 char buf
[INET6_ADDRSTRLEN
];
625 inet_ntop(AF_INET6
, &adj
->ll_ipv6_addrs
[i
], buf
,
627 json_object_string_add(ipv6_link_json
, "ipv6",
631 if (adj
->global_ipv6_count
) {
632 ipv6_non_link_json
= json_object_new_object();
633 json_object_object_add(iface_json
, "ipv6-global",
635 for (unsigned int i
= 0; i
< adj
->global_ipv6_count
;
637 char buf
[INET6_ADDRSTRLEN
];
638 inet_ntop(AF_INET6
, &adj
->global_ipv6_addrs
[i
],
640 json_object_string_add(ipv6_non_link_json
,
645 adj_sid_json
= json_object_new_object();
646 json_object_object_add(iface_json
, "adj-sid", adj_sid_json
);
647 for (ALL_LIST_ELEMENTS_RO(adj
->adj_sids
, anode
, sra
)) {
648 const char *adj_type
;
652 switch (sra
->adj
->circuit
->circ_type
) {
653 case CIRCUIT_T_BROADCAST
:
654 adj_type
= "LAN Adjacency-SID";
655 sid
= sra
->u
.ladj_sid
->sid
;
658 adj_type
= "Adjacency-SID";
659 sid
= sra
->u
.adj_sid
->sid
;
664 backup
= (sra
->type
== ISIS_SR_LAN_BACKUP
) ? " (backup)"
667 json_object_string_add(adj_sid_json
, "nexthop",
668 (sra
->nexthop
.family
== AF_INET
)
671 json_object_string_add(adj_sid_json
, "adj-type",
673 json_object_string_add(adj_sid_json
, "is-backup",
675 json_object_int_add(adj_sid_json
, "sid", sid
);
682 * show isis neighbor [detail]
684 void isis_adj_print_vty(struct isis_adjacency
*adj
, struct vty
*vty
,
688 struct isis_dynhn
*dyn
;
691 vty_out(vty
, " %-20s", isis_adj_name(adj
));
693 if (detail
== ISIS_UI_LEVEL_BRIEF
) {
695 vty_out(vty
, "%-12s", adj
->circuit
->interface
->name
);
697 vty_out(vty
, "NULL circuit!");
698 vty_out(vty
, "%-3u", adj
->level
); /* level */
699 vty_out(vty
, "%-13s", adj_state2string(adj
->adj_state
));
702 if (adj
->last_upd
+ adj
->hold_time
< now
)
703 vty_out(vty
, " Expiring");
705 vty_out(vty
, " %-9llu",
706 (unsigned long long)adj
->last_upd
707 + adj
->hold_time
- now
);
710 vty_out(vty
, "%-10s", snpa_print(adj
->snpa
));
714 if (detail
== ISIS_UI_LEVEL_DETAIL
) {
715 struct sr_adjacency
*sra
;
716 struct listnode
*anode
;
721 vty_out(vty
, " Interface: %s",
722 adj
->circuit
->interface
->name
);
724 vty_out(vty
, " Interface: NULL circuit");
725 vty_out(vty
, ", Level: %u", adj
->level
); /* level */
726 vty_out(vty
, ", State: %s", adj_state2string(adj
->adj_state
));
729 if (adj
->last_upd
+ adj
->hold_time
< now
)
730 vty_out(vty
, " Expiring");
732 vty_out(vty
, ", Expires in %s",
733 time2string(adj
->last_upd
734 + adj
->hold_time
- now
));
736 vty_out(vty
, ", Expires in %s",
737 time2string(adj
->hold_time
));
739 vty_out(vty
, " Adjacency flaps: %u", adj
->flaps
);
740 vty_out(vty
, ", Last: %s ago",
741 time2string(now
- adj
->last_flap
));
743 vty_out(vty
, " Circuit type: %s",
744 circuit_t2string(adj
->circuit_t
));
745 vty_out(vty
, ", Speaks: %s", nlpid2string(&adj
->nlpids
));
747 if (adj
->mt_count
!= 1
748 || adj
->mt_set
[0] != ISIS_MT_IPV4_UNICAST
) {
749 vty_out(vty
, " Topologies:\n");
750 for (unsigned int i
= 0; i
< adj
->mt_count
; i
++)
751 vty_out(vty
, " %s\n",
752 isis_mtid2str(adj
->mt_set
[i
]));
754 vty_out(vty
, " SNPA: %s", snpa_print(adj
->snpa
));
756 && (adj
->circuit
->circ_type
== CIRCUIT_T_BROADCAST
)) {
757 dyn
= dynhn_find_by_id(adj
->circuit
->isis
, adj
->lanid
);
759 vty_out(vty
, ", LAN id: %s.%02x", dyn
->hostname
,
760 adj
->lanid
[ISIS_SYS_ID_LEN
]);
762 vty_out(vty
, ", LAN id: %s.%02x",
763 sysid_print(adj
->lanid
),
764 adj
->lanid
[ISIS_SYS_ID_LEN
]);
767 vty_out(vty
, " LAN Priority: %u",
768 adj
->prio
[adj
->level
- 1]);
770 vty_out(vty
, ", %s, DIS flaps: %u, Last: %s ago",
772 adj
->dis_record
[ISIS_LEVELS
+ level
- 1]
774 adj
->dischanges
[level
- 1],
775 time2string(now
- (adj
->dis_record
[ISIS_LEVELS
781 if (adj
->area_address_count
) {
782 vty_out(vty
, " Area Address(es):\n");
783 for (unsigned int i
= 0; i
< adj
->area_address_count
;
785 vty_out(vty
, " %s\n",
786 isonet_print(adj
->area_addresses
[i
]
788 adj
->area_addresses
[i
]
792 if (adj
->ipv4_address_count
) {
793 vty_out(vty
, " IPv4 Address(es):\n");
794 for (unsigned int i
= 0; i
< adj
->ipv4_address_count
;
796 vty_out(vty
, " %pI4\n",
797 &adj
->ipv4_addresses
[i
]);
799 if (adj
->ll_ipv6_count
) {
800 vty_out(vty
, " IPv6 Address(es):\n");
801 for (unsigned int i
= 0; i
< adj
->ll_ipv6_count
; i
++) {
802 char buf
[INET6_ADDRSTRLEN
];
803 inet_ntop(AF_INET6
, &adj
->ll_ipv6_addrs
[i
],
805 vty_out(vty
, " %s\n", buf
);
808 if (adj
->global_ipv6_count
) {
809 vty_out(vty
, " Global IPv6 Address(es):\n");
810 for (unsigned int i
= 0; i
< adj
->global_ipv6_count
;
812 char buf
[INET6_ADDRSTRLEN
];
813 inet_ntop(AF_INET6
, &adj
->global_ipv6_addrs
[i
],
815 vty_out(vty
, " %s\n", buf
);
818 if (adj
->circuit
&& adj
->circuit
->bfd_config
.enabled
) {
819 vty_out(vty
, " BFD is %s%s\n",
820 adj
->bfd_session
? "active, status "
824 : bfd_get_status_str(bfd_sess_status(
827 for (ALL_LIST_ELEMENTS_RO(adj
->adj_sids
, anode
, sra
)) {
828 const char *adj_type
;
832 switch (sra
->adj
->circuit
->circ_type
) {
833 case CIRCUIT_T_BROADCAST
:
834 adj_type
= "LAN Adjacency-SID";
835 sid
= sra
->u
.ladj_sid
->sid
;
838 adj_type
= "Adjacency-SID";
839 sid
= sra
->u
.adj_sid
->sid
;
844 backup
= (sra
->type
== ISIS_SR_LAN_BACKUP
) ? " (backup)"
847 vty_out(vty
, " %s %s%s: %u\n",
848 (sra
->nexthop
.family
== AF_INET
) ? "IPv4"
850 adj_type
, backup
, sid
);
857 void isis_adj_build_neigh_list(struct list
*adjdb
, struct list
*list
)
859 struct isis_adjacency
*adj
;
860 struct listnode
*node
;
863 zlog_warn("isis_adj_build_neigh_list(): NULL list");
867 for (ALL_LIST_ELEMENTS_RO(adjdb
, node
, adj
)) {
869 zlog_warn("isis_adj_build_neigh_list(): NULL adj");
873 if ((adj
->adj_state
== ISIS_ADJ_UP
874 || adj
->adj_state
== ISIS_ADJ_INITIALIZING
))
875 listnode_add(list
, adj
->snpa
);
880 void isis_adj_build_up_list(struct list
*adjdb
, struct list
*list
)
882 struct isis_adjacency
*adj
;
883 struct listnode
*node
;
886 zlog_warn("isis_adj_build_up_list(): adjacency DB is empty");
891 zlog_warn("isis_adj_build_up_list(): NULL list");
895 for (ALL_LIST_ELEMENTS_RO(adjdb
, node
, adj
)) {
897 zlog_warn("isis_adj_build_up_list(): NULL adj");
901 if (adj
->adj_state
== ISIS_ADJ_UP
)
902 listnode_add(list
, adj
);
908 int isis_adj_usage2levels(enum isis_adj_usage usage
)
911 case ISIS_ADJ_LEVEL1
:
913 case ISIS_ADJ_LEVEL2
:
915 case ISIS_ADJ_LEVEL1AND2
:
916 return IS_LEVEL_1
| IS_LEVEL_2
;