]> git.proxmox.com Git - mirror_frr.git/blob - bfdd/bfdd_northbound.c
Merge pull request #5081 from pguibert6WIND/show_brief_doc
[mirror_frr.git] / bfdd / bfdd_northbound.c
1 /*
2 * BFD daemon northbound implementation.
3 *
4 * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
5 * Rafael Zalamena
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301 USA.
21 */
22
23 #include <zebra.h>
24
25 #include "lib/log.h"
26 #include "lib/northbound.h"
27
28 #include "bfd.h"
29
30 /*
31 * Helpers.
32 */
33 static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode,
34 struct bfd_key *bk)
35 {
36 const char *ifname = NULL, *vrfname = NULL;
37 struct sockaddr_any psa, lsa;
38
39 /* Required destination parameter. */
40 strtosa(yang_dnode_get_string(dnode, "./dest-addr"), &psa);
41
42 /* Get optional source address. */
43 memset(&lsa, 0, sizeof(lsa));
44 if (yang_dnode_exists(dnode, "./source-addr"))
45 strtosa(yang_dnode_get_string(dnode, "./source-addr"), &lsa);
46
47 /* Get optional interface and vrf names. */
48 if (yang_dnode_exists(dnode, "./interface"))
49 ifname = yang_dnode_get_string(dnode, "./interface");
50 if (yang_dnode_exists(dnode, "./vrf"))
51 vrfname = yang_dnode_get_string(dnode, "./vrf");
52
53 /* Generate the corresponding key. */
54 gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname);
55 }
56
57 static int bfd_session_create(enum nb_event event, const struct lyd_node *dnode,
58 union nb_resource *resource, bool mhop)
59 {
60 struct bfd_session *bs;
61 struct bfd_key bk;
62
63 switch (event) {
64 case NB_EV_VALIDATE:
65 break;
66
67 case NB_EV_PREPARE:
68 bfd_session_get_key(mhop, dnode, &bk);
69 bs = bfd_key_lookup(bk);
70
71 /* This session was already configured by another daemon. */
72 if (bs != NULL) {
73 /* Now it is configured also by CLI. */
74 BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
75 bs->refcount++;
76
77 resource->ptr = bs;
78 break;
79 }
80
81 bs = bfd_session_new();
82 if (bs == NULL)
83 return NB_ERR_RESOURCE;
84
85 /* Fill the session key. */
86 bfd_session_get_key(mhop, dnode, &bs->key);
87
88 /* Set configuration flags. */
89 bs->refcount = 1;
90 BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
91 if (mhop)
92 BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_MH);
93 if (bs->key.family == AF_INET6)
94 BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_IPV6);
95
96 resource->ptr = bs;
97 break;
98
99 case NB_EV_APPLY:
100 bs = resource->ptr;
101
102 /* Only attempt to registrate if freshly allocated. */
103 if (bs->discrs.my_discr == 0 && bs_registrate(bs) == NULL)
104 return NB_ERR_RESOURCE;
105
106 nb_running_set_entry(dnode, bs);
107 break;
108
109 case NB_EV_ABORT:
110 bs = resource->ptr;
111 if (bs->refcount <= 1)
112 bfd_session_free(resource->ptr);
113 break;
114 }
115
116 return NB_OK;
117 }
118
119 static int bfd_session_destroy(enum nb_event event,
120 const struct lyd_node *dnode, bool mhop)
121 {
122 struct bfd_session *bs;
123 struct bfd_key bk;
124
125 switch (event) {
126 case NB_EV_VALIDATE:
127 bfd_session_get_key(mhop, dnode, &bk);
128 if (bfd_key_lookup(bk) == NULL)
129 return NB_ERR_INCONSISTENCY;
130 break;
131
132 case NB_EV_PREPARE:
133 /* NOTHING */
134 break;
135
136 case NB_EV_APPLY:
137 bs = nb_running_unset_entry(dnode);
138 /* CLI is not using this session anymore. */
139 if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG) == 0)
140 break;
141
142 BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
143 bs->refcount--;
144 /* There are still daemons using it. */
145 if (bs->refcount > 0)
146 break;
147
148 bfd_session_free(bs);
149 break;
150
151 case NB_EV_ABORT:
152 /* NOTHING */
153 break;
154 }
155
156 return NB_OK;
157 }
158
159 /*
160 * XPath: /frr-bfdd:bfdd/bfd
161 */
162 static int bfdd_bfd_create(enum nb_event event,
163 const struct lyd_node *dnode
164 __attribute__((__unused__)),
165 union nb_resource *resource
166 __attribute__((__unused__)))
167 {
168 /* NOTHING */
169 return NB_OK;
170 }
171
172 static int bfdd_bfd_destroy(enum nb_event event, const struct lyd_node *dnode)
173 {
174 switch (event) {
175 case NB_EV_VALIDATE:
176 /* NOTHING */
177 return NB_OK;
178
179 case NB_EV_PREPARE:
180 /* NOTHING */
181 return NB_OK;
182
183 case NB_EV_APPLY:
184 bfd_sessions_remove_manual();
185 break;
186
187 case NB_EV_ABORT:
188 /* NOTHING */
189 return NB_OK;
190 }
191
192 return NB_OK;
193 }
194
195 /*
196 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop
197 */
198 static int bfdd_bfd_sessions_single_hop_create(enum nb_event event,
199 const struct lyd_node *dnode,
200 union nb_resource *resource)
201 {
202 return bfd_session_create(event, dnode, resource, false);
203 }
204
205 static int bfdd_bfd_sessions_single_hop_destroy(enum nb_event event,
206 const struct lyd_node *dnode)
207 {
208 return bfd_session_destroy(event, dnode, false);
209 }
210
211 static const void *
212 bfdd_bfd_sessions_single_hop_get_next(const void *parent_list_entry
213 __attribute__((__unused__)),
214 const void *list_entry)
215 {
216 return bfd_session_next(list_entry, false);
217 }
218
219 static int bfdd_bfd_sessions_single_hop_get_keys(const void *list_entry,
220 struct yang_list_keys *keys)
221 {
222 const struct bfd_session *bs = list_entry;
223 char dstbuf[INET6_ADDRSTRLEN];
224
225 inet_ntop(bs->key.family, &bs->key.peer, dstbuf, sizeof(dstbuf));
226
227 keys->num = 3;
228 strlcpy(keys->key[0], dstbuf, sizeof(keys->key[0]));
229 strlcpy(keys->key[1], bs->key.ifname, sizeof(keys->key[1]));
230 strlcpy(keys->key[2], bs->key.vrfname, sizeof(keys->key[2]));
231
232 return NB_OK;
233 }
234
235 static const void *
236 bfdd_bfd_sessions_single_hop_lookup_entry(const void *parent_list_entry
237 __attribute__((__unused__)),
238 const struct yang_list_keys *keys)
239 {
240 const char *dest_addr = keys->key[0];
241 const char *ifname = keys->key[1];
242 const char *vrf = keys->key[2];
243 struct sockaddr_any psa, lsa;
244 struct bfd_key bk;
245
246 strtosa(dest_addr, &psa);
247 memset(&lsa, 0, sizeof(lsa));
248 gen_bfd_key(&bk, &psa, &lsa, false, ifname, vrf);
249
250 return bfd_key_lookup(bk);
251 }
252
253 /*
254 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr
255 */
256 static int bfdd_bfd_sessions_single_hop_source_addr_modify(
257 enum nb_event event __attribute__((__unused__)),
258 const struct lyd_node *dnode __attribute__((__unused__)),
259 union nb_resource *resource __attribute__((__unused__)))
260 {
261 return NB_OK;
262 }
263
264 static int bfdd_bfd_sessions_single_hop_source_addr_destroy(
265 enum nb_event event __attribute__((__unused__)),
266 const struct lyd_node *dnode __attribute__((__unused__)))
267 {
268 return NB_OK;
269 }
270
271 /*
272 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier
273 */
274 static int bfdd_bfd_sessions_single_hop_detection_multiplier_modify(
275 enum nb_event event, const struct lyd_node *dnode,
276 union nb_resource *resource __attribute__((__unused__)))
277 {
278 uint8_t detection_multiplier = yang_dnode_get_uint8(dnode, NULL);
279 struct bfd_session *bs;
280
281 switch (event) {
282 case NB_EV_VALIDATE:
283 break;
284
285 case NB_EV_PREPARE:
286 /* NOTHING */
287 break;
288
289 case NB_EV_APPLY:
290 bs = nb_running_get_entry(dnode, NULL, true);
291 bs->detect_mult = detection_multiplier;
292 break;
293
294 case NB_EV_ABORT:
295 /* NOTHING */
296 break;
297 }
298
299 return NB_OK;
300 }
301
302 /*
303 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval
304 */
305 static int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify(
306 enum nb_event event, const struct lyd_node *dnode,
307 union nb_resource *resource __attribute__((__unused__)))
308 {
309 uint32_t tx_interval = yang_dnode_get_uint32(dnode, NULL);
310 struct bfd_session *bs;
311
312 switch (event) {
313 case NB_EV_VALIDATE:
314 if (tx_interval < 10000 || tx_interval > 60000000)
315 return NB_ERR_VALIDATION;
316 break;
317
318 case NB_EV_PREPARE:
319 /* NOTHING */
320 break;
321
322 case NB_EV_APPLY:
323 bs = nb_running_get_entry(dnode, NULL, true);
324 if (tx_interval == bs->timers.desired_min_tx)
325 return NB_OK;
326
327 bs->timers.desired_min_tx = tx_interval;
328 bfd_set_polling(bs);
329 break;
330
331 case NB_EV_ABORT:
332 /* NOTHING */
333 break;
334 }
335
336 return NB_OK;
337 }
338
339 /*
340 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval
341 */
342 static int bfdd_bfd_sessions_single_hop_required_receive_interval_modify(
343 enum nb_event event, const struct lyd_node *dnode,
344 union nb_resource *resource __attribute__((__unused__)))
345 {
346 uint32_t rx_interval = yang_dnode_get_uint32(dnode, NULL);
347 struct bfd_session *bs;
348
349 switch (event) {
350 case NB_EV_VALIDATE:
351 if (rx_interval < 10000 || rx_interval > 60000000)
352 return NB_ERR_VALIDATION;
353 break;
354
355 case NB_EV_PREPARE:
356 /* NOTHING */
357 break;
358
359 case NB_EV_APPLY:
360 bs = nb_running_get_entry(dnode, NULL, true);
361 if (rx_interval == bs->timers.required_min_rx)
362 return NB_OK;
363
364 bs->timers.required_min_rx = rx_interval;
365 bfd_set_polling(bs);
366 break;
367
368 case NB_EV_ABORT:
369 /* NOTHING */
370 break;
371 }
372
373 return NB_OK;
374 }
375
376 /*
377 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down
378 */
379 static int bfdd_bfd_sessions_single_hop_administrative_down_modify(
380 enum nb_event event, const struct lyd_node *dnode,
381 union nb_resource *resource __attribute__((__unused__)))
382 {
383 bool shutdown = yang_dnode_get_bool(dnode, NULL);
384 struct bfd_session *bs;
385
386 switch (event) {
387 case NB_EV_VALIDATE:
388 case NB_EV_PREPARE:
389 return NB_OK;
390
391 case NB_EV_APPLY:
392 break;
393
394 case NB_EV_ABORT:
395 return NB_OK;
396 }
397
398 bs = nb_running_get_entry(dnode, NULL, true);
399
400 if (shutdown == false) {
401 if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN))
402 return NB_OK;
403
404 BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN);
405
406 /* Change and notify state change. */
407 bs->ses_state = PTM_BFD_DOWN;
408 control_notify(bs);
409
410 /* Enable all timers. */
411 bfd_recvtimer_update(bs);
412 bfd_xmttimer_update(bs, bs->xmt_TO);
413 if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) {
414 bfd_echo_recvtimer_update(bs);
415 bfd_echo_xmttimer_update(bs, bs->echo_xmt_TO);
416 }
417 } else {
418 if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN))
419 return NB_OK;
420
421 BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN);
422
423 /* Disable all events. */
424 bfd_recvtimer_delete(bs);
425 bfd_echo_recvtimer_delete(bs);
426 bfd_xmttimer_delete(bs);
427 bfd_echo_xmttimer_delete(bs);
428
429 /* Change and notify state change. */
430 bs->ses_state = PTM_BFD_ADM_DOWN;
431 control_notify(bs);
432
433 ptm_bfd_snd(bs, 0);
434 }
435
436 return NB_OK;
437 }
438
439 /*
440 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode
441 */
442 static int bfdd_bfd_sessions_single_hop_echo_mode_modify(
443 enum nb_event event, const struct lyd_node *dnode,
444 union nb_resource *resource __attribute__((__unused__)))
445 {
446 bool echo = yang_dnode_get_bool(dnode, NULL);
447 struct bfd_session *bs;
448
449 switch (event) {
450 case NB_EV_VALIDATE:
451 case NB_EV_PREPARE:
452 return NB_OK;
453
454 case NB_EV_APPLY:
455 break;
456
457 case NB_EV_ABORT:
458 return NB_OK;
459 }
460
461 bs = nb_running_get_entry(dnode, NULL, true);
462
463 if (echo == false) {
464 if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO))
465 return NB_OK;
466
467 BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_ECHO);
468 ptm_bfd_echo_stop(bs);
469 } else {
470 if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO))
471 return NB_OK;
472
473 BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_ECHO);
474 /* Apply setting immediately. */
475 if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN))
476 bs_echo_timer_handler(bs);
477 }
478
479 return NB_OK;
480 }
481
482 /*
483 * XPath:
484 * /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval
485 */
486 static int
487 bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
488 enum nb_event event, const struct lyd_node *dnode,
489 union nb_resource *resource __attribute__((__unused__)))
490 {
491 uint32_t echo_interval = yang_dnode_get_uint32(dnode, NULL);
492 struct bfd_session *bs;
493
494 switch (event) {
495 case NB_EV_VALIDATE:
496 if (echo_interval < 10000 || echo_interval > 60000000)
497 return NB_ERR_VALIDATION;
498 break;
499
500 case NB_EV_PREPARE:
501 /* NOTHING */
502 break;
503
504 case NB_EV_APPLY:
505 bs = nb_running_get_entry(dnode, NULL, true);
506 if (echo_interval == bs->timers.required_min_echo)
507 return NB_OK;
508
509 bs->timers.required_min_echo = echo_interval;
510 break;
511
512 case NB_EV_ABORT:
513 /* NOTHING */
514 break;
515 }
516
517 return NB_OK;
518 }
519
520 /*
521 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-discriminator
522 */
523 static struct yang_data *
524 bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem(
525 const char *xpath, const void *list_entry)
526 {
527 const struct bfd_session *bs = list_entry;
528
529 return yang_data_new_uint32(xpath, bs->discrs.my_discr);
530 }
531
532 /*
533 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-state
534 */
535 static struct yang_data *
536 bfdd_bfd_sessions_single_hop_stats_local_state_get_elem(const char *xpath,
537 const void *list_entry)
538 {
539 const struct bfd_session *bs = list_entry;
540
541 return yang_data_new_enum(xpath, bs->ses_state);
542 }
543
544 /*
545 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-diagnostic
546 */
547 static struct yang_data *
548 bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem(
549 const char *xpath, const void *list_entry)
550 {
551 const struct bfd_session *bs = list_entry;
552
553 return yang_data_new_enum(xpath, bs->local_diag);
554 }
555
556 /*
557 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-multiplier
558 */
559 static struct yang_data *
560 bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem(
561 const char *xpath, const void *list_entry)
562 {
563 const struct bfd_session *bs = list_entry;
564
565 return yang_data_new_int8(xpath, bs->detect_mult);
566 }
567
568 /*
569 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-discriminator
570 */
571 static struct yang_data *
572 bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem(
573 const char *xpath, const void *list_entry)
574 {
575 const struct bfd_session *bs = list_entry;
576
577 if (bs->discrs.remote_discr == 0)
578 return NULL;
579
580 return yang_data_new_uint32(xpath, bs->discrs.remote_discr);
581 }
582
583 /*
584 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-state
585 */
586 static struct yang_data *
587 bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem(const char *xpath,
588 const void *list_entry)
589 {
590 const struct bfd_session *bs = list_entry;
591
592 return yang_data_new_enum(xpath, bs->ses_state);
593 }
594
595 /*
596 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-diagnostic
597 */
598 static struct yang_data *
599 bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem(
600 const char *xpath, const void *list_entry)
601 {
602 const struct bfd_session *bs = list_entry;
603
604 return yang_data_new_enum(xpath, bs->remote_diag);
605 }
606
607 /*
608 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-multiplier
609 */
610 static struct yang_data *
611 bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem(
612 const char *xpath, const void *list_entry)
613 {
614 const struct bfd_session *bs = list_entry;
615
616 return yang_data_new_int8(xpath, bs->remote_detect_mult);
617 }
618
619 /*
620 * XPath:
621 * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-transmission-interval
622 */
623 static struct yang_data *
624 bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem(
625 const char *xpath, const void *list_entry)
626 {
627 const struct bfd_session *bs = list_entry;
628
629 return yang_data_new_uint32(xpath, bs->remote_timers.desired_min_tx);
630 }
631
632 /*
633 * XPath:
634 * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-receive-interval
635 */
636 static struct yang_data *
637 bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem(
638 const char *xpath, const void *list_entry)
639 {
640 const struct bfd_session *bs = list_entry;
641
642 return yang_data_new_uint32(xpath, bs->remote_timers.required_min_rx);
643 }
644
645 /*
646 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/detection-mode
647 */
648 static struct yang_data *
649 bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem(
650 const char *xpath, const void *list_entry)
651 {
652 const struct bfd_session *bs = list_entry;
653 int detection_mode;
654
655 /*
656 * Detection mode:
657 * 1. Async with echo
658 * 2. Async without echo
659 * 3. Demand with echo
660 * 4. Demand without echo
661 *
662 * TODO: support demand mode.
663 */
664 if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO))
665 detection_mode = 1;
666 else
667 detection_mode = 2;
668
669 return yang_data_new_enum(xpath, detection_mode);
670 }
671
672 /*
673 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-down-time
674 */
675 static struct yang_data *
676 bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem(
677 const char *xpath __attribute__((__unused__)),
678 const void *list_entry __attribute__((__unused__)))
679 {
680 /*
681 * TODO: implement me.
682 *
683 * No yang support for time elements yet.
684 */
685 return NULL;
686 }
687
688 /*
689 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-up-time
690 */
691 static struct yang_data *
692 bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem(
693 const char *xpath __attribute__((__unused__)),
694 const void *list_entry __attribute__((__unused__)))
695 {
696 /*
697 * TODO: implement me.
698 *
699 * No yang support for time elements yet.
700 */
701 return NULL;
702 }
703
704 /*
705 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-down-count
706 */
707 static struct yang_data *
708 bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem(
709 const char *xpath, const void *list_entry)
710 {
711 const struct bfd_session *bs = list_entry;
712
713 return yang_data_new_uint64(xpath, bs->stats.session_down);
714 }
715
716 /*
717 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-up-count
718 */
719 static struct yang_data *
720 bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem(
721 const char *xpath, const void *list_entry)
722 {
723 const struct bfd_session *bs = list_entry;
724
725 return yang_data_new_uint64(xpath, bs->stats.session_up);
726 }
727
728 /*
729 * XPath:
730 * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-input-count
731 */
732 static struct yang_data *
733 bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem(
734 const char *xpath, const void *list_entry)
735 {
736 const struct bfd_session *bs = list_entry;
737
738 return yang_data_new_uint64(xpath, bs->stats.rx_ctrl_pkt);
739 }
740
741 /*
742 * XPath:
743 * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-output-count
744 */
745 static struct yang_data *
746 bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem(
747 const char *xpath, const void *list_entry)
748 {
749 const struct bfd_session *bs = list_entry;
750
751 return yang_data_new_uint64(xpath, bs->stats.tx_ctrl_pkt);
752 }
753
754 /*
755 * XPath:
756 * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-echo-transmission-interval
757 */
758 static struct yang_data *
759 bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem(
760 const char *xpath, const void *list_entry)
761 {
762 const struct bfd_session *bs = list_entry;
763
764 return yang_data_new_uint32(xpath, bs->remote_timers.required_min_echo);
765 }
766
767 /*
768 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-input-count
769 */
770 static struct yang_data *
771 bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem(
772 const char *xpath, const void *list_entry)
773 {
774 const struct bfd_session *bs = list_entry;
775
776 return yang_data_new_uint64(xpath, bs->stats.rx_echo_pkt);
777 }
778
779 /*
780 * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-output-count
781 */
782 static struct yang_data *
783 bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem(
784 const char *xpath, const void *list_entry)
785 {
786 const struct bfd_session *bs = list_entry;
787
788 return yang_data_new_uint64(xpath, bs->stats.tx_echo_pkt);
789 }
790
791 /*
792 * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop
793 */
794 static int bfdd_bfd_sessions_multi_hop_create(enum nb_event event,
795 const struct lyd_node *dnode,
796 union nb_resource *resource)
797 {
798 return bfd_session_create(event, dnode, resource, true);
799 }
800
801 static int bfdd_bfd_sessions_multi_hop_destroy(enum nb_event event,
802 const struct lyd_node *dnode)
803 {
804 return bfd_session_destroy(event, dnode, true);
805 }
806
807 static const void *
808 bfdd_bfd_sessions_multi_hop_get_next(const void *parent_list_entry
809 __attribute__((__unused__)),
810 const void *list_entry)
811 {
812 return bfd_session_next(list_entry, true);
813 }
814
815 static int bfdd_bfd_sessions_multi_hop_get_keys(const void *list_entry,
816 struct yang_list_keys *keys)
817 {
818 const struct bfd_session *bs = list_entry;
819 char dstbuf[INET6_ADDRSTRLEN], srcbuf[INET6_ADDRSTRLEN];
820
821 inet_ntop(bs->key.family, &bs->key.peer, dstbuf, sizeof(dstbuf));
822 inet_ntop(bs->key.family, &bs->key.local, srcbuf, sizeof(srcbuf));
823
824 keys->num = 4;
825 strlcpy(keys->key[0], srcbuf, sizeof(keys->key[0]));
826 strlcpy(keys->key[1], dstbuf, sizeof(keys->key[1]));
827 strlcpy(keys->key[2], bs->key.ifname, sizeof(keys->key[2]));
828 strlcpy(keys->key[3], bs->key.vrfname, sizeof(keys->key[3]));
829
830 return NB_OK;
831 }
832
833 static const void *
834 bfdd_bfd_sessions_multi_hop_lookup_entry(const void *parent_list_entry
835 __attribute__((__unused__)),
836 const struct yang_list_keys *keys)
837 {
838 const char *source_addr = keys->key[0];
839 const char *dest_addr = keys->key[1];
840 const char *ifname = keys->key[2];
841 const char *vrf = keys->key[3];
842 struct sockaddr_any psa, lsa;
843 struct bfd_key bk;
844
845 strtosa(dest_addr, &psa);
846 strtosa(source_addr, &lsa);
847 gen_bfd_key(&bk, &psa, &lsa, true, ifname, vrf);
848
849 return bfd_key_lookup(bk);
850 }
851
852 /* clang-format off */
853 const struct frr_yang_module_info frr_bfdd_info = {
854 .name = "frr-bfdd",
855 .nodes = {
856 {
857 .xpath = "/frr-bfdd:bfdd/bfd",
858 .cbs = {
859 .create = bfdd_bfd_create,
860 .destroy = bfdd_bfd_destroy,
861 .cli_show = bfd_cli_show_header,
862 .cli_show_end = bfd_cli_show_header_end,
863 }
864 },
865 {
866 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop",
867 .cbs = {
868 .create = bfdd_bfd_sessions_single_hop_create,
869 .destroy = bfdd_bfd_sessions_single_hop_destroy,
870 .get_next = bfdd_bfd_sessions_single_hop_get_next,
871 .get_keys = bfdd_bfd_sessions_single_hop_get_keys,
872 .lookup_entry = bfdd_bfd_sessions_single_hop_lookup_entry,
873 .cli_show = bfd_cli_show_single_hop_peer,
874 .cli_show_end = bfd_cli_show_peer_end,
875 }
876 },
877 {
878 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr",
879 .cbs = {
880 .modify = bfdd_bfd_sessions_single_hop_source_addr_modify,
881 .destroy = bfdd_bfd_sessions_single_hop_source_addr_destroy,
882 }
883 },
884 {
885 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier",
886 .cbs = {
887 .modify = bfdd_bfd_sessions_single_hop_detection_multiplier_modify,
888 .cli_show = bfd_cli_show_mult,
889 }
890 },
891 {
892 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval",
893 .cbs = {
894 .modify = bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify,
895 .cli_show = bfd_cli_show_tx,
896 }
897 },
898 {
899 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval",
900 .cbs = {
901 .modify = bfdd_bfd_sessions_single_hop_required_receive_interval_modify,
902 .cli_show = bfd_cli_show_rx,
903 }
904 },
905 {
906 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down",
907 .cbs = {
908 .modify = bfdd_bfd_sessions_single_hop_administrative_down_modify,
909 .cli_show = bfd_cli_show_shutdown,
910 }
911 },
912 {
913 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode",
914 .cbs = {
915 .modify = bfdd_bfd_sessions_single_hop_echo_mode_modify,
916 .cli_show = bfd_cli_show_echo,
917 }
918 },
919 {
920 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval",
921 .cbs = {
922 .modify = bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify,
923 .cli_show = bfd_cli_show_echo_interval,
924 }
925 },
926 {
927 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-discriminator",
928 .cbs = {
929 .get_elem = bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem,
930 }
931 },
932 {
933 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-state",
934 .cbs = {
935 .get_elem = bfdd_bfd_sessions_single_hop_stats_local_state_get_elem,
936 }
937 },
938 {
939 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-diagnostic",
940 .cbs = {
941 .get_elem = bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem,
942 }
943 },
944 {
945 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-multiplier",
946 .cbs = {
947 .get_elem = bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem,
948 }
949 },
950 {
951 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-discriminator",
952 .cbs = {
953 .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem,
954 }
955 },
956 {
957 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-state",
958 .cbs = {
959 .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem,
960 }
961 },
962 {
963 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-diagnostic",
964 .cbs = {
965 .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem,
966 }
967 },
968 {
969 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-multiplier",
970 .cbs = {
971 .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem,
972 }
973 },
974 {
975 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-transmission-interval",
976 .cbs = {
977 .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem,
978 }
979 },
980 {
981 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-receive-interval",
982 .cbs = {
983 .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem,
984 }
985 },
986 {
987 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/detection-mode",
988 .cbs = {
989 .get_elem = bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem,
990 }
991 },
992 {
993 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-down-time",
994 .cbs = {
995 .get_elem = bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem,
996 }
997 },
998 {
999 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-up-time",
1000 .cbs = {
1001 .get_elem = bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem,
1002 }
1003 },
1004 {
1005 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-down-count",
1006 .cbs = {
1007 .get_elem = bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem,
1008 }
1009 },
1010 {
1011 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-up-count",
1012 .cbs = {
1013 .get_elem = bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem,
1014 }
1015 },
1016 {
1017 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-input-count",
1018 .cbs = {
1019 .get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem,
1020 }
1021 },
1022 {
1023 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-output-count",
1024 .cbs = {
1025 .get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem,
1026 }
1027 },
1028 {
1029 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-echo-transmission-interval",
1030 .cbs = {
1031 .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem,
1032 }
1033 },
1034 {
1035 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-input-count",
1036 .cbs = {
1037 .get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem,
1038 }
1039 },
1040 {
1041 .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-output-count",
1042 .cbs = {
1043 .get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem,
1044 }
1045 },
1046 {
1047 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop",
1048 .cbs = {
1049 .create = bfdd_bfd_sessions_multi_hop_create,
1050 .destroy = bfdd_bfd_sessions_multi_hop_destroy,
1051 .get_next = bfdd_bfd_sessions_multi_hop_get_next,
1052 .get_keys = bfdd_bfd_sessions_multi_hop_get_keys,
1053 .lookup_entry = bfdd_bfd_sessions_multi_hop_lookup_entry,
1054 .cli_show = bfd_cli_show_multi_hop_peer,
1055 .cli_show_end = bfd_cli_show_peer_end,
1056 }
1057 },
1058 {
1059 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/detection-multiplier",
1060 .cbs = {
1061 .modify = bfdd_bfd_sessions_single_hop_detection_multiplier_modify,
1062 .cli_show = bfd_cli_show_mult,
1063 }
1064 },
1065 {
1066 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/desired-transmission-interval",
1067 .cbs = {
1068 .modify = bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify,
1069 .cli_show = bfd_cli_show_tx,
1070 }
1071 },
1072 {
1073 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/required-receive-interval",
1074 .cbs = {
1075 .modify = bfdd_bfd_sessions_single_hop_required_receive_interval_modify,
1076 .cli_show = bfd_cli_show_rx,
1077 }
1078 },
1079 {
1080 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/administrative-down",
1081 .cbs = {
1082 .modify = bfdd_bfd_sessions_single_hop_administrative_down_modify,
1083 .cli_show = bfd_cli_show_shutdown,
1084 }
1085 },
1086 {
1087 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-discriminator",
1088 .cbs = {
1089 .get_elem = bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem,
1090 }
1091 },
1092 {
1093 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-state",
1094 .cbs = {
1095 .get_elem = bfdd_bfd_sessions_single_hop_stats_local_state_get_elem,
1096 }
1097 },
1098 {
1099 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-diagnostic",
1100 .cbs = {
1101 .get_elem = bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem,
1102 }
1103 },
1104 {
1105 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-multiplier",
1106 .cbs = {
1107 .get_elem = bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem,
1108 }
1109 },
1110 {
1111 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-discriminator",
1112 .cbs = {
1113 .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem,
1114 }
1115 },
1116 {
1117 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-state",
1118 .cbs = {
1119 .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem,
1120 }
1121 },
1122 {
1123 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-diagnostic",
1124 .cbs = {
1125 .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem,
1126 }
1127 },
1128 {
1129 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-multiplier",
1130 .cbs = {
1131 .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem,
1132 }
1133 },
1134 {
1135 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/negotiated-transmission-interval",
1136 .cbs = {
1137 .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem,
1138 }
1139 },
1140 {
1141 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/negotiated-receive-interval",
1142 .cbs = {
1143 .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem,
1144 }
1145 },
1146 {
1147 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/detection-mode",
1148 .cbs = {
1149 .get_elem = bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem,
1150 }
1151 },
1152 {
1153 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/last-down-time",
1154 .cbs = {
1155 .get_elem = bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem,
1156 }
1157 },
1158 {
1159 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/last-up-time",
1160 .cbs = {
1161 .get_elem = bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem,
1162 }
1163 },
1164 {
1165 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/session-down-count",
1166 .cbs = {
1167 .get_elem = bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem,
1168 }
1169 },
1170 {
1171 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/session-up-count",
1172 .cbs = {
1173 .get_elem = bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem,
1174 }
1175 },
1176 {
1177 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/control-packet-input-count",
1178 .cbs = {
1179 .get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem,
1180 }
1181 },
1182 {
1183 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/control-packet-output-count",
1184 .cbs = {
1185 .get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem,
1186 }
1187 },
1188 {
1189 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/negotiated-echo-transmission-interval",
1190 .cbs = {
1191 .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem,
1192 }
1193 },
1194 {
1195 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/echo-packet-input-count",
1196 .cbs = {
1197 .get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem,
1198 }
1199 },
1200 {
1201 .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/echo-packet-output-count",
1202 .cbs = {
1203 .get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem,
1204 }
1205 },
1206 {
1207 .xpath = NULL,
1208 },
1209 }
1210 };