]> git.proxmox.com Git - mirror_frr.git/blame - isisd/isis_adjacency.c
*: require semicolon after DEFINE_MTYPE & co
[mirror_frr.git] / isisd / isis_adjacency.c
CommitLineData
eb5d44eb 1/*
d62a17ae 2 * IS-IS Rout(e)ing protocol - isis_adjacency.c
eb5d44eb 3 * handling of IS-IS adjacencies
4 *
5 * Copyright (C) 2001,2002 Sampo Saaristo
d62a17ae 6 * Tampere University of Technology
eb5d44eb 7 * Institute of Communications Engineering
8 *
d62a17ae 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)
eb5d44eb 12 * any later version.
13 *
d62a17ae 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
eb5d44eb 17 * more details.
896014f4
DL
18 *
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
eb5d44eb 22 */
23
eb5d44eb 24#include <zebra.h>
eb5d44eb 25
26#include "log.h"
27#include "memory.h"
28#include "hash.h"
29#include "vty.h"
30#include "linklist.h"
31#include "thread.h"
32#include "if.h"
33#include "stream.h"
34
eb5d44eb 35#include "isisd/isis_constants.h"
36#include "isisd/isis_common.h"
3f045a08 37#include "isisd/isis_flags.h"
eb5d44eb 38#include "isisd/isisd.h"
39#include "isisd/isis_circuit.h"
40#include "isisd/isis_adjacency.h"
41#include "isisd/isis_misc.h"
42#include "isisd/isis_dr.h"
43#include "isisd/isis_dynhn.h"
44#include "isisd/isis_pdu.h"
3f045a08 45#include "isisd/isis_lsp.h"
3f045a08 46#include "isisd/isis_events.h"
206f4aae 47#include "isisd/isis_mt.h"
42fe2621 48#include "isisd/isis_tlvs.h"
8e6fb83b 49#include "isisd/fabricd.h"
2a1c520e 50#include "isisd/isis_nb.h"
eb5d44eb 51
1ee746d9 52static struct isis_adjacency *adj_alloc(struct isis_circuit *circuit,
53 const uint8_t *id)
eb5d44eb 54{
d62a17ae 55 struct isis_adjacency *adj;
eb5d44eb 56
d62a17ae 57 adj = XCALLOC(MTYPE_ISIS_ADJACENCY, sizeof(struct isis_adjacency));
58 memcpy(adj->sysid, id, ISIS_SYS_ID_LEN);
f390d2c7 59
1ee746d9 60 adj->snmp_idx = ++circuit->snmp_adj_idx_gen;
61
62 if (circuit->snmp_adj_list == NULL)
63 circuit->snmp_adj_list = list_new();
64
65 adj->snmp_list_node = listnode_add(circuit->snmp_adj_list, adj);
66
d62a17ae 67 return adj;
eb5d44eb 68}
69
d7c0a89a 70struct isis_adjacency *isis_new_adj(const uint8_t *id, const uint8_t *snpa,
d62a17ae 71 int level, struct isis_circuit *circuit)
eb5d44eb 72{
d62a17ae 73 struct isis_adjacency *adj;
74 int i;
75
1ee746d9 76 adj = adj_alloc(circuit, id); /* P2P kludge */
d62a17ae 77
d62a17ae 78 if (snpa) {
79 memcpy(adj->snpa, snpa, ETH_ALEN);
80 } else {
81 memset(adj->snpa, ' ', ETH_ALEN);
eb5d44eb 82 }
eb5d44eb 83
d62a17ae 84 adj->circuit = circuit;
85 adj->level = level;
86 adj->flaps = 0;
87 adj->last_flap = time(NULL);
42fe2621 88 adj->threeway_state = ISIS_THREEWAY_DOWN;
d62a17ae 89 if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
90 listnode_add(circuit->u.bc.adjdb[level - 1], adj);
91 adj->dischanges[level - 1] = 0;
92 for (i = 0; i < DIS_RECORDS;
93 i++) /* clear N DIS state change records */
94 {
95 adj->dis_record[(i * ISIS_LEVELS) + level - 1].dis =
96 ISIS_UNKNOWN_DIS;
97 adj->dis_record[(i * ISIS_LEVELS) + level - 1]
98 .last_dis_change = time(NULL);
99 }
100 }
26f6acaf 101 adj->adj_sids = list_new();
75eddbc3 102 listnode_add(circuit->area->adjacency_list, adj);
d62a17ae 103
104 return adj;
eb5d44eb 105}
106
d7c0a89a 107struct isis_adjacency *isis_adj_lookup(const uint8_t *sysid, struct list *adjdb)
eb5d44eb 108{
d62a17ae 109 struct isis_adjacency *adj;
110 struct listnode *node;
eb5d44eb 111
d62a17ae 112 for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj))
113 if (memcmp(adj->sysid, sysid, ISIS_SYS_ID_LEN) == 0)
114 return adj;
f390d2c7 115
d62a17ae 116 return NULL;
eb5d44eb 117}
118
d7c0a89a 119struct isis_adjacency *isis_adj_lookup_snpa(const uint8_t *ssnpa,
d62a17ae 120 struct list *adjdb)
eb5d44eb 121{
d62a17ae 122 struct listnode *node;
123 struct isis_adjacency *adj;
eb5d44eb 124
d62a17ae 125 for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj))
126 if (memcmp(adj->snpa, ssnpa, ETH_ALEN) == 0)
127 return adj;
f390d2c7 128
d62a17ae 129 return NULL;
eb5d44eb 130}
131
75eddbc3
RW
132struct isis_adjacency *isis_adj_find(const struct isis_area *area, int level,
133 const uint8_t *sysid)
26f6acaf 134{
75eddbc3 135 struct isis_adjacency *adj;
26f6acaf
RW
136 struct listnode *node;
137
75eddbc3
RW
138 for (ALL_LIST_ELEMENTS_RO(area->adjacency_list, node, adj)) {
139 if (!(adj->level & level))
140 continue;
141
142 if (!memcmp(adj->sysid, sysid, ISIS_SYS_ID_LEN))
143 return adj;
26f6acaf
RW
144 }
145
75eddbc3 146 return NULL;
26f6acaf
RW
147}
148
a5b5e946
CF
149DEFINE_HOOK(isis_adj_state_change_hook, (struct isis_adjacency *adj), (adj))
150
d62a17ae 151void isis_delete_adj(void *arg)
eb5d44eb 152{
d62a17ae 153 struct isis_adjacency *adj = arg;
3f045a08 154
d62a17ae 155 if (!adj)
156 return;
1ee746d9 157 /* Remove self from snmp list without walking the list*/
158 list_delete_node(adj->circuit->snmp_adj_list, adj->snmp_list_node);
f390d2c7 159
50478845 160 thread_cancel(&adj->t_expire);
690497fb 161 if (adj->adj_state != ISIS_ADJ_DOWN)
a5b5e946 162 adj->adj_state = ISIS_ADJ_DOWN;
3f045a08 163
690497fb
G
164 hook_call(isis_adj_state_change_hook, adj);
165
0a22ddfb
QY
166 XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->area_addresses);
167 XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv4_addresses);
168 XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv6_addresses);
3f045a08 169
d62a17ae 170 adj_mt_finish(adj);
26f6acaf 171 list_delete(&adj->adj_sids);
d8fba7d9 172
75eddbc3 173 listnode_delete(adj->circuit->area->adjacency_list, adj);
d62a17ae 174 XFREE(MTYPE_ISIS_ADJACENCY, adj);
175 return;
eb5d44eb 176}
177
d62a17ae 178static const char *adj_state2string(int state)
3f045a08
JB
179{
180
d62a17ae 181 switch (state) {
182 case ISIS_ADJ_INITIALIZING:
183 return "Initializing";
184 case ISIS_ADJ_UP:
185 return "Up";
186 case ISIS_ADJ_DOWN:
187 return "Down";
188 default:
189 return "Unknown";
190 }
191
192 return NULL; /* not reached */
3f045a08
JB
193}
194
7145d5bb
EDP
195static const char *adj_level2string(int level)
196{
197 switch (level) {
198 case IS_LEVEL_1:
199 return "level-1";
200 case IS_LEVEL_2:
201 return "level-2";
202 case IS_LEVEL_1_AND_2:
203 return "level-1-2";
204 default:
205 return "unknown";
206 }
207
208 return NULL; /* not reached */
209}
210
42fe2621
CF
211void isis_adj_process_threeway(struct isis_adjacency *adj,
212 struct isis_threeway_adj *tw_adj,
213 enum isis_adj_usage adj_usage)
214{
215 enum isis_threeway_state next_tw_state = ISIS_THREEWAY_DOWN;
216
58e5d748 217 if (tw_adj && !adj->circuit->disable_threeway_adj) {
42fe2621
CF
218 if (tw_adj->state == ISIS_THREEWAY_DOWN) {
219 next_tw_state = ISIS_THREEWAY_INITIALIZING;
220 } else if (tw_adj->state == ISIS_THREEWAY_INITIALIZING) {
221 next_tw_state = ISIS_THREEWAY_UP;
222 } else if (tw_adj->state == ISIS_THREEWAY_UP) {
223 if (adj->threeway_state == ISIS_THREEWAY_DOWN)
224 next_tw_state = ISIS_THREEWAY_DOWN;
225 else
226 next_tw_state = ISIS_THREEWAY_UP;
227 }
228 } else {
229 next_tw_state = ISIS_THREEWAY_UP;
230 }
231
232 if (next_tw_state != adj->threeway_state) {
e740f9c1 233 if (IS_DEBUG_ADJ_PACKETS) {
42fe2621
CF
234 zlog_info("ISIS-Adj (%s): Threeway state change %s to %s",
235 adj->circuit->area->area_tag,
236 isis_threeway_state_name(adj->threeway_state),
237 isis_threeway_state_name(next_tw_state));
238 }
239 }
240
8e6fb83b
CF
241 if (next_tw_state != ISIS_THREEWAY_DOWN)
242 fabricd_initial_sync_hello(adj->circuit);
243
42fe2621 244 if (next_tw_state == ISIS_THREEWAY_DOWN) {
16167b31
DS
245 isis_adj_state_change(&adj, ISIS_ADJ_DOWN,
246 "Neighbor restarted");
42fe2621
CF
247 return;
248 }
249
250 if (next_tw_state == ISIS_THREEWAY_UP) {
251 if (adj->adj_state != ISIS_ADJ_UP) {
16167b31 252 isis_adj_state_change(&adj, ISIS_ADJ_UP, NULL);
42fe2621
CF
253 adj->adj_usage = adj_usage;
254 }
255 }
256
5346acec
CF
257 if (adj->threeway_state != next_tw_state) {
258 send_hello_sched(adj->circuit, 0, TRIGGERED_IIH_DELAY);
259 }
260
42fe2621
CF
261 adj->threeway_state = next_tw_state;
262}
7145d5bb
EDP
263void isis_log_adj_change(struct isis_adjacency *adj,
264 enum isis_adj_state old_state,
265 enum isis_adj_state new_state, const char *reason)
266{
267 const char *adj_name;
268 struct isis_dynhn *dyn;
269
270 dyn = dynhn_find_by_id(adj->sysid);
271 if (dyn)
272 adj_name = dyn->hostname;
273 else
274 adj_name = sysid_print(adj->sysid);
275
276 zlog_info(
277 "%%ADJCHANGE: Adjacency to %s (%s) for %s changed from %s to %s, %s",
278 adj_name, adj->circuit->interface->name,
279 adj_level2string(adj->level), adj_state2string(old_state),
280 adj_state2string(new_state), reason ? reason : "unspecified");
281}
16167b31 282void isis_adj_state_change(struct isis_adjacency **padj,
d62a17ae 283 enum isis_adj_state new_state, const char *reason)
eb5d44eb 284{
16167b31 285 struct isis_adjacency *adj = *padj;
5346acec
CF
286 enum isis_adj_state old_state = adj->adj_state;
287 struct isis_circuit *circuit = adj->circuit;
16167b31 288 bool del = false;
d62a17ae 289
8cea0065
EDP
290 if (new_state == old_state)
291 return;
292
d62a17ae 293 adj->adj_state = new_state;
8cea0065 294 send_hello_sched(circuit, adj->level, TRIGGERED_IIH_DELAY);
d62a17ae 295
e740f9c1 296 if (IS_DEBUG_ADJ_PACKETS) {
d62a17ae 297 zlog_debug("ISIS-Adj (%s): Adjacency state change %d->%d: %s",
298 circuit->area->area_tag, old_state, new_state,
299 reason ? reason : "unspecified");
300 }
301
7145d5bb
EDP
302 if (circuit->area->log_adj_changes)
303 isis_log_adj_change(adj, old_state, new_state, reason);
d62a17ae 304
de983bb8
EDP
305#ifndef FABRICD
306 /* send northbound notification */
307 isis_notif_adj_state_change(adj, new_state, reason);
308#endif /* ifndef FABRICD */
309
d62a17ae 310 if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
5346acec 311 for (int level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) {
d62a17ae 312 if ((adj->level & level) == 0)
313 continue;
314 if (new_state == ISIS_ADJ_UP) {
1ee746d9 315 circuit->adj_state_changes++;
d62a17ae 316 circuit->upadjcount[level - 1]++;
d62a17ae 317 /* update counter & timers for debugging
318 * purposes */
319 adj->last_flap = time(NULL);
320 adj->flaps++;
8cea0065 321 } else if (old_state == ISIS_ADJ_UP) {
1ee746d9 322 circuit->adj_state_changes++;
d62a17ae 323 listnode_delete(circuit->u.bc.adjdb[level - 1],
324 adj);
58e16237 325
d62a17ae 326 circuit->upadjcount[level - 1]--;
58e16237 327 if (circuit->upadjcount[level - 1] == 0)
9b39405f 328 isis_tx_queue_clean(circuit->tx_queue);
58e16237 329
8cea0065
EDP
330 if (new_state == ISIS_ADJ_DOWN)
331 del = true;
d62a17ae 332 }
333
334 if (circuit->u.bc.lan_neighs[level - 1]) {
335 list_delete_all_node(
336 circuit->u.bc.lan_neighs[level - 1]);
337 isis_adj_build_neigh_list(
338 circuit->u.bc.adjdb[level - 1],
339 circuit->u.bc.lan_neighs[level - 1]);
340 }
341
342 /* On adjacency state change send new pseudo LSP if we
343 * are the DR */
344 if (circuit->u.bc.is_dr[level - 1])
345 lsp_regenerate_schedule_pseudo(circuit, level);
346 }
347
d62a17ae 348 } else if (circuit->circ_type == CIRCUIT_T_P2P) {
5346acec 349 for (int level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) {
d62a17ae 350 if ((adj->level & level) == 0)
351 continue;
352 if (new_state == ISIS_ADJ_UP) {
353 circuit->upadjcount[level - 1]++;
d62a17ae 354
d62a17ae 355 /* update counter & timers for debugging
356 * purposes */
357 adj->last_flap = time(NULL);
358 adj->flaps++;
359
8e6fb83b
CF
360 if (level == IS_LEVEL_1) {
361 thread_add_timer(master, send_l1_csnp,
362 circuit, 0,
363 &circuit->t_send_csnp[0]);
364 } else {
365 thread_add_timer(master, send_l2_csnp,
366 circuit, 0,
367 &circuit->t_send_csnp[1]);
368 }
8cea0065 369 } else if (old_state == ISIS_ADJ_UP) {
d62a17ae 370 if (adj->circuit->u.p2p.neighbor == adj)
371 adj->circuit->u.p2p.neighbor = NULL;
372 circuit->upadjcount[level - 1]--;
58e16237 373 if (circuit->upadjcount[level - 1] == 0)
9b39405f 374 isis_tx_queue_clean(circuit->tx_queue);
58e16237 375
8cea0065
EDP
376 if (new_state == ISIS_ADJ_DOWN)
377 del = true;
d62a17ae 378 }
379 }
16167b31 380 }
d62a17ae 381
e4229afd
EDP
382 hook_call(isis_adj_state_change_hook, adj);
383
16167b31
DS
384 if (del) {
385 isis_delete_adj(adj);
386 *padj = NULL;
d62a17ae 387 }
eb5d44eb 388}
389
390
d62a17ae 391void isis_adj_print(struct isis_adjacency *adj)
eb5d44eb 392{
d62a17ae 393 struct isis_dynhn *dyn;
d62a17ae 394
395 if (!adj)
396 return;
397 dyn = dynhn_find_by_id(adj->sysid);
398 if (dyn)
af8ac8f9 399 zlog_debug("%s", dyn->hostname);
d62a17ae 400
63efca0e 401 zlog_debug("SystemId %20s SNPA %s, level %d; Holding Time %d",
d62a17ae 402 sysid_print(adj->sysid), snpa_print(adj->snpa), adj->level,
403 adj->hold_time);
0c1bd758 404 if (adj->ipv4_address_count) {
d62a17ae 405 zlog_debug("IPv4 Address(es):");
0c1bd758 406 for (unsigned int i = 0; i < adj->ipv4_address_count; i++)
a854ea43 407 zlog_debug("%pI4", &adj->ipv4_addresses[i]);
d62a17ae 408 }
409
0c1bd758 410 if (adj->ipv6_address_count) {
d62a17ae 411 zlog_debug("IPv6 Address(es):");
0c1bd758
CF
412 for (unsigned int i = 0; i < adj->ipv6_address_count; i++) {
413 char buf[INET6_ADDRSTRLEN];
414 inet_ntop(AF_INET6, &adj->ipv6_addresses[i], buf,
415 sizeof(buf));
416 zlog_debug("%s", buf);
d62a17ae 417 }
f390d2c7 418 }
d62a17ae 419 zlog_debug("Speaks: %s", nlpid2string(&adj->nlpids));
eb5d44eb 420
d62a17ae 421 return;
eb5d44eb 422}
423
2a1c520e
RW
424const char *isis_adj_yang_state(enum isis_adj_state state)
425{
426 switch (state) {
427 case ISIS_ADJ_DOWN:
428 return "down";
429 case ISIS_ADJ_UP:
430 return "up";
431 case ISIS_ADJ_INITIALIZING:
432 return "init";
433 default:
434 return "failed";
435 }
436}
437
d62a17ae 438int isis_adj_expire(struct thread *thread)
eb5d44eb 439{
d62a17ae 440 struct isis_adjacency *adj;
eb5d44eb 441
d62a17ae 442 /*
443 * Get the adjacency
444 */
445 adj = THREAD_ARG(thread);
446 assert(adj);
447 adj->t_expire = NULL;
eb5d44eb 448
d62a17ae 449 /* trigger the adj expire event */
16167b31 450 isis_adj_state_change(&adj, ISIS_ADJ_DOWN, "holding time expired");
eb5d44eb 451
d62a17ae 452 return 0;
eb5d44eb 453}
454
eb5d44eb 455/*
3f045a08 456 * show isis neighbor [detail]
eb5d44eb 457 */
d62a17ae 458void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
459 char detail)
eb5d44eb 460{
d62a17ae 461 time_t now;
462 struct isis_dynhn *dyn;
463 int level;
d62a17ae 464
465 dyn = dynhn_find_by_id(adj->sysid);
466 if (dyn)
af8ac8f9 467 vty_out(vty, " %-20s", dyn->hostname);
d62a17ae 468 else
469 vty_out(vty, " %-20s", sysid_print(adj->sysid));
470
471 if (detail == ISIS_UI_LEVEL_BRIEF) {
472 if (adj->circuit)
473 vty_out(vty, "%-12s", adj->circuit->interface->name);
474 else
475 vty_out(vty, "NULL circuit!");
476 vty_out(vty, "%-3u", adj->level); /* level */
477 vty_out(vty, "%-13s", adj_state2string(adj->adj_state));
478 now = time(NULL);
3cbe31c7
EDP
479 if (adj->last_upd) {
480 if (adj->last_upd + adj->hold_time
481 < (unsigned long long)now)
482 vty_out(vty, " Expiring");
483 else
484 vty_out(vty, " %-9llu",
485 (unsigned long long)adj->last_upd
486 + adj->hold_time - now);
487 } else
d62a17ae 488 vty_out(vty, "- ");
489 vty_out(vty, "%-10s", snpa_print(adj->snpa));
490 vty_out(vty, "\n");
f390d2c7 491 }
d62a17ae 492
493 if (detail == ISIS_UI_LEVEL_DETAIL) {
26f6acaf
RW
494 struct sr_adjacency *sra;
495 struct listnode *anode;
496
d62a17ae 497 level = adj->level;
498 vty_out(vty, "\n");
499 if (adj->circuit)
500 vty_out(vty, " Interface: %s",
501 adj->circuit->interface->name);
502 else
503 vty_out(vty, " Interface: NULL circuit");
504 vty_out(vty, ", Level: %u", adj->level); /* level */
505 vty_out(vty, ", State: %s", adj_state2string(adj->adj_state));
506 now = time(NULL);
3cbe31c7
EDP
507 if (adj->last_upd) {
508 if (adj->last_upd + adj->hold_time
509 < (unsigned long long)now)
510 vty_out(vty, " Expiring");
511 else
512 vty_out(vty, ", Expires in %s",
513 time2string(adj->last_upd
514 + adj->hold_time - now));
515 } else
d62a17ae 516 vty_out(vty, ", Expires in %s",
517 time2string(adj->hold_time));
518 vty_out(vty, "\n");
519 vty_out(vty, " Adjacency flaps: %u", adj->flaps);
520 vty_out(vty, ", Last: %s ago",
521 time2string(now - adj->last_flap));
522 vty_out(vty, "\n");
523 vty_out(vty, " Circuit type: %s",
524 circuit_t2string(adj->circuit_t));
525 vty_out(vty, ", Speaks: %s", nlpid2string(&adj->nlpids));
526 vty_out(vty, "\n");
527 if (adj->mt_count != 1
528 || adj->mt_set[0] != ISIS_MT_IPV4_UNICAST) {
529 vty_out(vty, " Topologies:\n");
530 for (unsigned int i = 0; i < adj->mt_count; i++)
531 vty_out(vty, " %s\n",
532 isis_mtid2str(adj->mt_set[i]));
533 }
534 vty_out(vty, " SNPA: %s", snpa_print(adj->snpa));
535 if (adj->circuit
536 && (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) {
537 dyn = dynhn_find_by_id(adj->lanid);
538 if (dyn)
af8ac8f9 539 vty_out(vty, ", LAN id: %s.%02x", dyn->hostname,
d62a17ae 540 adj->lanid[ISIS_SYS_ID_LEN]);
541 else
542 vty_out(vty, ", LAN id: %s.%02x",
543 sysid_print(adj->lanid),
544 adj->lanid[ISIS_SYS_ID_LEN]);
545
546 vty_out(vty, "\n");
547 vty_out(vty, " LAN Priority: %u",
548 adj->prio[adj->level - 1]);
549
550 vty_out(vty, ", %s, DIS flaps: %u, Last: %s ago",
551 isis_disflag2string(
552 adj->dis_record[ISIS_LEVELS + level - 1]
553 .dis),
554 adj->dischanges[level - 1],
9d303b37
DL
555 time2string(now - (adj->dis_record[ISIS_LEVELS
556 + level - 1]
557 .last_dis_change)));
d62a17ae 558 }
559 vty_out(vty, "\n");
560
0c1bd758 561 if (adj->area_address_count) {
d62a17ae 562 vty_out(vty, " Area Address(es):\n");
0c1bd758
CF
563 for (unsigned int i = 0; i < adj->area_address_count;
564 i++) {
d62a17ae 565 vty_out(vty, " %s\n",
996c9314
LB
566 isonet_print(adj->area_addresses[i]
567 .area_addr,
568 adj->area_addresses[i]
569 .addr_len));
0c1bd758 570 }
d62a17ae 571 }
0c1bd758 572 if (adj->ipv4_address_count) {
d62a17ae 573 vty_out(vty, " IPv4 Address(es):\n");
0c1bd758
CF
574 for (unsigned int i = 0; i < adj->ipv4_address_count;
575 i++)
a854ea43
MS
576 vty_out(vty, " %pI4\n",
577 &adj->ipv4_addresses[i]);
d62a17ae 578 }
0c1bd758 579 if (adj->ipv6_address_count) {
d62a17ae 580 vty_out(vty, " IPv6 Address(es):\n");
0c1bd758
CF
581 for (unsigned int i = 0; i < adj->ipv6_address_count;
582 i++) {
583 char buf[INET6_ADDRSTRLEN];
584 inet_ntop(AF_INET6, &adj->ipv6_addresses[i],
585 buf, sizeof(buf));
586 vty_out(vty, " %s\n", buf);
d62a17ae 587 }
588 }
26f6acaf
RW
589 for (ALL_LIST_ELEMENTS_RO(adj->adj_sids, anode, sra)) {
590 const char *adj_type;
591 const char *backup;
592 uint32_t sid;
593
594 switch (sra->adj->circuit->circ_type) {
595 case CIRCUIT_T_BROADCAST:
596 adj_type = "LAN Adjacency-SID";
597 sid = sra->u.ladj_sid->sid;
598 break;
599 case CIRCUIT_T_P2P:
600 adj_type = "Adjacency-SID";
601 sid = sra->u.adj_sid->sid;
602 break;
603 default:
604 continue;
605 }
606 backup = (sra->type == ISIS_SR_LAN_BACKUP) ? " (backup)"
607 : "";
608
609 vty_out(vty, " %s %s%s: %u\n",
610 (sra->nexthop.family == AF_INET) ? "IPv4"
611 : "IPv6",
612 adj_type, backup, sid);
613 }
d62a17ae 614 vty_out(vty, "\n");
f390d2c7 615 }
d62a17ae 616 return;
eb5d44eb 617}
618
d62a17ae 619void isis_adj_build_neigh_list(struct list *adjdb, struct list *list)
eb5d44eb 620{
d62a17ae 621 struct isis_adjacency *adj;
622 struct listnode *node;
623
624 if (!list) {
625 zlog_warn("isis_adj_build_neigh_list(): NULL list");
626 return;
f390d2c7 627 }
628
d62a17ae 629 for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj)) {
630 if (!adj) {
631 zlog_warn("isis_adj_build_neigh_list(): NULL adj");
632 return;
633 }
634
635 if ((adj->adj_state == ISIS_ADJ_UP
636 || adj->adj_state == ISIS_ADJ_INITIALIZING))
637 listnode_add(list, adj->snpa);
638 }
639 return;
eb5d44eb 640}
641
d62a17ae 642void isis_adj_build_up_list(struct list *adjdb, struct list *list)
eb5d44eb 643{
d62a17ae 644 struct isis_adjacency *adj;
645 struct listnode *node;
646
647 if (adjdb == NULL) {
648 zlog_warn("isis_adj_build_up_list(): adjacency DB is empty");
649 return;
650 }
651
652 if (!list) {
653 zlog_warn("isis_adj_build_up_list(): NULL list");
654 return;
f390d2c7 655 }
656
d62a17ae 657 for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj)) {
658 if (!adj) {
659 zlog_warn("isis_adj_build_up_list(): NULL adj");
660 return;
661 }
f390d2c7 662
d62a17ae 663 if (adj->adj_state == ISIS_ADJ_UP)
664 listnode_add(list, adj);
665 }
666
667 return;
eb5d44eb 668}
d8fba7d9 669
d62a17ae 670int isis_adj_usage2levels(enum isis_adj_usage usage)
d8fba7d9 671{
d62a17ae 672 switch (usage) {
673 case ISIS_ADJ_LEVEL1:
674 return IS_LEVEL_1;
675 case ISIS_ADJ_LEVEL2:
676 return IS_LEVEL_2;
677 case ISIS_ADJ_LEVEL1AND2:
678 return IS_LEVEL_1 | IS_LEVEL_2;
679 default:
680 break;
681 }
682 return 0;
d8fba7d9 683}