]> git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_nb_state.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[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 char xpath_value[ISO_SYSID_STRLEN];
136
137 snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pSY", adj->sysid);
138
139 return yang_data_new_string(args->xpath, xpath_value);
140 }
141
142 /*
143 * XPath:
144 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/neighbor-extended-circuit-id
145 */
146 struct yang_data *
147 lib_interface_state_isis_adjacencies_adjacency_neighbor_extended_circuit_id_get_elem(
148 struct nb_cb_get_elem_args *args)
149 {
150 const struct isis_adjacency *adj = args->list_entry;
151
152 return yang_data_new_uint32(args->xpath, adj->circuit->circuit_id);
153 }
154
155 /*
156 * XPath:
157 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/neighbor-snpa
158 */
159 struct yang_data *
160 lib_interface_state_isis_adjacencies_adjacency_neighbor_snpa_get_elem(
161 struct nb_cb_get_elem_args *args)
162 {
163 const struct isis_adjacency *adj = args->list_entry;
164 char xpath_value[ISO_SYSID_STRLEN];
165
166 snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pSY", adj->snpa);
167
168 return yang_data_new_string(args->xpath, xpath_value);
169 }
170
171 /*
172 * XPath:
173 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/hold-timer
174 */
175 struct yang_data *
176 lib_interface_state_isis_adjacencies_adjacency_hold_timer_get_elem(
177 struct nb_cb_get_elem_args *args)
178 {
179 const struct isis_adjacency *adj = args->list_entry;
180
181 return yang_data_new_uint16(args->xpath, adj->hold_time);
182 }
183
184 /*
185 * XPath:
186 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/neighbor-priority
187 */
188 struct yang_data *
189 lib_interface_state_isis_adjacencies_adjacency_neighbor_priority_get_elem(
190 struct nb_cb_get_elem_args *args)
191 {
192 const struct isis_adjacency *adj = args->list_entry;
193
194 return yang_data_new_uint8(args->xpath, adj->prio[adj->level - 1]);
195 }
196
197 /*
198 * XPath:
199 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/state
200 */
201 struct yang_data *lib_interface_state_isis_adjacencies_adjacency_state_get_elem(
202 struct nb_cb_get_elem_args *args)
203 {
204 const struct isis_adjacency *adj = args->list_entry;
205
206 return yang_data_new_string(args->xpath,
207 isis_adj_yang_state(adj->adj_state));
208 }
209
210 /*
211 * XPath:
212 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid
213 */
214 const void *
215 lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_get_next(
216 struct nb_cb_get_next_args *args)
217 {
218 const struct isis_adjacency *adj = args->parent_list_entry;
219 const struct sr_adjacency *sra = args->list_entry, *sra_next = NULL;
220 struct listnode *node, *node_next;
221
222 if (args->list_entry == NULL)
223 sra_next = listnode_head(adj->adj_sids);
224 else {
225 node = listnode_lookup(adj->adj_sids, sra);
226 node_next = listnextnode(node);
227 if (node_next)
228 sra_next = listgetdata(node_next);
229 }
230
231 return sra_next;
232 }
233
234 /*
235 * XPath:
236 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/af
237 */
238 struct yang_data *
239 lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_af_get_elem(
240 struct nb_cb_get_elem_args *args)
241 {
242 const struct sr_adjacency *sra = args->list_entry;
243
244 switch (sra->adj->circuit->circ_type) {
245 case CIRCUIT_T_BROADCAST:
246 /* Adjacency SID is not published with circuit type Broadcast */
247 return NULL;
248 case CIRCUIT_T_P2P:
249 return yang_data_new_uint8(args->xpath, sra->u.adj_sid->family);
250 }
251
252 return NULL;
253 }
254
255 /*
256 * XPath:
257 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/value
258 */
259 struct yang_data *
260 lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_value_get_elem(
261 struct nb_cb_get_elem_args *args)
262 {
263 const struct sr_adjacency *sra = args->list_entry;
264
265 switch (sra->adj->circuit->circ_type) {
266 case CIRCUIT_T_BROADCAST:
267 /* Adjacency SID is not published with circuit type Broadcast */
268 return NULL;
269 case CIRCUIT_T_P2P:
270 return yang_data_new_uint32(args->xpath, sra->u.adj_sid->sid);
271 }
272
273 return NULL;
274 }
275
276 /*
277 * XPath:
278 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/weight
279 */
280 struct yang_data *
281 lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_weight_get_elem(
282 struct nb_cb_get_elem_args *args)
283 {
284 const struct sr_adjacency *sra = args->list_entry;
285
286 switch (sra->adj->circuit->circ_type) {
287 case CIRCUIT_T_BROADCAST:
288 /* Adjacency SID is not published with circuit type Broadcast */
289 return NULL;
290 case CIRCUIT_T_P2P:
291 return yang_data_new_uint8(args->xpath, sra->u.adj_sid->weight);
292 }
293
294 return NULL;
295 }
296
297 /*
298 * XPath:
299 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/protection-requested
300 */
301 struct yang_data *
302 lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_protection_requested_get_elem(
303 struct nb_cb_get_elem_args *args)
304 {
305 const struct sr_adjacency *sra = args->list_entry;
306
307 switch (sra->adj->circuit->circ_type) {
308 case CIRCUIT_T_BROADCAST:
309 /* Adjacency SID is not published with circuit type Broadcast */
310 return NULL;
311 case CIRCUIT_T_P2P:
312 return yang_data_new_bool(args->xpath,
313 sra->u.adj_sid->flags &
314 EXT_SUBTLV_LINK_ADJ_SID_BFLG);
315 }
316
317 return NULL;
318 }
319
320 /*
321 * XPath:
322 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid
323 */
324 const void *
325 lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_get_next(
326 struct nb_cb_get_next_args *args)
327 {
328 const struct isis_adjacency *adj = args->parent_list_entry;
329 const struct sr_adjacency *sra = args->list_entry, *sra_next = NULL;
330 struct listnode *node, *node_next;
331
332 if (args->list_entry == NULL)
333 sra_next = listnode_head(adj->adj_sids);
334 else {
335 node = listnode_lookup(adj->adj_sids, sra);
336 node_next = listnextnode(node);
337 if (node_next)
338 sra_next = listgetdata(node_next);
339 }
340
341 return sra_next;
342 }
343
344 /*
345 * XPath:
346 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/af
347 */
348 struct yang_data *
349 lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_af_get_elem(
350 struct nb_cb_get_elem_args *args)
351 {
352 const struct sr_adjacency *sra = args->list_entry;
353
354 switch (sra->adj->circuit->circ_type) {
355 case CIRCUIT_T_BROADCAST:
356 return yang_data_new_uint8(args->xpath,
357 sra->u.ladj_sid->family);
358 case CIRCUIT_T_P2P:
359 /* LAN adjacency SID is not published with circuit type P2P */
360 return NULL;
361 }
362
363 return NULL;
364 }
365
366 /*
367 * XPath:
368 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/value
369 */
370 struct yang_data *
371 lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_value_get_elem(
372 struct nb_cb_get_elem_args *args)
373 {
374 const struct sr_adjacency *sra = args->list_entry;
375
376 switch (sra->adj->circuit->circ_type) {
377 case CIRCUIT_T_BROADCAST:
378 return yang_data_new_uint32(args->xpath, sra->u.ladj_sid->sid);
379 case CIRCUIT_T_P2P:
380 /* LAN adjacency SID is not published with circuit type P2P */
381 return NULL;
382 }
383
384 return NULL;
385 }
386
387 /*
388 * XPath:
389 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/weight
390 */
391 struct yang_data *
392 lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_weight_get_elem(
393 struct nb_cb_get_elem_args *args)
394 {
395 const struct sr_adjacency *sra = args->list_entry;
396
397 switch (sra->adj->circuit->circ_type) {
398 case CIRCUIT_T_BROADCAST:
399 return yang_data_new_uint8(args->xpath,
400 sra->u.ladj_sid->weight);
401 case CIRCUIT_T_P2P:
402 /* LAN adjacency SID is not published with circuit type P2P */
403 return NULL;
404 }
405
406 return NULL;
407 }
408
409 /*
410 * XPath:
411 * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/protection-requested
412 */
413 struct yang_data *
414 lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_protection_requested_get_elem(
415 struct nb_cb_get_elem_args *args)
416 {
417 const struct sr_adjacency *sra = args->list_entry;
418
419 switch (sra->adj->circuit->circ_type) {
420 case CIRCUIT_T_BROADCAST:
421 return yang_data_new_bool(args->xpath,
422 sra->u.ladj_sid->flags &
423 EXT_SUBTLV_LINK_ADJ_SID_BFLG);
424 case CIRCUIT_T_P2P:
425 /* LAN adjacency SID is not published with circuit type P2P */
426 return NULL;
427 }
428
429 return NULL;
430 }
431
432 /*
433 * XPath:
434 * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/adjacency-changes
435 */
436 struct yang_data *
437 lib_interface_state_isis_event_counters_adjacency_changes_get_elem(
438 struct nb_cb_get_elem_args *args)
439 {
440 struct interface *ifp;
441 struct isis_circuit *circuit;
442
443 ifp = (struct interface *)args->list_entry;
444 if (!ifp)
445 return NULL;
446
447 circuit = circuit_scan_by_ifp(ifp);
448 if (!circuit)
449 return NULL;
450
451 return yang_data_new_uint32(args->xpath, circuit->adj_state_changes);
452 }
453
454 /*
455 * XPath:
456 * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/adjacency-number
457 */
458 struct yang_data *
459 lib_interface_state_isis_event_counters_adjacency_number_get_elem(
460 struct nb_cb_get_elem_args *args)
461 {
462 struct interface *ifp;
463 struct isis_circuit *circuit;
464 struct isis_adjacency *adj;
465 struct listnode *node;
466 uint32_t total = 0;
467
468 ifp = (struct interface *)args->list_entry;
469 if (!ifp)
470 return NULL;
471
472 circuit = circuit_scan_by_ifp(ifp);
473 if (!circuit)
474 return NULL;
475
476 /*
477 * TODO: keep track of the number of adjacencies instead of calculating
478 * it on demand.
479 */
480 switch (circuit->circ_type) {
481 case CIRCUIT_T_BROADCAST:
482 for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) {
483 for (ALL_LIST_ELEMENTS_RO(
484 circuit->u.bc.adjdb[level - 1], node, adj))
485 total++;
486 }
487 break;
488 case CIRCUIT_T_P2P:
489 adj = circuit->u.p2p.neighbor;
490 if (adj)
491 total = 1;
492 break;
493 default:
494 break;
495 }
496
497 return yang_data_new_uint32(args->xpath, total);
498 }
499
500 /*
501 * XPath:
502 * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/init-fails
503 */
504 struct yang_data *lib_interface_state_isis_event_counters_init_fails_get_elem(
505 struct nb_cb_get_elem_args *args)
506 {
507 struct interface *ifp;
508 struct isis_circuit *circuit;
509
510 ifp = (struct interface *)args->list_entry;
511 if (!ifp)
512 return NULL;
513
514 circuit = circuit_scan_by_ifp(ifp);
515 if (!circuit)
516 return NULL;
517
518 return yang_data_new_uint32(args->xpath, circuit->init_failures);
519 }
520
521 /*
522 * XPath:
523 * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/adjacency-rejects
524 */
525 struct yang_data *
526 lib_interface_state_isis_event_counters_adjacency_rejects_get_elem(
527 struct nb_cb_get_elem_args *args)
528 {
529 struct interface *ifp;
530 struct isis_circuit *circuit;
531
532 ifp = (struct interface *)args->list_entry;
533 if (!ifp)
534 return NULL;
535
536 circuit = circuit_scan_by_ifp(ifp);
537 if (!circuit)
538 return NULL;
539
540 return yang_data_new_uint32(args->xpath, circuit->rej_adjacencies);
541 }
542
543 /*
544 * XPath:
545 * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/id-len-mismatch
546 */
547 struct yang_data *
548 lib_interface_state_isis_event_counters_id_len_mismatch_get_elem(
549 struct nb_cb_get_elem_args *args)
550 {
551 struct interface *ifp;
552 struct isis_circuit *circuit;
553
554 ifp = (struct interface *)args->list_entry;
555 if (!ifp)
556 return NULL;
557
558 circuit = circuit_scan_by_ifp(ifp);
559 if (!circuit)
560 return NULL;
561
562 return yang_data_new_uint32(args->xpath, circuit->id_len_mismatches);
563 }
564
565 /*
566 * XPath:
567 * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/max-area-addresses-mismatch
568 */
569 struct yang_data *
570 lib_interface_state_isis_event_counters_max_area_addresses_mismatch_get_elem(
571 struct nb_cb_get_elem_args *args)
572 {
573 struct interface *ifp;
574 struct isis_circuit *circuit;
575
576 ifp = (struct interface *)args->list_entry;
577 if (!ifp)
578 return NULL;
579
580 circuit = circuit_scan_by_ifp(ifp);
581 if (!circuit)
582 return NULL;
583
584 return yang_data_new_uint32(args->xpath,
585 circuit->max_area_addr_mismatches);
586 }
587
588 /*
589 * XPath:
590 * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/authentication-type-fails
591 */
592 struct yang_data *
593 lib_interface_state_isis_event_counters_authentication_type_fails_get_elem(
594 struct nb_cb_get_elem_args *args)
595 {
596 struct interface *ifp;
597 struct isis_circuit *circuit;
598
599 ifp = (struct interface *)args->list_entry;
600 if (!ifp)
601 return NULL;
602
603 circuit = circuit_scan_by_ifp(ifp);
604 if (!circuit)
605 return NULL;
606
607 return yang_data_new_uint32(args->xpath, circuit->auth_type_failures);
608 }
609
610 /*
611 * XPath:
612 * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/authentication-fails
613 */
614 struct yang_data *
615 lib_interface_state_isis_event_counters_authentication_fails_get_elem(
616 struct nb_cb_get_elem_args *args)
617 {
618 struct interface *ifp;
619 struct isis_circuit *circuit;
620
621 ifp = (struct interface *)args->list_entry;
622 if (!ifp)
623 return NULL;
624
625 circuit = circuit_scan_by_ifp(ifp);
626 if (!circuit)
627 return NULL;
628
629 return yang_data_new_uint32(args->xpath, circuit->auth_failures);
630 }