]>
Commit | Line | Data |
---|---|---|
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 | */ | |
31 | void bfd_session_get_key(bool mhop, const struct lyd_node *dnode, | |
32 | struct bfd_key *bk); | |
33 | int bfd_session_create(enum nb_event event, const struct lyd_node *dnode, | |
34 | union nb_resource *resource, bool mhop); | |
35 | int bfd_session_destroy(enum nb_event event, const struct lyd_node *dnode, | |
36 | bool mhop); | |
37 | ||
38 | /* | |
39 | * Helpers. | |
40 | */ | |
41 | void 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 | ||
65 | int 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 | ||
112 | int 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 | */ | |
143 | static 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 | ||
153 | static 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 | */ | |
162 | static 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 | ||
169 | static 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 | ||
175 | static const void * | |
176 | bfdd_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 | ||
183 | static 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 | ||
199 | static const void * | |
200 | bfdd_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 | */ | |
220 | static 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 | ||
228 | static 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 | */ | |
238 | static 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 | */ | |
271 | static 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 | */ | |
310 | static 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 | */ | |
349 | static 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 | */ | |
412 | static 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 | */ | |
456 | static int | |
457 | bfdd_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 | */ | |
495 | static struct yang_data * | |
496 | bfdd_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 | */ | |
507 | static struct yang_data * | |
508 | bfdd_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 | */ | |
519 | static struct yang_data * | |
520 | bfdd_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 | */ | |
531 | static struct yang_data * | |
532 | bfdd_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 | */ | |
543 | static struct yang_data * | |
544 | bfdd_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 | */ | |
555 | static struct yang_data * | |
556 | bfdd_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 | */ | |
567 | static struct yang_data * | |
568 | bfdd_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 | */ | |
579 | static struct yang_data * | |
580 | bfdd_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 | */ | |
592 | static struct yang_data * | |
593 | bfdd_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 | */ | |
606 | static struct yang_data * | |
607 | bfdd_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 | */ | |
619 | static struct yang_data * | |
620 | bfdd_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 | */ | |
646 | static struct yang_data * | |
647 | bfdd_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 | */ | |
662 | static struct yang_data * | |
663 | bfdd_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 | */ | |
678 | static struct yang_data * | |
679 | bfdd_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 | */ | |
690 | static struct yang_data * | |
691 | bfdd_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 | */ | |
703 | static struct yang_data * | |
704 | bfdd_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 | */ | |
716 | static struct yang_data * | |
717 | bfdd_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 | */ | |
729 | static struct yang_data * | |
730 | bfdd_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 | */ | |
742 | static struct yang_data * | |
743 | bfdd_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 | */ | |
754 | static struct yang_data * | |
755 | bfdd_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 | */ | |
766 | static 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 | ||
773 | static 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 | ||
779 | static const void * | |
780 | bfdd_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 | ||
787 | static 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 | ||
805 | static const void * | |
806 | bfdd_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 */ | |
825 | const 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 | }; |