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