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