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