]> git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_nb_state.c
doc: Add `show ipv6 rpf X:X::X:X` command to docs
[mirror_frr.git] / isisd / isis_nb_state.c
1 /*
2 * Copyright (C) 2018 Volta Networks
3 * Emanuele Di Pascale
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include <zebra.h>
21
22 #include "northbound.h"
23 #include "linklist.h"
24
25 #include "isisd/isisd.h"
26 #include "isisd/isis_nb.h"
27 #include "isisd/isis_circuit.h"
28 #include "isisd/isis_adjacency.h"
29 #include "isisd/isis_misc.h"
30
31 /*
32 * XPath: /frr-interface:lib/interface/state/frr-isisd:isis
33 */
34 struct yang_data *
35 lib_interface_state_isis_get_elem(struct nb_cb_get_elem_args *args)
36 {
37 struct interface *ifp;
38 struct isis_circuit *circuit;
39
40 ifp = (struct interface *)args->list_entry;
41 if (!ifp)
42 return NULL;
43
44 circuit = circuit_scan_by_ifp(ifp);
45 if (!circuit || !circuit->area)
46 return NULL;
47
48 return yang_data_new(args->xpath, NULL);
49 }
50
51 /*
52 * XPath:
53 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency
54 */
55 const void *lib_interface_state_isis_adjacencies_adjacency_get_next(
56 struct nb_cb_get_next_args *args)
57 {
58 struct interface *ifp;
59 struct isis_circuit *circuit;
60 struct isis_adjacency *adj = NULL, *adj_next = NULL;
61 struct list *list;
62 struct listnode *node, *node_next;
63
64 /* Get first adjacency. */
65 if (args->list_entry == NULL) {
66 ifp = (struct interface *)args->parent_list_entry;
67 if (!ifp)
68 return NULL;
69
70 circuit = circuit_scan_by_ifp(ifp);
71 if (!circuit)
72 return NULL;
73
74 switch (circuit->circ_type) {
75 case CIRCUIT_T_BROADCAST:
76 for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS;
77 level++) {
78 struct list *adjdb;
79
80 adjdb = circuit->u.bc.adjdb[level - 1];
81 if (adjdb) {
82 adj = listnode_head(adjdb);
83 if (adj)
84 break;
85 }
86 }
87 break;
88 case CIRCUIT_T_P2P:
89 adj = circuit->u.p2p.neighbor;
90 break;
91 default:
92 break;
93 }
94
95 return adj;
96 }
97
98 /* Get next adjacency. */
99 adj = (struct isis_adjacency *)args->list_entry;
100 circuit = adj->circuit;
101 switch (circuit->circ_type) {
102 case CIRCUIT_T_BROADCAST:
103 list = circuit->u.bc.adjdb[adj->level - 1];
104 node = listnode_lookup(list, adj);
105 node_next = listnextnode(node);
106 if (node_next)
107 adj_next = listgetdata(node_next);
108 else if (adj->level == ISIS_LEVEL1) {
109 /*
110 * Once we finish the L1 adjacencies, move to the L2
111 * adjacencies list.
112 */
113 list = circuit->u.bc.adjdb[ISIS_LEVEL2 - 1];
114 adj_next = listnode_head(list);
115 }
116 break;
117 case CIRCUIT_T_P2P:
118 /* P2P circuits have at most one adjacency. */
119 default:
120 break;
121 }
122
123 return adj_next;
124 }
125
126 /*
127 * XPath:
128 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/neighbor-sys-type
129 */
130 struct yang_data *
131 lib_interface_state_isis_adjacencies_adjacency_neighbor_sys_type_get_elem(
132 struct nb_cb_get_elem_args *args)
133 {
134 const struct isis_adjacency *adj = args->list_entry;
135
136 return yang_data_new_enum(args->xpath, adj->level);
137 }
138
139 /*
140 * XPath:
141 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/neighbor-sysid
142 */
143 struct yang_data *
144 lib_interface_state_isis_adjacencies_adjacency_neighbor_sysid_get_elem(
145 struct nb_cb_get_elem_args *args)
146 {
147 const struct isis_adjacency *adj = args->list_entry;
148
149 return yang_data_new_string(args->xpath, sysid_print(adj->sysid));
150 }
151
152 /*
153 * XPath:
154 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/neighbor-extended-circuit-id
155 */
156 struct yang_data *
157 lib_interface_state_isis_adjacencies_adjacency_neighbor_extended_circuit_id_get_elem(
158 struct nb_cb_get_elem_args *args)
159 {
160 const struct isis_adjacency *adj = args->list_entry;
161
162 return yang_data_new_uint32(args->xpath, adj->circuit->circuit_id);
163 }
164
165 /*
166 * XPath:
167 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/neighbor-snpa
168 */
169 struct yang_data *
170 lib_interface_state_isis_adjacencies_adjacency_neighbor_snpa_get_elem(
171 struct nb_cb_get_elem_args *args)
172 {
173 const struct isis_adjacency *adj = args->list_entry;
174
175 return yang_data_new_string(args->xpath, snpa_print(adj->snpa));
176 }
177
178 /*
179 * XPath:
180 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/hold-timer
181 */
182 struct yang_data *
183 lib_interface_state_isis_adjacencies_adjacency_hold_timer_get_elem(
184 struct nb_cb_get_elem_args *args)
185 {
186 const struct isis_adjacency *adj = args->list_entry;
187
188 return yang_data_new_uint16(args->xpath, adj->hold_time);
189 }
190
191 /*
192 * XPath:
193 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/neighbor-priority
194 */
195 struct yang_data *
196 lib_interface_state_isis_adjacencies_adjacency_neighbor_priority_get_elem(
197 struct nb_cb_get_elem_args *args)
198 {
199 const struct isis_adjacency *adj = args->list_entry;
200
201 return yang_data_new_uint8(args->xpath, adj->prio[adj->level - 1]);
202 }
203
204 /*
205 * XPath:
206 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/state
207 */
208 struct yang_data *lib_interface_state_isis_adjacencies_adjacency_state_get_elem(
209 struct nb_cb_get_elem_args *args)
210 {
211 const struct isis_adjacency *adj = args->list_entry;
212
213 return yang_data_new_string(args->xpath,
214 isis_adj_yang_state(adj->adj_state));
215 }
216
217 /*
218 * XPath:
219 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid
220 */
221 const void *
222 lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_get_next(
223 struct nb_cb_get_next_args *args)
224 {
225 const struct isis_adjacency *adj = args->parent_list_entry;
226 const struct sr_adjacency *sra = args->list_entry, *sra_next = NULL;
227 struct listnode *node, *node_next;
228
229 if (args->list_entry == NULL)
230 sra_next = listnode_head(adj->adj_sids);
231 else {
232 node = listnode_lookup(adj->adj_sids, sra);
233 node_next = listnextnode(node);
234 if (node_next)
235 sra_next = listgetdata(node_next);
236 }
237
238 return sra_next;
239 }
240
241 /*
242 * XPath:
243 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/af
244 */
245 struct yang_data *
246 lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_af_get_elem(
247 struct nb_cb_get_elem_args *args)
248 {
249 const struct sr_adjacency *sra = args->list_entry;
250
251 switch (sra->adj->circuit->circ_type) {
252 case CIRCUIT_T_BROADCAST:
253 /* Adjacency SID is not published with circuit type Broadcast */
254 return NULL;
255 case CIRCUIT_T_P2P:
256 return yang_data_new_uint8(args->xpath, sra->u.adj_sid->family);
257 }
258
259 return NULL;
260 }
261
262 /*
263 * XPath:
264 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/value
265 */
266 struct yang_data *
267 lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_value_get_elem(
268 struct nb_cb_get_elem_args *args)
269 {
270 const struct sr_adjacency *sra = args->list_entry;
271
272 switch (sra->adj->circuit->circ_type) {
273 case CIRCUIT_T_BROADCAST:
274 /* Adjacency SID is not published with circuit type Broadcast */
275 return NULL;
276 case CIRCUIT_T_P2P:
277 return yang_data_new_uint32(args->xpath, sra->u.adj_sid->sid);
278 }
279
280 return NULL;
281 }
282
283 /*
284 * XPath:
285 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/weight
286 */
287 struct yang_data *
288 lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_weight_get_elem(
289 struct nb_cb_get_elem_args *args)
290 {
291 const struct sr_adjacency *sra = args->list_entry;
292
293 switch (sra->adj->circuit->circ_type) {
294 case CIRCUIT_T_BROADCAST:
295 /* Adjacency SID is not published with circuit type Broadcast */
296 return NULL;
297 case CIRCUIT_T_P2P:
298 return yang_data_new_uint8(args->xpath, sra->u.adj_sid->weight);
299 }
300
301 return NULL;
302 }
303
304 /*
305 * XPath:
306 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/protection-requested
307 */
308 struct yang_data *
309 lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_protection_requested_get_elem(
310 struct nb_cb_get_elem_args *args)
311 {
312 const struct sr_adjacency *sra = args->list_entry;
313
314 switch (sra->adj->circuit->circ_type) {
315 case CIRCUIT_T_BROADCAST:
316 /* Adjacency SID is not published with circuit type Broadcast */
317 return NULL;
318 case CIRCUIT_T_P2P:
319 return yang_data_new_bool(args->xpath,
320 sra->u.adj_sid->flags &
321 EXT_SUBTLV_LINK_ADJ_SID_BFLG);
322 }
323
324 return NULL;
325 }
326
327 /*
328 * XPath:
329 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid
330 */
331 const void *
332 lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_get_next(
333 struct nb_cb_get_next_args *args)
334 {
335 const struct isis_adjacency *adj = args->parent_list_entry;
336 const struct sr_adjacency *sra = args->list_entry, *sra_next = NULL;
337 struct listnode *node, *node_next;
338
339 if (args->list_entry == NULL)
340 sra_next = listnode_head(adj->adj_sids);
341 else {
342 node = listnode_lookup(adj->adj_sids, sra);
343 node_next = listnextnode(node);
344 if (node_next)
345 sra_next = listgetdata(node_next);
346 }
347
348 return sra_next;
349 }
350
351 /*
352 * XPath:
353 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/af
354 */
355 struct yang_data *
356 lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_af_get_elem(
357 struct nb_cb_get_elem_args *args)
358 {
359 const struct sr_adjacency *sra = args->list_entry;
360
361 switch (sra->adj->circuit->circ_type) {
362 case CIRCUIT_T_BROADCAST:
363 return yang_data_new_uint8(args->xpath,
364 sra->u.ladj_sid->family);
365 case CIRCUIT_T_P2P:
366 /* LAN adjacency SID is not published with circuit type P2P */
367 return NULL;
368 }
369
370 return NULL;
371 }
372
373 /*
374 * XPath:
375 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/value
376 */
377 struct yang_data *
378 lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_value_get_elem(
379 struct nb_cb_get_elem_args *args)
380 {
381 const struct sr_adjacency *sra = args->list_entry;
382
383 switch (sra->adj->circuit->circ_type) {
384 case CIRCUIT_T_BROADCAST:
385 return yang_data_new_uint32(args->xpath, sra->u.ladj_sid->sid);
386 case CIRCUIT_T_P2P:
387 /* LAN adjacency SID is not published with circuit type P2P */
388 return NULL;
389 }
390
391 return NULL;
392 }
393
394 /*
395 * XPath:
396 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/weight
397 */
398 struct yang_data *
399 lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_weight_get_elem(
400 struct nb_cb_get_elem_args *args)
401 {
402 const struct sr_adjacency *sra = args->list_entry;
403
404 switch (sra->adj->circuit->circ_type) {
405 case CIRCUIT_T_BROADCAST:
406 return yang_data_new_uint8(args->xpath,
407 sra->u.ladj_sid->weight);
408 case CIRCUIT_T_P2P:
409 /* LAN adjacency SID is not published with circuit type P2P */
410 return NULL;
411 }
412
413 return NULL;
414 }
415
416 /*
417 * XPath:
418 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/protection-requested
419 */
420 struct yang_data *
421 lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_protection_requested_get_elem(
422 struct nb_cb_get_elem_args *args)
423 {
424 const struct sr_adjacency *sra = args->list_entry;
425
426 switch (sra->adj->circuit->circ_type) {
427 case CIRCUIT_T_BROADCAST:
428 return yang_data_new_bool(args->xpath,
429 sra->u.ladj_sid->flags &
430 EXT_SUBTLV_LINK_ADJ_SID_BFLG);
431 case CIRCUIT_T_P2P:
432 /* LAN adjacency SID is not published with circuit type P2P */
433 return NULL;
434 }
435
436 return NULL;
437 }
438
439 /*
440 * XPath:
441 * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/adjacency-changes
442 */
443 struct yang_data *
444 lib_interface_state_isis_event_counters_adjacency_changes_get_elem(
445 struct nb_cb_get_elem_args *args)
446 {
447 struct interface *ifp;
448 struct isis_circuit *circuit;
449
450 ifp = (struct interface *)args->list_entry;
451 if (!ifp)
452 return NULL;
453
454 circuit = circuit_scan_by_ifp(ifp);
455 if (!circuit)
456 return NULL;
457
458 return yang_data_new_uint32(args->xpath, circuit->adj_state_changes);
459 }
460
461 /*
462 * XPath:
463 * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/adjacency-number
464 */
465 struct yang_data *
466 lib_interface_state_isis_event_counters_adjacency_number_get_elem(
467 struct nb_cb_get_elem_args *args)
468 {
469 struct interface *ifp;
470 struct isis_circuit *circuit;
471 struct isis_adjacency *adj;
472 struct listnode *node;
473 uint32_t total = 0;
474
475 ifp = (struct interface *)args->list_entry;
476 if (!ifp)
477 return NULL;
478
479 circuit = circuit_scan_by_ifp(ifp);
480 if (!circuit)
481 return NULL;
482
483 /*
484 * TODO: keep track of the number of adjacencies instead of calculating
485 * it on demand.
486 */
487 switch (circuit->circ_type) {
488 case CIRCUIT_T_BROADCAST:
489 for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) {
490 for (ALL_LIST_ELEMENTS_RO(
491 circuit->u.bc.adjdb[level - 1], node, adj))
492 total++;
493 }
494 break;
495 case CIRCUIT_T_P2P:
496 adj = circuit->u.p2p.neighbor;
497 if (adj)
498 total = 1;
499 break;
500 default:
501 break;
502 }
503
504 return yang_data_new_uint32(args->xpath, total);
505 }
506
507 /*
508 * XPath:
509 * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/init-fails
510 */
511 struct yang_data *lib_interface_state_isis_event_counters_init_fails_get_elem(
512 struct nb_cb_get_elem_args *args)
513 {
514 struct interface *ifp;
515 struct isis_circuit *circuit;
516
517 ifp = (struct interface *)args->list_entry;
518 if (!ifp)
519 return NULL;
520
521 circuit = circuit_scan_by_ifp(ifp);
522 if (!circuit)
523 return NULL;
524
525 return yang_data_new_uint32(args->xpath, circuit->init_failures);
526 }
527
528 /*
529 * XPath:
530 * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/adjacency-rejects
531 */
532 struct yang_data *
533 lib_interface_state_isis_event_counters_adjacency_rejects_get_elem(
534 struct nb_cb_get_elem_args *args)
535 {
536 struct interface *ifp;
537 struct isis_circuit *circuit;
538
539 ifp = (struct interface *)args->list_entry;
540 if (!ifp)
541 return NULL;
542
543 circuit = circuit_scan_by_ifp(ifp);
544 if (!circuit)
545 return NULL;
546
547 return yang_data_new_uint32(args->xpath, circuit->rej_adjacencies);
548 }
549
550 /*
551 * XPath:
552 * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/id-len-mismatch
553 */
554 struct yang_data *
555 lib_interface_state_isis_event_counters_id_len_mismatch_get_elem(
556 struct nb_cb_get_elem_args *args)
557 {
558 struct interface *ifp;
559 struct isis_circuit *circuit;
560
561 ifp = (struct interface *)args->list_entry;
562 if (!ifp)
563 return NULL;
564
565 circuit = circuit_scan_by_ifp(ifp);
566 if (!circuit)
567 return NULL;
568
569 return yang_data_new_uint32(args->xpath, circuit->id_len_mismatches);
570 }
571
572 /*
573 * XPath:
574 * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/max-area-addresses-mismatch
575 */
576 struct yang_data *
577 lib_interface_state_isis_event_counters_max_area_addresses_mismatch_get_elem(
578 struct nb_cb_get_elem_args *args)
579 {
580 struct interface *ifp;
581 struct isis_circuit *circuit;
582
583 ifp = (struct interface *)args->list_entry;
584 if (!ifp)
585 return NULL;
586
587 circuit = circuit_scan_by_ifp(ifp);
588 if (!circuit)
589 return NULL;
590
591 return yang_data_new_uint32(args->xpath,
592 circuit->max_area_addr_mismatches);
593 }
594
595 /*
596 * XPath:
597 * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/authentication-type-fails
598 */
599 struct yang_data *
600 lib_interface_state_isis_event_counters_authentication_type_fails_get_elem(
601 struct nb_cb_get_elem_args *args)
602 {
603 struct interface *ifp;
604 struct isis_circuit *circuit;
605
606 ifp = (struct interface *)args->list_entry;
607 if (!ifp)
608 return NULL;
609
610 circuit = circuit_scan_by_ifp(ifp);
611 if (!circuit)
612 return NULL;
613
614 return yang_data_new_uint32(args->xpath, circuit->auth_type_failures);
615 }
616
617 /*
618 * XPath:
619 * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/authentication-fails
620 */
621 struct yang_data *
622 lib_interface_state_isis_event_counters_authentication_fails_get_elem(
623 struct nb_cb_get_elem_args *args)
624 {
625 struct interface *ifp;
626 struct isis_circuit *circuit;
627
628 ifp = (struct interface *)args->list_entry;
629 if (!ifp)
630 return NULL;
631
632 circuit = circuit_scan_by_ifp(ifp);
633 if (!circuit)
634 return NULL;
635
636 return yang_data_new_uint32(args->xpath, circuit->auth_failures);
637 }