]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
1c2facd1 RW |
2 | /* |
3 | * Copyright (C) 2018 NetDEF, Inc. | |
4 | * Renato Westphal | |
1c2facd1 RW |
5 | */ |
6 | ||
7 | #include <zebra.h> | |
8 | ||
ac313345 | 9 | #include "base64.h" |
1c2facd1 RW |
10 | #include "log.h" |
11 | #include "lib_errors.h" | |
12 | #include "northbound.h" | |
566bdaf6 | 13 | #include "printfrr.h" |
cad46cfd | 14 | #include "nexthop.h" |
8d0c8ff5 | 15 | #include "printfrr.h" |
1c2facd1 | 16 | |
3bb513c3 CH |
17 | |
18 | #define YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt) \ | |
19 | ({ \ | |
20 | va_list __ap; \ | |
21 | va_start(__ap, (xpath_fmt)); \ | |
22 | const struct lyd_value *__dvalue = \ | |
23 | yang_dnode_xpath_get_value(dnode, xpath_fmt, __ap); \ | |
24 | va_end(__ap); \ | |
25 | __dvalue; \ | |
26 | }) | |
27 | ||
28 | #define YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt) \ | |
29 | ({ \ | |
30 | va_list __ap; \ | |
31 | va_start(__ap, (xpath_fmt)); \ | |
32 | const char *__canon = \ | |
33 | yang_dnode_xpath_get_canon(dnode, xpath_fmt, __ap); \ | |
34 | va_end(__ap); \ | |
35 | __canon; \ | |
36 | }) | |
37 | ||
38 | #define YANG_DNODE_GET_ASSERT(dnode, xpath) \ | |
39 | do { \ | |
40 | if ((dnode) == NULL) { \ | |
41 | flog_err(EC_LIB_YANG_DNODE_NOT_FOUND, \ | |
42 | "%s: couldn't find %s", __func__, (xpath)); \ | |
43 | zlog_backtrace(LOG_ERR); \ | |
44 | abort(); \ | |
45 | } \ | |
46 | } while (0) | |
47 | ||
0f9de11a | 48 | PRINTFRR(2, 0) |
3bb513c3 CH |
49 | static inline const char * |
50 | yang_dnode_xpath_get_canon(const struct lyd_node *dnode, const char *xpath_fmt, | |
51 | va_list ap) | |
52 | { | |
53 | const struct lyd_node_term *__dleaf = | |
54 | (const struct lyd_node_term *)dnode; | |
55 | assert(__dleaf); | |
56 | if (xpath_fmt) { | |
57 | char __xpath[XPATH_MAXLEN]; | |
58 | vsnprintf(__xpath, sizeof(__xpath), xpath_fmt, ap); | |
59 | __dleaf = (const struct lyd_node_term *)yang_dnode_get(dnode, | |
60 | __xpath); | |
61 | YANG_DNODE_GET_ASSERT(__dleaf, __xpath); | |
62 | } | |
63 | return lyd_get_value(&__dleaf->node); | |
64 | } | |
65 | ||
0f9de11a | 66 | PRINTFRR(2, 0) |
3bb513c3 CH |
67 | static inline const struct lyd_value * |
68 | yang_dnode_xpath_get_value(const struct lyd_node *dnode, const char *xpath_fmt, | |
69 | va_list ap) | |
70 | { | |
71 | const struct lyd_node_term *__dleaf = | |
72 | (const struct lyd_node_term *)dnode; | |
73 | assert(__dleaf); | |
74 | if (xpath_fmt) { | |
75 | char __xpath[XPATH_MAXLEN]; | |
76 | vsnprintf(__xpath, sizeof(__xpath), xpath_fmt, ap); | |
77 | __dleaf = (const struct lyd_node_term *)yang_dnode_get(dnode, | |
78 | __xpath); | |
79 | YANG_DNODE_GET_ASSERT(__dleaf, __xpath); | |
80 | } | |
81 | const struct lyd_value *__dvalue = &__dleaf->value; | |
82 | if (__dvalue->realtype->basetype == LY_TYPE_UNION) | |
83 | __dvalue = &__dvalue->subvalue->value; | |
84 | return __dvalue; | |
85 | } | |
86 | ||
1c2facd1 RW |
87 | static const char *yang_get_default_value(const char *xpath) |
88 | { | |
3bb513c3 | 89 | const struct lysc_node *snode; |
1c2facd1 RW |
90 | const char *value; |
91 | ||
3bb513c3 | 92 | snode = lys_find_path(ly_native_ctx, NULL, xpath, 0); |
1c2facd1 RW |
93 | if (snode == NULL) { |
94 | flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH, | |
95 | "%s: unknown data path: %s", __func__, xpath); | |
96 | zlog_backtrace(LOG_ERR); | |
97 | abort(); | |
98 | } | |
99 | ||
100 | value = yang_snode_get_default(snode); | |
101 | assert(value); | |
102 | ||
103 | return value; | |
104 | } | |
105 | ||
1c2facd1 RW |
106 | /* |
107 | * Primitive type: bool. | |
108 | */ | |
109 | bool yang_str2bool(const char *value) | |
110 | { | |
111 | return strmatch(value, "true"); | |
112 | } | |
113 | ||
114 | struct yang_data *yang_data_new_bool(const char *xpath, bool value) | |
115 | { | |
d8729f8c | 116 | return yang_data_new(xpath, (value) ? "true" : "false"); |
1c2facd1 RW |
117 | } |
118 | ||
119 | bool yang_dnode_get_bool(const struct lyd_node *dnode, const char *xpath_fmt, | |
120 | ...) | |
121 | { | |
3bb513c3 CH |
122 | const struct lyd_value *dvalue; |
123 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); | |
124 | assert(dvalue->realtype->basetype == LY_TYPE_BOOL); | |
125 | return dvalue->boolean; | |
1c2facd1 RW |
126 | } |
127 | ||
128 | bool yang_get_default_bool(const char *xpath_fmt, ...) | |
129 | { | |
130 | char xpath[XPATH_MAXLEN]; | |
131 | const char *value; | |
132 | va_list ap; | |
133 | ||
134 | va_start(ap, xpath_fmt); | |
135 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
136 | va_end(ap); | |
137 | ||
138 | value = yang_get_default_value(xpath); | |
139 | return yang_str2bool(value); | |
140 | } | |
141 | ||
142 | /* | |
143 | * Primitive type: dec64. | |
144 | */ | |
145 | double yang_str2dec64(const char *xpath, const char *value) | |
146 | { | |
147 | double dbl = 0; | |
148 | ||
149 | if (sscanf(value, "%lf", &dbl) != 1) { | |
150 | flog_err(EC_LIB_YANG_DATA_CONVERT, | |
151 | "%s: couldn't convert string to decimal64 [xpath %s]", | |
152 | __func__, xpath); | |
153 | zlog_backtrace(LOG_ERR); | |
154 | abort(); | |
155 | } | |
156 | ||
157 | return dbl; | |
158 | } | |
159 | ||
160 | struct yang_data *yang_data_new_dec64(const char *xpath, double value) | |
161 | { | |
162 | char value_str[BUFSIZ]; | |
163 | ||
164 | snprintf(value_str, sizeof(value_str), "%lf", value); | |
165 | return yang_data_new(xpath, value_str); | |
166 | } | |
167 | ||
168 | double yang_dnode_get_dec64(const struct lyd_node *dnode, const char *xpath_fmt, | |
169 | ...) | |
170 | { | |
3bb513c3 CH |
171 | const double denom[19] = {1e0, 1e-1, 1e-2, 1e-3, 1e-4, |
172 | 1e-5, 1e-6, 1e-7, 1e-8, 1e-9, | |
173 | 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, | |
174 | 1e-15, 1e-16, 1e-17, 1e-18}; | |
175 | const struct lysc_type_dec *dectype; | |
176 | const struct lyd_value *dvalue; | |
1c2facd1 | 177 | |
3bb513c3 CH |
178 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); |
179 | dectype = (const struct lysc_type_dec *)dvalue->realtype; | |
180 | assert(dectype->basetype == LY_TYPE_DEC64); | |
181 | assert(dectype->fraction_digits < sizeof(denom) / sizeof(*denom)); | |
182 | return (double)dvalue->dec64 * denom[dectype->fraction_digits]; | |
1c2facd1 RW |
183 | } |
184 | ||
185 | double yang_get_default_dec64(const char *xpath_fmt, ...) | |
186 | { | |
187 | char xpath[XPATH_MAXLEN]; | |
188 | const char *value; | |
189 | va_list ap; | |
190 | ||
191 | va_start(ap, xpath_fmt); | |
192 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
193 | va_end(ap); | |
194 | ||
195 | value = yang_get_default_value(xpath); | |
196 | return yang_str2dec64(xpath, value); | |
197 | } | |
198 | ||
199 | /* | |
200 | * Primitive type: enum. | |
201 | */ | |
202 | int yang_str2enum(const char *xpath, const char *value) | |
203 | { | |
3bb513c3 CH |
204 | const struct lysc_node *snode; |
205 | const struct lysc_node_leaf *sleaf; | |
206 | const struct lysc_type_enum *type; | |
207 | const struct lysc_type_bitenum_item *enums; | |
1c2facd1 | 208 | |
3bb513c3 | 209 | snode = lys_find_path(ly_native_ctx, NULL, xpath, 0); |
1c2facd1 RW |
210 | if (snode == NULL) { |
211 | flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH, | |
212 | "%s: unknown data path: %s", __func__, xpath); | |
213 | zlog_backtrace(LOG_ERR); | |
214 | abort(); | |
215 | } | |
216 | ||
3bb513c3 CH |
217 | assert(snode->nodetype == LYS_LEAF); |
218 | sleaf = (const struct lysc_node_leaf *)snode; | |
219 | type = (const struct lysc_type_enum *)sleaf->type; | |
220 | assert(type->basetype == LY_TYPE_ENUM); | |
221 | enums = type->enums; | |
222 | unsigned int count = LY_ARRAY_COUNT(enums); | |
223 | for (unsigned int i = 0; i < count; i++) { | |
224 | if (strmatch(value, enums[i].name)) { | |
225 | assert(CHECK_FLAG(enums[i].flags, LYS_SET_VALUE)); | |
226 | return enums[i].value; | |
227 | } | |
1c2facd1 RW |
228 | } |
229 | ||
230 | flog_err(EC_LIB_YANG_DATA_CONVERT, | |
231 | "%s: couldn't convert string to enum [xpath %s]", __func__, | |
232 | xpath); | |
233 | zlog_backtrace(LOG_ERR); | |
234 | abort(); | |
235 | } | |
236 | ||
237 | struct yang_data *yang_data_new_enum(const char *xpath, int value) | |
238 | { | |
3bb513c3 CH |
239 | const struct lysc_node *snode; |
240 | const struct lysc_node_leaf *sleaf; | |
241 | const struct lysc_type_enum *type; | |
242 | const struct lysc_type_bitenum_item *enums; | |
1c2facd1 | 243 | |
3bb513c3 | 244 | snode = lys_find_path(ly_native_ctx, NULL, xpath, 0); |
1c2facd1 RW |
245 | if (snode == NULL) { |
246 | flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH, | |
247 | "%s: unknown data path: %s", __func__, xpath); | |
248 | zlog_backtrace(LOG_ERR); | |
249 | abort(); | |
250 | } | |
251 | ||
3bb513c3 CH |
252 | assert(snode->nodetype == LYS_LEAF); |
253 | sleaf = (const struct lysc_node_leaf *)snode; | |
254 | type = (const struct lysc_type_enum *)sleaf->type; | |
255 | assert(type->basetype == LY_TYPE_ENUM); | |
256 | enums = type->enums; | |
257 | unsigned int count = LY_ARRAY_COUNT(enums); | |
258 | for (unsigned int i = 0; i < count; i++) { | |
259 | if (CHECK_FLAG(enums[i].flags, LYS_SET_VALUE) | |
260 | && value == enums[i].value) | |
261 | return yang_data_new(xpath, enums[i].name); | |
1c2facd1 RW |
262 | } |
263 | ||
264 | flog_err(EC_LIB_YANG_DATA_CONVERT, | |
265 | "%s: couldn't convert enum to string [xpath %s]", __func__, | |
266 | xpath); | |
267 | zlog_backtrace(LOG_ERR); | |
268 | abort(); | |
269 | } | |
270 | ||
271 | int yang_dnode_get_enum(const struct lyd_node *dnode, const char *xpath_fmt, | |
272 | ...) | |
273 | { | |
3bb513c3 | 274 | const struct lyd_value *dvalue; |
1c2facd1 | 275 | |
3bb513c3 CH |
276 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); |
277 | assert(dvalue->realtype->basetype == LY_TYPE_ENUM); | |
278 | assert(dvalue->enum_item->flags & LYS_SET_VALUE); | |
279 | return dvalue->enum_item->value; | |
1c2facd1 RW |
280 | } |
281 | ||
282 | int yang_get_default_enum(const char *xpath_fmt, ...) | |
283 | { | |
284 | char xpath[XPATH_MAXLEN]; | |
285 | const char *value; | |
286 | va_list ap; | |
287 | ||
288 | va_start(ap, xpath_fmt); | |
289 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
290 | va_end(ap); | |
291 | ||
292 | value = yang_get_default_value(xpath); | |
293 | return yang_str2enum(xpath, value); | |
294 | } | |
295 | ||
296 | /* | |
297 | * Primitive type: int8. | |
298 | */ | |
299 | int8_t yang_str2int8(const char *value) | |
300 | { | |
301 | return strtol(value, NULL, 10); | |
302 | } | |
303 | ||
304 | struct yang_data *yang_data_new_int8(const char *xpath, int8_t value) | |
305 | { | |
306 | char value_str[BUFSIZ]; | |
307 | ||
308 | snprintf(value_str, sizeof(value_str), "%d", value); | |
309 | return yang_data_new(xpath, value_str); | |
310 | } | |
311 | ||
312 | int8_t yang_dnode_get_int8(const struct lyd_node *dnode, const char *xpath_fmt, | |
313 | ...) | |
314 | { | |
3bb513c3 CH |
315 | const struct lyd_value *dvalue; |
316 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); | |
317 | assert(dvalue->realtype->basetype == LY_TYPE_INT8); | |
318 | return dvalue->int8; | |
1c2facd1 RW |
319 | } |
320 | ||
321 | int8_t yang_get_default_int8(const char *xpath_fmt, ...) | |
322 | { | |
323 | char xpath[XPATH_MAXLEN]; | |
324 | const char *value; | |
325 | va_list ap; | |
326 | ||
327 | va_start(ap, xpath_fmt); | |
328 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
329 | va_end(ap); | |
330 | ||
331 | value = yang_get_default_value(xpath); | |
332 | return yang_str2int8(value); | |
333 | } | |
334 | ||
335 | /* | |
336 | * Primitive type: int16. | |
337 | */ | |
338 | int16_t yang_str2int16(const char *value) | |
339 | { | |
340 | return strtol(value, NULL, 10); | |
341 | } | |
342 | ||
343 | struct yang_data *yang_data_new_int16(const char *xpath, int16_t value) | |
344 | { | |
345 | char value_str[BUFSIZ]; | |
346 | ||
347 | snprintf(value_str, sizeof(value_str), "%d", value); | |
348 | return yang_data_new(xpath, value_str); | |
349 | } | |
350 | ||
351 | int16_t yang_dnode_get_int16(const struct lyd_node *dnode, | |
352 | const char *xpath_fmt, ...) | |
353 | { | |
3bb513c3 CH |
354 | const struct lyd_value *dvalue; |
355 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); | |
356 | assert(dvalue->realtype->basetype == LY_TYPE_INT16); | |
357 | return dvalue->int16; | |
1c2facd1 RW |
358 | } |
359 | ||
360 | int16_t yang_get_default_int16(const char *xpath_fmt, ...) | |
361 | { | |
362 | char xpath[XPATH_MAXLEN]; | |
363 | const char *value; | |
364 | va_list ap; | |
365 | ||
366 | va_start(ap, xpath_fmt); | |
367 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
368 | va_end(ap); | |
369 | ||
370 | value = yang_get_default_value(xpath); | |
371 | return yang_str2int16(value); | |
372 | } | |
373 | ||
374 | /* | |
375 | * Primitive type: int32. | |
376 | */ | |
377 | int32_t yang_str2int32(const char *value) | |
378 | { | |
379 | return strtol(value, NULL, 10); | |
380 | } | |
381 | ||
382 | struct yang_data *yang_data_new_int32(const char *xpath, int32_t value) | |
383 | { | |
384 | char value_str[BUFSIZ]; | |
385 | ||
386 | snprintf(value_str, sizeof(value_str), "%d", value); | |
387 | return yang_data_new(xpath, value_str); | |
388 | } | |
389 | ||
390 | int32_t yang_dnode_get_int32(const struct lyd_node *dnode, | |
391 | const char *xpath_fmt, ...) | |
392 | { | |
3bb513c3 CH |
393 | const struct lyd_value *dvalue; |
394 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); | |
395 | assert(dvalue->realtype->basetype == LY_TYPE_INT32); | |
396 | return dvalue->int32; | |
1c2facd1 RW |
397 | } |
398 | ||
399 | int32_t yang_get_default_int32(const char *xpath_fmt, ...) | |
400 | { | |
401 | char xpath[XPATH_MAXLEN]; | |
402 | const char *value; | |
403 | va_list ap; | |
404 | ||
405 | va_start(ap, xpath_fmt); | |
406 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
407 | va_end(ap); | |
408 | ||
409 | value = yang_get_default_value(xpath); | |
410 | return yang_str2int32(value); | |
411 | } | |
412 | ||
413 | /* | |
414 | * Primitive type: int64. | |
415 | */ | |
416 | int64_t yang_str2int64(const char *value) | |
417 | { | |
418 | return strtoll(value, NULL, 10); | |
419 | } | |
420 | ||
421 | struct yang_data *yang_data_new_int64(const char *xpath, int64_t value) | |
422 | { | |
423 | char value_str[BUFSIZ]; | |
424 | ||
566bdaf6 | 425 | snprintfrr(value_str, sizeof(value_str), "%" PRId64, value); |
1c2facd1 RW |
426 | return yang_data_new(xpath, value_str); |
427 | } | |
428 | ||
429 | int64_t yang_dnode_get_int64(const struct lyd_node *dnode, | |
430 | const char *xpath_fmt, ...) | |
431 | { | |
3bb513c3 CH |
432 | const struct lyd_value *dvalue; |
433 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); | |
434 | assert(dvalue->realtype->basetype == LY_TYPE_INT64); | |
435 | return dvalue->int64; | |
1c2facd1 RW |
436 | } |
437 | ||
438 | int64_t yang_get_default_int64(const char *xpath_fmt, ...) | |
439 | { | |
440 | char xpath[XPATH_MAXLEN]; | |
441 | const char *value; | |
442 | va_list ap; | |
443 | ||
444 | va_start(ap, xpath_fmt); | |
445 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
446 | va_end(ap); | |
447 | ||
448 | value = yang_get_default_value(xpath); | |
449 | return yang_str2int64(value); | |
450 | } | |
451 | ||
452 | /* | |
453 | * Primitive type: uint8. | |
454 | */ | |
455 | uint8_t yang_str2uint8(const char *value) | |
456 | { | |
457 | return strtoul(value, NULL, 10); | |
458 | } | |
459 | ||
460 | struct yang_data *yang_data_new_uint8(const char *xpath, uint8_t value) | |
461 | { | |
462 | char value_str[BUFSIZ]; | |
463 | ||
464 | snprintf(value_str, sizeof(value_str), "%u", value); | |
465 | return yang_data_new(xpath, value_str); | |
466 | } | |
467 | ||
468 | uint8_t yang_dnode_get_uint8(const struct lyd_node *dnode, | |
469 | const char *xpath_fmt, ...) | |
470 | { | |
3bb513c3 CH |
471 | const struct lyd_value *dvalue; |
472 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); | |
473 | assert(dvalue->realtype->basetype == LY_TYPE_UINT8); | |
474 | return dvalue->uint8; | |
1c2facd1 RW |
475 | } |
476 | ||
477 | uint8_t yang_get_default_uint8(const char *xpath_fmt, ...) | |
478 | { | |
479 | char xpath[XPATH_MAXLEN]; | |
480 | const char *value; | |
481 | va_list ap; | |
482 | ||
483 | va_start(ap, xpath_fmt); | |
484 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
485 | va_end(ap); | |
486 | ||
487 | value = yang_get_default_value(xpath); | |
488 | return yang_str2uint8(value); | |
489 | } | |
490 | ||
491 | /* | |
492 | * Primitive type: uint16. | |
493 | */ | |
494 | uint16_t yang_str2uint16(const char *value) | |
495 | { | |
496 | return strtoul(value, NULL, 10); | |
497 | } | |
498 | ||
499 | struct yang_data *yang_data_new_uint16(const char *xpath, uint16_t value) | |
500 | { | |
501 | char value_str[BUFSIZ]; | |
502 | ||
503 | snprintf(value_str, sizeof(value_str), "%u", value); | |
504 | return yang_data_new(xpath, value_str); | |
505 | } | |
506 | ||
507 | uint16_t yang_dnode_get_uint16(const struct lyd_node *dnode, | |
508 | const char *xpath_fmt, ...) | |
509 | { | |
3bb513c3 CH |
510 | const struct lyd_value *dvalue; |
511 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); | |
512 | assert(dvalue->realtype->basetype == LY_TYPE_UINT16); | |
513 | return dvalue->uint16; | |
1c2facd1 RW |
514 | } |
515 | ||
516 | uint16_t yang_get_default_uint16(const char *xpath_fmt, ...) | |
517 | { | |
518 | char xpath[XPATH_MAXLEN]; | |
519 | const char *value; | |
520 | va_list ap; | |
521 | ||
522 | va_start(ap, xpath_fmt); | |
523 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
524 | va_end(ap); | |
525 | ||
526 | value = yang_get_default_value(xpath); | |
527 | return yang_str2uint16(value); | |
528 | } | |
529 | ||
530 | /* | |
531 | * Primitive type: uint32. | |
532 | */ | |
533 | uint32_t yang_str2uint32(const char *value) | |
534 | { | |
535 | return strtoul(value, NULL, 10); | |
536 | } | |
537 | ||
538 | struct yang_data *yang_data_new_uint32(const char *xpath, uint32_t value) | |
539 | { | |
540 | char value_str[BUFSIZ]; | |
541 | ||
542 | snprintf(value_str, sizeof(value_str), "%u", value); | |
543 | return yang_data_new(xpath, value_str); | |
544 | } | |
545 | ||
546 | uint32_t yang_dnode_get_uint32(const struct lyd_node *dnode, | |
547 | const char *xpath_fmt, ...) | |
548 | { | |
3bb513c3 CH |
549 | const struct lyd_value *dvalue; |
550 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); | |
551 | assert(dvalue->realtype->basetype == LY_TYPE_UINT32); | |
552 | return dvalue->uint32; | |
1c2facd1 RW |
553 | } |
554 | ||
555 | uint32_t yang_get_default_uint32(const char *xpath_fmt, ...) | |
556 | { | |
557 | char xpath[XPATH_MAXLEN]; | |
558 | const char *value; | |
559 | va_list ap; | |
560 | ||
561 | va_start(ap, xpath_fmt); | |
562 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
563 | va_end(ap); | |
564 | ||
565 | value = yang_get_default_value(xpath); | |
566 | return yang_str2uint32(value); | |
567 | } | |
568 | ||
569 | /* | |
570 | * Primitive type: uint64. | |
571 | */ | |
572 | uint64_t yang_str2uint64(const char *value) | |
573 | { | |
574 | return strtoull(value, NULL, 10); | |
575 | } | |
576 | ||
577 | struct yang_data *yang_data_new_uint64(const char *xpath, uint64_t value) | |
578 | { | |
579 | char value_str[BUFSIZ]; | |
580 | ||
566bdaf6 | 581 | snprintfrr(value_str, sizeof(value_str), "%" PRIu64, value); |
1c2facd1 RW |
582 | return yang_data_new(xpath, value_str); |
583 | } | |
584 | ||
585 | uint64_t yang_dnode_get_uint64(const struct lyd_node *dnode, | |
586 | const char *xpath_fmt, ...) | |
587 | { | |
3bb513c3 CH |
588 | const struct lyd_value *dvalue; |
589 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); | |
590 | assert(dvalue->realtype->basetype == LY_TYPE_UINT64); | |
591 | return dvalue->uint64; | |
1c2facd1 RW |
592 | } |
593 | ||
594 | uint64_t yang_get_default_uint64(const char *xpath_fmt, ...) | |
595 | { | |
596 | char xpath[XPATH_MAXLEN]; | |
597 | const char *value; | |
598 | va_list ap; | |
599 | ||
600 | va_start(ap, xpath_fmt); | |
601 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
602 | va_end(ap); | |
603 | ||
604 | value = yang_get_default_value(xpath); | |
605 | return yang_str2uint64(value); | |
606 | } | |
607 | ||
608 | /* | |
609 | * Primitive type: string. | |
610 | * | |
611 | * All string wrappers can be used with non-string types. | |
612 | */ | |
613 | struct yang_data *yang_data_new_string(const char *xpath, const char *value) | |
614 | { | |
615 | return yang_data_new(xpath, value); | |
616 | } | |
617 | ||
618 | const char *yang_dnode_get_string(const struct lyd_node *dnode, | |
619 | const char *xpath_fmt, ...) | |
620 | { | |
3bb513c3 | 621 | return YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); |
1c2facd1 RW |
622 | } |
623 | ||
624 | void yang_dnode_get_string_buf(char *buf, size_t size, | |
625 | const struct lyd_node *dnode, | |
626 | const char *xpath_fmt, ...) | |
627 | { | |
3bb513c3 CH |
628 | const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); |
629 | if (strlcpy(buf, canon, size) >= size) { | |
1c2facd1 RW |
630 | char xpath[XPATH_MAXLEN]; |
631 | ||
632 | yang_dnode_get_path(dnode, xpath, sizeof(xpath)); | |
633 | flog_warn(EC_LIB_YANG_DATA_TRUNCATED, | |
634 | "%s: value was truncated [xpath %s]", __func__, | |
635 | xpath); | |
636 | } | |
637 | } | |
638 | ||
639 | const char *yang_get_default_string(const char *xpath_fmt, ...) | |
640 | { | |
641 | char xpath[XPATH_MAXLEN]; | |
642 | va_list ap; | |
643 | ||
644 | va_start(ap, xpath_fmt); | |
645 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
646 | va_end(ap); | |
647 | ||
648 | return yang_get_default_value(xpath); | |
649 | } | |
650 | ||
651 | void yang_get_default_string_buf(char *buf, size_t size, const char *xpath_fmt, | |
652 | ...) | |
653 | { | |
654 | char xpath[XPATH_MAXLEN]; | |
655 | const char *value; | |
656 | va_list ap; | |
657 | ||
658 | va_start(ap, xpath_fmt); | |
659 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
660 | va_end(ap); | |
661 | ||
662 | value = yang_get_default_value(xpath); | |
663 | if (strlcpy(buf, value, size) >= size) | |
664 | flog_warn(EC_LIB_YANG_DATA_TRUNCATED, | |
665 | "%s: value was truncated [xpath %s]", __func__, | |
666 | xpath); | |
667 | } | |
668 | ||
ac313345 | 669 | /* |
670 | * Primitive type: binary. | |
671 | */ | |
672 | struct yang_data *yang_data_new_binary(const char *xpath, const char *value, | |
673 | size_t len) | |
674 | { | |
675 | char *value_str; | |
676 | struct base64_encodestate s; | |
677 | int cnt; | |
678 | char *c; | |
679 | struct yang_data *data; | |
680 | ||
681 | value_str = (char *)malloc(len * 2); | |
682 | base64_init_encodestate(&s); | |
683 | cnt = base64_encode_block(value, len, value_str, &s); | |
684 | c = value_str + cnt; | |
685 | cnt = base64_encode_blockend(c, &s); | |
686 | c += cnt; | |
687 | *c = 0; | |
688 | data = yang_data_new(xpath, value_str); | |
689 | free(value_str); | |
690 | return data; | |
691 | } | |
692 | ||
693 | size_t yang_dnode_get_binary_buf(char *buf, size_t size, | |
694 | const struct lyd_node *dnode, | |
695 | const char *xpath_fmt, ...) | |
696 | { | |
697 | const char *canon; | |
698 | size_t cannon_len; | |
699 | size_t decode_len; | |
700 | size_t ret_len; | |
701 | size_t cnt; | |
702 | char *value_str; | |
703 | struct base64_decodestate s; | |
704 | ||
705 | canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); | |
706 | cannon_len = strlen(canon); | |
c4a97dc5 | 707 | decode_len = cannon_len + 1; |
ac313345 | 708 | value_str = (char *)malloc(decode_len); |
709 | base64_init_decodestate(&s); | |
710 | cnt = base64_decode_block(canon, cannon_len, value_str, &s); | |
711 | ||
712 | ret_len = size > cnt ? cnt : size; | |
713 | memcpy(buf, value_str, ret_len); | |
714 | if (size < cnt) { | |
715 | char xpath[XPATH_MAXLEN]; | |
716 | ||
717 | yang_dnode_get_path(dnode, xpath, sizeof(xpath)); | |
718 | flog_warn(EC_LIB_YANG_DATA_TRUNCATED, | |
719 | "%s: value was truncated [xpath %s]", __func__, | |
720 | xpath); | |
721 | } | |
722 | free(value_str); | |
723 | return ret_len; | |
724 | } | |
725 | ||
726 | ||
b71df689 CS |
727 | /* |
728 | * Primitive type: empty. | |
729 | */ | |
730 | struct yang_data *yang_data_new_empty(const char *xpath) | |
731 | { | |
732 | return yang_data_new(xpath, NULL); | |
733 | } | |
734 | ||
47cd2234 CS |
735 | bool yang_dnode_get_empty(const struct lyd_node *dnode, const char *xpath_fmt, |
736 | ...) | |
737 | { | |
738 | va_list ap; | |
739 | char xpath[XPATH_MAXLEN]; | |
3bb513c3 | 740 | const struct lyd_node_term *dleaf; |
47cd2234 CS |
741 | |
742 | assert(dnode); | |
743 | ||
744 | va_start(ap, xpath_fmt); | |
745 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
746 | va_end(ap); | |
747 | ||
748 | dnode = yang_dnode_get(dnode, xpath); | |
749 | if (dnode) { | |
3bb513c3 CH |
750 | dleaf = (const struct lyd_node_term *)dnode; |
751 | if (dleaf->value.realtype->basetype == LY_TYPE_EMPTY) | |
47cd2234 CS |
752 | return true; |
753 | } | |
754 | ||
755 | return false; | |
756 | } | |
757 | ||
eed84494 RW |
758 | /* |
759 | * Derived type: IP prefix. | |
760 | */ | |
761 | void yang_str2prefix(const char *value, union prefixptr prefix) | |
762 | { | |
763 | (void)str2prefix(value, prefix.p); | |
764 | apply_mask(prefix.p); | |
765 | } | |
766 | ||
767 | struct yang_data *yang_data_new_prefix(const char *xpath, | |
768 | union prefixconstptr prefix) | |
769 | { | |
770 | char value_str[PREFIX2STR_BUFFER]; | |
771 | ||
772 | (void)prefix2str(prefix.p, value_str, sizeof(value_str)); | |
773 | return yang_data_new(xpath, value_str); | |
774 | } | |
775 | ||
46fcb2df | 776 | void yang_dnode_get_prefix(struct prefix *prefix, const struct lyd_node *dnode, |
eed84494 RW |
777 | const char *xpath_fmt, ...) |
778 | { | |
3bb513c3 | 779 | const char *canon; |
46fcb2df RZ |
780 | /* |
781 | * Initialize prefix to avoid static analyzer complaints about | |
782 | * uninitialized memory. | |
783 | */ | |
784 | memset(prefix, 0, sizeof(*prefix)); | |
785 | ||
3bb513c3 CH |
786 | /* XXX ip_prefix is a native type now in ly2, leverage? */ |
787 | canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); | |
788 | (void)str2prefix(canon, prefix); | |
eed84494 RW |
789 | } |
790 | ||
791 | void yang_get_default_prefix(union prefixptr var, const char *xpath_fmt, ...) | |
792 | { | |
793 | char xpath[XPATH_MAXLEN]; | |
794 | const char *value; | |
795 | va_list ap; | |
796 | ||
797 | va_start(ap, xpath_fmt); | |
798 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
799 | va_end(ap); | |
800 | ||
801 | value = yang_get_default_value(xpath); | |
802 | yang_str2prefix(value, var); | |
803 | } | |
804 | ||
1c2facd1 RW |
805 | /* |
806 | * Derived type: ipv4. | |
807 | */ | |
808 | void yang_str2ipv4(const char *value, struct in_addr *addr) | |
809 | { | |
810 | (void)inet_pton(AF_INET, value, addr); | |
811 | } | |
812 | ||
813 | struct yang_data *yang_data_new_ipv4(const char *xpath, | |
814 | const struct in_addr *addr) | |
815 | { | |
816 | char value_str[INET_ADDRSTRLEN]; | |
817 | ||
818 | (void)inet_ntop(AF_INET, addr, value_str, sizeof(value_str)); | |
819 | return yang_data_new(xpath, value_str); | |
820 | } | |
821 | ||
822 | void yang_dnode_get_ipv4(struct in_addr *addr, const struct lyd_node *dnode, | |
823 | const char *xpath_fmt, ...) | |
824 | { | |
3bb513c3 CH |
825 | /* XXX libyang2 IPv4 address is a native type now in ly2 */ |
826 | const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); | |
827 | (void)inet_pton(AF_INET, canon, addr); | |
1c2facd1 RW |
828 | } |
829 | ||
830 | void yang_get_default_ipv4(struct in_addr *var, const char *xpath_fmt, ...) | |
831 | { | |
832 | char xpath[XPATH_MAXLEN]; | |
833 | const char *value; | |
834 | va_list ap; | |
835 | ||
836 | va_start(ap, xpath_fmt); | |
837 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
838 | va_end(ap); | |
839 | ||
840 | value = yang_get_default_value(xpath); | |
841 | yang_str2ipv4(value, var); | |
842 | } | |
843 | ||
844 | /* | |
845 | * Derived type: ipv4p. | |
846 | */ | |
847 | void yang_str2ipv4p(const char *value, union prefixptr prefix) | |
848 | { | |
849 | struct prefix_ipv4 *prefix4 = prefix.p4; | |
850 | ||
851 | (void)str2prefix_ipv4(value, prefix4); | |
852 | apply_mask_ipv4(prefix4); | |
853 | } | |
854 | ||
855 | struct yang_data *yang_data_new_ipv4p(const char *xpath, | |
70065793 | 856 | union prefixconstptr prefix) |
1c2facd1 RW |
857 | { |
858 | char value_str[PREFIX2STR_BUFFER]; | |
859 | ||
860 | (void)prefix2str(prefix.p, value_str, sizeof(value_str)); | |
861 | return yang_data_new(xpath, value_str); | |
862 | } | |
863 | ||
864 | void yang_dnode_get_ipv4p(union prefixptr prefix, const struct lyd_node *dnode, | |
865 | const char *xpath_fmt, ...) | |
866 | { | |
1c2facd1 | 867 | struct prefix_ipv4 *prefix4 = prefix.p4; |
3bb513c3 CH |
868 | /* XXX libyang2: ipv4/6 address is a native type now in ly2 */ |
869 | const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); | |
870 | (void)str2prefix_ipv4(canon, prefix4); | |
1c2facd1 RW |
871 | } |
872 | ||
873 | void yang_get_default_ipv4p(union prefixptr var, const char *xpath_fmt, ...) | |
874 | { | |
875 | char xpath[XPATH_MAXLEN]; | |
876 | const char *value; | |
877 | va_list ap; | |
878 | ||
879 | va_start(ap, xpath_fmt); | |
880 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
881 | va_end(ap); | |
882 | ||
883 | value = yang_get_default_value(xpath); | |
884 | yang_str2ipv4p(value, var); | |
885 | } | |
886 | ||
887 | /* | |
888 | * Derived type: ipv6. | |
889 | */ | |
890 | void yang_str2ipv6(const char *value, struct in6_addr *addr) | |
891 | { | |
892 | (void)inet_pton(AF_INET6, value, addr); | |
893 | } | |
894 | ||
895 | struct yang_data *yang_data_new_ipv6(const char *xpath, | |
896 | const struct in6_addr *addr) | |
897 | { | |
898 | char value_str[INET6_ADDRSTRLEN]; | |
899 | ||
900 | (void)inet_ntop(AF_INET6, addr, value_str, sizeof(value_str)); | |
901 | return yang_data_new(xpath, value_str); | |
902 | } | |
903 | ||
904 | void yang_dnode_get_ipv6(struct in6_addr *addr, const struct lyd_node *dnode, | |
905 | const char *xpath_fmt, ...) | |
906 | { | |
3bb513c3 CH |
907 | /* XXX libyang2: IPv6 address is a native type now, leverage. */ |
908 | const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); | |
909 | (void)inet_pton(AF_INET6, canon, addr); | |
1c2facd1 RW |
910 | } |
911 | ||
912 | void yang_get_default_ipv6(struct in6_addr *var, const char *xpath_fmt, ...) | |
913 | { | |
914 | char xpath[XPATH_MAXLEN]; | |
915 | const char *value; | |
916 | va_list ap; | |
917 | ||
918 | va_start(ap, xpath_fmt); | |
919 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
920 | va_end(ap); | |
921 | ||
922 | value = yang_get_default_value(xpath); | |
923 | yang_str2ipv6(value, var); | |
924 | } | |
925 | ||
926 | /* | |
927 | * Derived type: ipv6p. | |
928 | */ | |
929 | void yang_str2ipv6p(const char *value, union prefixptr prefix) | |
930 | { | |
931 | struct prefix_ipv6 *prefix6 = prefix.p6; | |
932 | ||
933 | (void)str2prefix_ipv6(value, prefix6); | |
934 | apply_mask_ipv6(prefix6); | |
935 | } | |
936 | ||
937 | struct yang_data *yang_data_new_ipv6p(const char *xpath, | |
70065793 | 938 | union prefixconstptr prefix) |
1c2facd1 RW |
939 | { |
940 | char value_str[PREFIX2STR_BUFFER]; | |
941 | ||
942 | (void)prefix2str(prefix.p, value_str, sizeof(value_str)); | |
943 | return yang_data_new(xpath, value_str); | |
944 | } | |
945 | ||
946 | void yang_dnode_get_ipv6p(union prefixptr prefix, const struct lyd_node *dnode, | |
947 | const char *xpath_fmt, ...) | |
948 | { | |
1c2facd1 RW |
949 | struct prefix_ipv6 *prefix6 = prefix.p6; |
950 | ||
3bb513c3 CH |
951 | /* XXX IPv6 address is a native type now in ly2 -- can we leverage? */ |
952 | const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); | |
953 | (void)str2prefix_ipv6(canon, prefix6); | |
1c2facd1 RW |
954 | } |
955 | ||
956 | void yang_get_default_ipv6p(union prefixptr var, const char *xpath_fmt, ...) | |
957 | { | |
958 | char xpath[XPATH_MAXLEN]; | |
959 | const char *value; | |
960 | va_list ap; | |
961 | ||
962 | va_start(ap, xpath_fmt); | |
963 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
964 | va_end(ap); | |
965 | ||
966 | value = yang_get_default_value(xpath); | |
967 | yang_str2ipv6p(value, var); | |
968 | } | |
b0584ad3 QY |
969 | |
970 | /* | |
971 | * Derived type: ip. | |
972 | */ | |
973 | void yang_str2ip(const char *value, struct ipaddr *ip) | |
974 | { | |
975 | (void)str2ipaddr(value, ip); | |
976 | } | |
977 | ||
978 | struct yang_data *yang_data_new_ip(const char *xpath, const struct ipaddr *addr) | |
979 | { | |
980 | size_t sz = IS_IPADDR_V4(addr) ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN; | |
981 | char value_str[sz]; | |
982 | ||
983 | ipaddr2str(addr, value_str, sizeof(value_str)); | |
984 | return yang_data_new(xpath, value_str); | |
985 | } | |
986 | ||
987 | void yang_dnode_get_ip(struct ipaddr *addr, const struct lyd_node *dnode, | |
988 | const char *xpath_fmt, ...) | |
989 | { | |
3bb513c3 CH |
990 | /* XXX IPv4 address could be a plugin type now in ly2, leverage? */ |
991 | const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); | |
992 | (void)str2ipaddr(canon, addr); | |
b0584ad3 QY |
993 | } |
994 | ||
995 | void yang_get_default_ip(struct ipaddr *var, const char *xpath_fmt, ...) | |
996 | { | |
997 | char xpath[XPATH_MAXLEN]; | |
998 | const char *value; | |
999 | va_list ap; | |
1000 | ||
1001 | va_start(ap, xpath_fmt); | |
1002 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); | |
1003 | va_end(ap); | |
1004 | ||
1005 | value = yang_get_default_value(xpath); | |
1006 | yang_str2ip(value, var); | |
1007 | } | |
dd9ef518 CS |
1008 | |
1009 | struct yang_data *yang_data_new_mac(const char *xpath, | |
1010 | const struct ethaddr *mac) | |
1011 | { | |
1012 | char value_str[ETHER_ADDR_STRLEN]; | |
1013 | ||
1014 | prefix_mac2str(mac, value_str, sizeof(value_str)); | |
1015 | return yang_data_new(xpath, value_str); | |
1016 | } | |
1017 | ||
1018 | void yang_str2mac(const char *value, struct ethaddr *mac) | |
1019 | { | |
bec74cc8 | 1020 | (void)prefix_str2mac(value, mac); |
dd9ef518 | 1021 | } |
cad46cfd | 1022 | |
8d0c8ff5 CS |
1023 | struct yang_data *yang_data_new_date_and_time(const char *xpath, time_t time) |
1024 | { | |
1025 | struct tm tm; | |
1026 | char timebuf[MONOTIME_STRLEN]; | |
1027 | struct timeval _time, time_real; | |
1028 | char *ts_dot; | |
1029 | uint16_t buflen; | |
1030 | ||
1031 | _time.tv_sec = time; | |
1032 | _time.tv_usec = 0; | |
1033 | monotime_to_realtime(&_time, &time_real); | |
1034 | ||
1035 | gmtime_r(&time_real.tv_sec, &tm); | |
1036 | ||
1037 | /* rfc-3339 format */ | |
1038 | strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%S", &tm); | |
1039 | buflen = strlen(timebuf); | |
1040 | ts_dot = timebuf + buflen; | |
1041 | ||
1042 | /* microseconds and appends Z */ | |
1043 | snprintfrr(ts_dot, sizeof(timebuf) - buflen, ".%06luZ", | |
1044 | (unsigned long)time_real.tv_usec); | |
1045 | ||
1046 | return yang_data_new(xpath, timebuf); | |
1047 | } | |
1048 | ||
cad46cfd CS |
1049 | const char *yang_nexthop_type2str(uint32_t ntype) |
1050 | { | |
1051 | switch (ntype) { | |
1052 | case NEXTHOP_TYPE_IFINDEX: | |
1053 | return "ifindex"; | |
1054 | break; | |
1055 | case NEXTHOP_TYPE_IPV4: | |
1056 | return "ip4"; | |
1057 | break; | |
1058 | case NEXTHOP_TYPE_IPV4_IFINDEX: | |
1059 | return "ip4-ifindex"; | |
1060 | break; | |
1061 | case NEXTHOP_TYPE_IPV6: | |
1062 | return "ip6"; | |
1063 | break; | |
1064 | case NEXTHOP_TYPE_IPV6_IFINDEX: | |
1065 | return "ip6-ifindex"; | |
1066 | break; | |
1067 | case NEXTHOP_TYPE_BLACKHOLE: | |
1068 | return "blackhole"; | |
1069 | break; | |
1070 | default: | |
1071 | return "unknown"; | |
1072 | break; | |
1073 | } | |
1074 | } | |
755100ac | 1075 | |
1076 | ||
1077 | const char *yang_afi_safi_value2identity(afi_t afi, safi_t safi) | |
1078 | { | |
1079 | if (afi == AFI_IP && safi == SAFI_UNICAST) | |
1080 | return "frr-routing:ipv4-unicast"; | |
1081 | if (afi == AFI_IP6 && safi == SAFI_UNICAST) | |
1082 | return "frr-routing:ipv6-unicast"; | |
1083 | if (afi == AFI_IP && safi == SAFI_MULTICAST) | |
1084 | return "frr-routing:ipv4-multicast"; | |
1085 | if (afi == AFI_IP6 && safi == SAFI_MULTICAST) | |
1086 | return "frr-routing:ipv6-multicast"; | |
532f9f17 CS |
1087 | if (afi == AFI_IP && safi == SAFI_MPLS_VPN) |
1088 | return "frr-routing:l3vpn-ipv4-unicast"; | |
1089 | if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN) | |
1090 | return "frr-routing:l3vpn-ipv6-unicast"; | |
1091 | if (afi == AFI_L2VPN && safi == SAFI_EVPN) | |
1092 | return "frr-routing:l2vpn-evpn"; | |
1093 | if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) | |
1094 | return "frr-routing:ipv4-labeled-unicast"; | |
1095 | if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) | |
1096 | return "frr-routing:ipv6-labeled-unicast"; | |
fbace230 CS |
1097 | if (afi == AFI_IP && safi == SAFI_FLOWSPEC) |
1098 | return "frr-routing:ipv4-flowspec"; | |
1099 | if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC) | |
1100 | return "frr-routing:ipv6-flowspec"; | |
755100ac | 1101 | |
1102 | return NULL; | |
1103 | } | |
1104 | ||
1105 | void yang_afi_safi_identity2value(const char *key, afi_t *afi, safi_t *safi) | |
1106 | { | |
1107 | if (strmatch(key, "frr-routing:ipv4-unicast")) { | |
1108 | *afi = AFI_IP; | |
1109 | *safi = SAFI_UNICAST; | |
1110 | } else if (strmatch(key, "frr-routing:ipv6-unicast")) { | |
1111 | *afi = AFI_IP6; | |
1112 | *safi = SAFI_UNICAST; | |
1113 | } else if (strmatch(key, "frr-routing:ipv4-multicast")) { | |
1114 | *afi = AFI_IP; | |
1115 | *safi = SAFI_MULTICAST; | |
1116 | } else if (strmatch(key, "frr-routing:ipv6-multicast")) { | |
1117 | *afi = AFI_IP6; | |
1118 | *safi = SAFI_MULTICAST; | |
532f9f17 CS |
1119 | } else if (strmatch(key, "frr-routing:l3vpn-ipv4-unicast")) { |
1120 | *afi = AFI_IP; | |
1121 | *safi = SAFI_MPLS_VPN; | |
1122 | } else if (strmatch(key, "frr-routing:l3vpn-ipv6-unicast")) { | |
1123 | *afi = AFI_IP6; | |
1124 | *safi = SAFI_MPLS_VPN; | |
1125 | } else if (strmatch(key, "frr-routing:ipv4-labeled-unicast")) { | |
1126 | *afi = AFI_IP; | |
1127 | *safi = SAFI_LABELED_UNICAST; | |
1128 | } else if (strmatch(key, "frr-routing:ipv6-labeled-unicast")) { | |
1129 | *afi = AFI_IP6; | |
1130 | *safi = SAFI_LABELED_UNICAST; | |
1131 | } else if (strmatch(key, "frr-routing:l2vpn-evpn")) { | |
1132 | *afi = AFI_L2VPN; | |
1133 | *safi = SAFI_EVPN; | |
fbace230 CS |
1134 | } else if (strmatch(key, "frr-routing:ipv4-flowspec")) { |
1135 | *afi = AFI_IP; | |
1136 | *safi = SAFI_FLOWSPEC; | |
1137 | } else if (strmatch(key, "frr-routing:ipv6-flowspec")) { | |
1138 | *afi = AFI_IP6; | |
1139 | *safi = SAFI_FLOWSPEC; | |
755100ac | 1140 | } else { |
1141 | *afi = AFI_UNSPEC; | |
1142 | *safi = SAFI_UNSPEC; | |
1143 | } | |
1144 | } |