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