]>
Commit | Line | Data |
---|---|---|
686d244f RZ |
1 | /* |
2 | * Route map northbound implementation. | |
3 | * | |
4 | * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF") | |
5 | * Rafael Zalamena | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
20 | * 02110-1301 USA. | |
21 | */ | |
22 | ||
23 | #include <zebra.h> | |
24 | ||
25 | #include "lib/command.h" | |
26 | #include "lib/log.h" | |
27 | #include "lib/northbound.h" | |
28 | #include "lib/routemap.h" | |
29 | ||
30 | /* | |
31 | * Auxiliary functions to avoid code duplication: | |
32 | * | |
33 | * lib_route_map_entry_set_destroy: unset `set` commands. | |
34 | * lib_route_map_entry_match_destroy: unset `match` commands. | |
35 | */ | |
60ee8be1 | 36 | int lib_route_map_entry_match_destroy(struct nb_cb_destroy_args *args) |
686d244f RZ |
37 | { |
38 | struct routemap_hook_context *rhc; | |
39 | int rv; | |
40 | ||
60ee8be1 | 41 | if (args->event != NB_EV_APPLY) |
686d244f RZ |
42 | return NB_OK; |
43 | ||
60ee8be1 | 44 | rhc = nb_running_get_entry(args->dnode, NULL, true); |
686d244f RZ |
45 | if (rhc->rhc_mhook == NULL) |
46 | return NB_OK; | |
47 | ||
48 | rv = rhc->rhc_mhook(NULL, rhc->rhc_rmi, rhc->rhc_rule, NULL, | |
49 | rhc->rhc_event); | |
50 | if (rv != CMD_SUCCESS) | |
51 | return NB_ERR_INCONSISTENCY; | |
52 | ||
53 | return NB_OK; | |
54 | } | |
55 | ||
60ee8be1 | 56 | int lib_route_map_entry_set_destroy(struct nb_cb_destroy_args *args) |
686d244f RZ |
57 | { |
58 | struct routemap_hook_context *rhc; | |
59 | int rv; | |
60 | ||
60ee8be1 | 61 | if (args->event != NB_EV_APPLY) |
686d244f RZ |
62 | return NB_OK; |
63 | ||
60ee8be1 | 64 | rhc = nb_running_get_entry(args->dnode, NULL, true); |
686d244f RZ |
65 | if (rhc->rhc_shook == NULL) |
66 | return NB_OK; | |
67 | ||
68 | rv = rhc->rhc_shook(NULL, rhc->rhc_rmi, rhc->rhc_rule, NULL); | |
69 | if (rv != CMD_SUCCESS) | |
70 | return NB_ERR_INCONSISTENCY; | |
71 | ||
72 | return NB_OK; | |
73 | } | |
74 | ||
54a35ff4 RZ |
75 | /* |
76 | * Auxiliary hook context list manipulation functions. | |
77 | */ | |
78 | struct routemap_hook_context * | |
79 | routemap_hook_context_insert(struct route_map_index *rmi) | |
80 | { | |
81 | struct routemap_hook_context *rhc; | |
82 | ||
83 | rhc = XCALLOC(MTYPE_TMP, sizeof(*rhc)); | |
84 | rhc->rhc_rmi = rmi; | |
85 | TAILQ_INSERT_TAIL(&rmi->rhclist, rhc, rhc_entry); | |
86 | ||
87 | return rhc; | |
88 | } | |
89 | ||
60ee8be1 | 90 | void routemap_hook_context_free(struct routemap_hook_context *rhc) |
54a35ff4 RZ |
91 | { |
92 | struct route_map_index *rmi = rhc->rhc_rmi; | |
93 | ||
94 | TAILQ_REMOVE(&rmi->rhclist, rhc, rhc_entry); | |
95 | XFREE(MTYPE_TMP, rhc); | |
96 | } | |
97 | ||
686d244f RZ |
98 | /* |
99 | * XPath: /frr-route-map:lib/route-map | |
100 | */ | |
60ee8be1 | 101 | static int lib_route_map_create(struct nb_cb_create_args *args) |
686d244f RZ |
102 | { |
103 | struct route_map *rm; | |
104 | const char *rm_name; | |
105 | ||
60ee8be1 | 106 | switch (args->event) { |
686d244f RZ |
107 | case NB_EV_VALIDATE: |
108 | case NB_EV_PREPARE: | |
109 | case NB_EV_ABORT: | |
110 | /* NOTHING */ | |
111 | break; | |
112 | case NB_EV_APPLY: | |
60ee8be1 | 113 | rm_name = yang_dnode_get_string(args->dnode, "./name"); |
686d244f | 114 | rm = route_map_get(rm_name); |
60ee8be1 | 115 | nb_running_set_entry(args->dnode, rm); |
686d244f RZ |
116 | break; |
117 | } | |
118 | ||
119 | return NB_OK; | |
120 | } | |
121 | ||
60ee8be1 | 122 | static int lib_route_map_destroy(struct nb_cb_destroy_args *args) |
686d244f RZ |
123 | { |
124 | struct route_map *rm; | |
125 | ||
60ee8be1 | 126 | switch (args->event) { |
686d244f RZ |
127 | case NB_EV_VALIDATE: |
128 | case NB_EV_PREPARE: | |
129 | case NB_EV_ABORT: | |
130 | /* NOTHING */ | |
131 | break; | |
132 | case NB_EV_APPLY: | |
60ee8be1 | 133 | rm = nb_running_unset_entry(args->dnode); |
686d244f RZ |
134 | route_map_delete(rm); |
135 | break; | |
136 | } | |
137 | ||
138 | return NB_OK; | |
139 | } | |
140 | ||
141 | /* | |
142 | * XPath: /frr-route-map:lib/route-map/entry | |
143 | */ | |
60ee8be1 | 144 | static int lib_route_map_entry_create(struct nb_cb_create_args *args) |
686d244f RZ |
145 | { |
146 | struct route_map_index *rmi; | |
147 | struct route_map *rm; | |
148 | uint16_t sequence; | |
149 | int action; | |
150 | ||
60ee8be1 | 151 | switch (args->event) { |
686d244f RZ |
152 | case NB_EV_VALIDATE: |
153 | case NB_EV_PREPARE: | |
154 | case NB_EV_ABORT: | |
155 | /* NOTHING */ | |
156 | break; | |
157 | case NB_EV_APPLY: | |
60ee8be1 RW |
158 | sequence = yang_dnode_get_uint16(args->dnode, "./sequence"); |
159 | action = yang_dnode_get_enum(args->dnode, "./action") == 0 | |
686d244f RZ |
160 | ? RMAP_PERMIT |
161 | : RMAP_DENY; | |
60ee8be1 | 162 | rm = nb_running_get_entry(args->dnode, NULL, true); |
686d244f | 163 | rmi = route_map_index_get(rm, action, sequence); |
60ee8be1 | 164 | nb_running_set_entry(args->dnode, rmi); |
686d244f RZ |
165 | break; |
166 | } | |
167 | ||
168 | return NB_OK; | |
169 | } | |
170 | ||
60ee8be1 | 171 | static int lib_route_map_entry_destroy(struct nb_cb_destroy_args *args) |
686d244f RZ |
172 | { |
173 | struct route_map_index *rmi; | |
174 | ||
60ee8be1 | 175 | switch (args->event) { |
686d244f RZ |
176 | case NB_EV_VALIDATE: |
177 | case NB_EV_PREPARE: | |
178 | case NB_EV_ABORT: | |
179 | /* NOTHING */ | |
180 | break; | |
181 | case NB_EV_APPLY: | |
60ee8be1 | 182 | rmi = nb_running_unset_entry(args->dnode); |
686d244f RZ |
183 | route_map_index_delete(rmi, 1); |
184 | break; | |
185 | } | |
186 | ||
187 | return NB_OK; | |
188 | } | |
189 | ||
190 | /* | |
191 | * XPath: /frr-route-map:lib/route-map/entry/description | |
192 | */ | |
60ee8be1 RW |
193 | static int |
194 | lib_route_map_entry_description_modify(struct nb_cb_modify_args *args) | |
686d244f RZ |
195 | { |
196 | struct route_map_index *rmi; | |
197 | const char *description; | |
198 | ||
60ee8be1 | 199 | switch (args->event) { |
686d244f RZ |
200 | case NB_EV_VALIDATE: |
201 | /* NOTHING */ | |
202 | break; | |
203 | case NB_EV_PREPARE: | |
60ee8be1 RW |
204 | description = yang_dnode_get_string(args->dnode, NULL); |
205 | args->resource->ptr = XSTRDUP(MTYPE_TMP, description); | |
206 | if (args->resource->ptr == NULL) | |
686d244f RZ |
207 | return NB_ERR_RESOURCE; |
208 | break; | |
209 | case NB_EV_ABORT: | |
60ee8be1 | 210 | XFREE(MTYPE_TMP, args->resource->ptr); |
686d244f RZ |
211 | break; |
212 | case NB_EV_APPLY: | |
60ee8be1 | 213 | rmi = nb_running_get_entry(args->dnode, NULL, true); |
5567e801 | 214 | XFREE(MTYPE_TMP, rmi->description); |
60ee8be1 | 215 | rmi->description = args->resource->ptr; |
686d244f RZ |
216 | break; |
217 | } | |
218 | ||
219 | return NB_OK; | |
220 | } | |
221 | ||
60ee8be1 RW |
222 | static int |
223 | lib_route_map_entry_description_destroy(struct nb_cb_destroy_args *args) | |
686d244f RZ |
224 | { |
225 | struct route_map_index *rmi; | |
226 | ||
60ee8be1 | 227 | switch (args->event) { |
686d244f RZ |
228 | case NB_EV_VALIDATE: |
229 | case NB_EV_PREPARE: | |
230 | case NB_EV_ABORT: | |
231 | /* NOTHING */ | |
232 | break; | |
233 | case NB_EV_APPLY: | |
60ee8be1 | 234 | rmi = nb_running_get_entry(args->dnode, NULL, true); |
ff51421e | 235 | XFREE(MTYPE_TMP, rmi->description); |
686d244f RZ |
236 | break; |
237 | } | |
238 | ||
239 | return NB_OK; | |
240 | } | |
241 | ||
242 | /* | |
243 | * XPath: /frr-route-map:lib/route-map/entry/action | |
244 | */ | |
60ee8be1 | 245 | static int lib_route_map_entry_action_modify(struct nb_cb_modify_args *args) |
686d244f RZ |
246 | { |
247 | struct route_map_index *rmi; | |
248 | ||
60ee8be1 | 249 | switch (args->event) { |
686d244f RZ |
250 | case NB_EV_VALIDATE: |
251 | case NB_EV_PREPARE: | |
252 | case NB_EV_ABORT: | |
253 | /* NOTHING */ | |
254 | break; | |
255 | case NB_EV_APPLY: | |
60ee8be1 RW |
256 | rmi = nb_running_get_entry(args->dnode, NULL, true); |
257 | rmi->type = yang_dnode_get_enum(args->dnode, NULL); | |
686d244f RZ |
258 | /* TODO: notify? */ |
259 | break; | |
260 | } | |
261 | ||
262 | return NB_OK; | |
263 | } | |
264 | ||
265 | /* | |
266 | * XPath: /frr-route-map:lib/route-map/entry/call | |
267 | */ | |
60ee8be1 | 268 | static int lib_route_map_entry_call_modify(struct nb_cb_modify_args *args) |
686d244f RZ |
269 | { |
270 | struct route_map_index *rmi; | |
271 | const char *rm_name, *rmn_name; | |
272 | ||
60ee8be1 | 273 | switch (args->event) { |
686d244f | 274 | case NB_EV_VALIDATE: |
60ee8be1 RW |
275 | rm_name = yang_dnode_get_string(args->dnode, "../../name"); |
276 | rmn_name = yang_dnode_get_string(args->dnode, NULL); | |
686d244f RZ |
277 | /* Don't allow to jump to the same route map instance. */ |
278 | if (strcmp(rm_name, rmn_name) == 0) | |
279 | return NB_ERR_VALIDATION; | |
280 | ||
281 | /* TODO: detect circular route map sequences. */ | |
282 | break; | |
283 | case NB_EV_PREPARE: | |
60ee8be1 RW |
284 | rmn_name = yang_dnode_get_string(args->dnode, NULL); |
285 | args->resource->ptr = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmn_name); | |
686d244f RZ |
286 | break; |
287 | case NB_EV_ABORT: | |
60ee8be1 | 288 | XFREE(MTYPE_ROUTE_MAP_NAME, args->resource->ptr); |
686d244f RZ |
289 | break; |
290 | case NB_EV_APPLY: | |
60ee8be1 | 291 | rmi = nb_running_get_entry(args->dnode, NULL, true); |
686d244f RZ |
292 | if (rmi->nextrm) { |
293 | route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED, | |
294 | rmi->nextrm, rmi->map->name); | |
295 | XFREE(MTYPE_ROUTE_MAP_NAME, rmi->nextrm); | |
296 | } | |
60ee8be1 | 297 | rmi->nextrm = args->resource->ptr; |
686d244f RZ |
298 | route_map_upd8_dependency(RMAP_EVENT_CALL_ADDED, rmi->nextrm, |
299 | rmi->map->name); | |
300 | break; | |
301 | } | |
302 | ||
303 | return NB_OK; | |
304 | } | |
305 | ||
60ee8be1 | 306 | static int lib_route_map_entry_call_destroy(struct nb_cb_destroy_args *args) |
686d244f RZ |
307 | { |
308 | struct route_map_index *rmi; | |
309 | ||
60ee8be1 | 310 | switch (args->event) { |
686d244f RZ |
311 | case NB_EV_VALIDATE: |
312 | case NB_EV_PREPARE: | |
313 | case NB_EV_ABORT: | |
314 | /* NOTHING */ | |
315 | break; | |
316 | case NB_EV_APPLY: | |
60ee8be1 | 317 | rmi = nb_running_get_entry(args->dnode, NULL, true); |
686d244f RZ |
318 | route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED, rmi->nextrm, |
319 | rmi->map->name); | |
320 | XFREE(MTYPE_ROUTE_MAP_NAME, rmi->nextrm); | |
321 | rmi->nextrm = NULL; | |
322 | break; | |
323 | } | |
324 | ||
325 | return NB_OK; | |
326 | } | |
327 | ||
328 | /* | |
329 | * XPath: /frr-route-map:lib/route-map/entry/exit-policy | |
330 | */ | |
60ee8be1 RW |
331 | static int |
332 | lib_route_map_entry_exit_policy_modify(struct nb_cb_modify_args *args) | |
686d244f RZ |
333 | { |
334 | struct route_map_index *rmi; | |
335 | int rm_action; | |
336 | int policy; | |
337 | ||
60ee8be1 | 338 | switch (args->event) { |
686d244f | 339 | case NB_EV_VALIDATE: |
60ee8be1 | 340 | policy = yang_dnode_get_enum(args->dnode, NULL); |
686d244f RZ |
341 | switch (policy) { |
342 | case 0: /* permit-or-deny */ | |
343 | break; | |
344 | case 1: /* next */ | |
345 | /* FALLTHROUGH */ | |
346 | case 2: /* goto */ | |
60ee8be1 RW |
347 | rm_action = |
348 | yang_dnode_get_enum(args->dnode, "../action"); | |
686d244f RZ |
349 | if (rm_action == 1 /* deny */) { |
350 | /* | |
351 | * On deny it is not possible to 'goto' | |
352 | * anywhere. | |
353 | */ | |
354 | return NB_ERR_VALIDATION; | |
355 | } | |
356 | break; | |
357 | } | |
358 | break; | |
359 | case NB_EV_PREPARE: | |
360 | case NB_EV_ABORT: | |
361 | break; | |
362 | case NB_EV_APPLY: | |
60ee8be1 RW |
363 | rmi = nb_running_get_entry(args->dnode, NULL, true); |
364 | policy = yang_dnode_get_enum(args->dnode, NULL); | |
686d244f RZ |
365 | |
366 | switch (policy) { | |
367 | case 0: /* permit-or-deny */ | |
368 | rmi->exitpolicy = RMAP_EXIT; | |
369 | break; | |
370 | case 1: /* next */ | |
371 | rmi->exitpolicy = RMAP_NEXT; | |
372 | break; | |
373 | case 2: /* goto */ | |
374 | rmi->exitpolicy = RMAP_GOTO; | |
375 | break; | |
376 | } | |
377 | break; | |
378 | } | |
379 | ||
380 | return NB_OK; | |
381 | } | |
382 | ||
383 | /* | |
384 | * XPath: /frr-route-map:lib/route-map/entry/goto-value | |
385 | */ | |
60ee8be1 | 386 | static int lib_route_map_entry_goto_value_modify(struct nb_cb_modify_args *args) |
686d244f RZ |
387 | { |
388 | struct route_map_index *rmi; | |
389 | uint16_t rmi_index; | |
390 | uint16_t rmi_next; | |
391 | ||
60ee8be1 | 392 | switch (args->event) { |
686d244f | 393 | case NB_EV_VALIDATE: |
60ee8be1 RW |
394 | rmi_index = yang_dnode_get_uint16(args->dnode, "../sequence"); |
395 | rmi_next = yang_dnode_get_uint16(args->dnode, NULL); | |
686d244f RZ |
396 | if (rmi_next <= rmi_index) { |
397 | /* Can't jump backwards on a route map. */ | |
398 | return NB_ERR_VALIDATION; | |
399 | } | |
400 | break; | |
401 | case NB_EV_PREPARE: | |
402 | case NB_EV_ABORT: | |
403 | /* NOTHING */ | |
404 | break; | |
405 | case NB_EV_APPLY: | |
60ee8be1 RW |
406 | rmi = nb_running_get_entry(args->dnode, NULL, true); |
407 | rmi->nextpref = yang_dnode_get_uint16(args->dnode, NULL); | |
686d244f RZ |
408 | break; |
409 | } | |
410 | ||
411 | return NB_OK; | |
412 | } | |
413 | ||
60ee8be1 RW |
414 | static int |
415 | lib_route_map_entry_goto_value_destroy(struct nb_cb_destroy_args *args) | |
686d244f RZ |
416 | { |
417 | struct route_map_index *rmi; | |
418 | ||
60ee8be1 | 419 | switch (args->event) { |
686d244f RZ |
420 | case NB_EV_VALIDATE: |
421 | case NB_EV_PREPARE: | |
422 | case NB_EV_ABORT: | |
423 | /* NOTHING */ | |
424 | break; | |
425 | case NB_EV_APPLY: | |
60ee8be1 | 426 | rmi = nb_running_get_entry(args->dnode, NULL, true); |
686d244f RZ |
427 | rmi->nextpref = 0; |
428 | break; | |
429 | } | |
430 | ||
431 | return NB_OK; | |
432 | } | |
433 | ||
434 | /* | |
435 | * XPath: /frr-route-map:lib/route-map/entry/match-condition | |
436 | */ | |
437 | static int | |
60ee8be1 | 438 | lib_route_map_entry_match_condition_create(struct nb_cb_create_args *args) |
686d244f RZ |
439 | { |
440 | struct routemap_hook_context *rhc; | |
54a35ff4 | 441 | struct route_map_index *rmi; |
686d244f | 442 | |
60ee8be1 | 443 | switch (args->event) { |
686d244f | 444 | case NB_EV_VALIDATE: |
686d244f | 445 | case NB_EV_PREPARE: |
686d244f | 446 | case NB_EV_ABORT: |
54a35ff4 | 447 | /* NOTHING */ |
686d244f RZ |
448 | break; |
449 | case NB_EV_APPLY: | |
60ee8be1 | 450 | rmi = nb_running_get_entry(args->dnode, NULL, true); |
54a35ff4 | 451 | rhc = routemap_hook_context_insert(rmi); |
60ee8be1 | 452 | nb_running_set_entry(args->dnode, rhc); |
686d244f RZ |
453 | break; |
454 | } | |
455 | ||
456 | return NB_OK; | |
457 | } | |
458 | ||
459 | static int | |
60ee8be1 | 460 | lib_route_map_entry_match_condition_destroy(struct nb_cb_destroy_args *args) |
686d244f RZ |
461 | { |
462 | struct routemap_hook_context *rhc; | |
463 | int rv; | |
464 | ||
60ee8be1 | 465 | if (args->event != NB_EV_APPLY) |
686d244f RZ |
466 | return NB_OK; |
467 | ||
60ee8be1 RW |
468 | rv = lib_route_map_entry_match_destroy(args); |
469 | rhc = nb_running_unset_entry(args->dnode); | |
54a35ff4 | 470 | routemap_hook_context_free(rhc); |
686d244f RZ |
471 | |
472 | return rv; | |
473 | } | |
474 | ||
475 | /* | |
476 | * XPath: /frr-route-map:lib/route-map/entry/match-condition/interface | |
477 | */ | |
478 | static int lib_route_map_entry_match_condition_interface_modify( | |
60ee8be1 | 479 | struct nb_cb_modify_args *args) |
686d244f RZ |
480 | { |
481 | struct routemap_hook_context *rhc; | |
482 | const char *ifname; | |
483 | int rv; | |
484 | ||
60ee8be1 | 485 | if (args->event != NB_EV_APPLY) |
686d244f RZ |
486 | return NB_OK; |
487 | ||
488 | /* Check for hook function. */ | |
489 | if (rmap_match_set_hook.match_interface == NULL) | |
490 | return NB_OK; | |
491 | ||
492 | /* Add configuration. */ | |
60ee8be1 RW |
493 | rhc = nb_running_get_entry(args->dnode, NULL, true); |
494 | ifname = yang_dnode_get_string(args->dnode, NULL); | |
686d244f RZ |
495 | |
496 | /* Set destroy information. */ | |
497 | rhc->rhc_mhook = rmap_match_set_hook.no_match_interface; | |
498 | rhc->rhc_rule = "interface"; | |
499 | rhc->rhc_event = RMAP_EVENT_MATCH_DELETED; | |
500 | ||
501 | rv = rmap_match_set_hook.match_interface(NULL, rhc->rhc_rmi, | |
502 | "interface", ifname, | |
503 | RMAP_EVENT_MATCH_ADDED); | |
504 | if (rv != CMD_SUCCESS) { | |
505 | rhc->rhc_mhook = NULL; | |
506 | return NB_ERR_INCONSISTENCY; | |
507 | } | |
508 | ||
509 | return NB_OK; | |
510 | } | |
511 | ||
512 | static int lib_route_map_entry_match_condition_interface_destroy( | |
60ee8be1 | 513 | struct nb_cb_destroy_args *args) |
686d244f | 514 | { |
60ee8be1 | 515 | return lib_route_map_entry_match_destroy(args); |
686d244f RZ |
516 | } |
517 | ||
686d244f RZ |
518 | /* |
519 | * XPath: /frr-route-map:lib/route-map/entry/match-condition/list-name | |
520 | */ | |
521 | static int lib_route_map_entry_match_condition_list_name_modify( | |
60ee8be1 | 522 | struct nb_cb_modify_args *args) |
686d244f RZ |
523 | { |
524 | struct routemap_hook_context *rhc; | |
525 | const char *acl; | |
526 | int condition; | |
527 | int rv; | |
528 | ||
60ee8be1 | 529 | if (args->event != NB_EV_APPLY) |
686d244f RZ |
530 | return NB_OK; |
531 | ||
532 | /* Check for hook installation, otherwise we can just stop. */ | |
60ee8be1 RW |
533 | acl = yang_dnode_get_string(args->dnode, NULL); |
534 | rhc = nb_running_get_entry(args->dnode, NULL, true); | |
535 | condition = yang_dnode_get_enum(args->dnode, "../condition"); | |
686d244f RZ |
536 | switch (condition) { |
537 | case 1: /* ipv4-address-list */ | |
538 | if (rmap_match_set_hook.match_ip_address == NULL) | |
539 | return NB_OK; | |
540 | rhc->rhc_mhook = rmap_match_set_hook.no_match_ip_address; | |
541 | rhc->rhc_rule = "ip address"; | |
542 | rhc->rhc_event = RMAP_EVENT_FILTER_DELETED; | |
543 | rv = rmap_match_set_hook.match_ip_address( | |
544 | NULL, rhc->rhc_rmi, "ip address", acl, | |
545 | RMAP_EVENT_FILTER_ADDED); | |
546 | break; | |
547 | case 2: /* ipv4-prefix-list */ | |
548 | if (rmap_match_set_hook.match_ip_address_prefix_list == NULL) | |
549 | return NB_OK; | |
550 | rhc->rhc_mhook = | |
551 | rmap_match_set_hook.no_match_ip_address_prefix_list; | |
552 | rhc->rhc_rule = "ip address prefix-list"; | |
553 | rhc->rhc_event = RMAP_EVENT_PLIST_DELETED; | |
554 | rv = rmap_match_set_hook.match_ip_address_prefix_list( | |
555 | NULL, rhc->rhc_rmi, "ip address prefix-list", acl, | |
556 | RMAP_EVENT_PLIST_ADDED); | |
557 | break; | |
558 | case 3: /* ipv4-next-hop-list */ | |
559 | if (rmap_match_set_hook.match_ip_next_hop == NULL) | |
560 | return NB_OK; | |
561 | rhc->rhc_mhook = rmap_match_set_hook.no_match_ip_next_hop; | |
562 | rhc->rhc_rule = "ip next-hop"; | |
563 | rhc->rhc_event = RMAP_EVENT_FILTER_DELETED; | |
564 | rv = rmap_match_set_hook.match_ip_next_hop( | |
565 | NULL, rhc->rhc_rmi, "ip next-hop", acl, | |
566 | RMAP_EVENT_FILTER_ADDED); | |
567 | break; | |
568 | case 4: /* ipv4-next-hop-prefix-list */ | |
569 | if (rmap_match_set_hook.match_ip_next_hop_prefix_list == NULL) | |
570 | return NB_OK; | |
571 | rhc->rhc_mhook = | |
572 | rmap_match_set_hook.no_match_ip_next_hop_prefix_list; | |
573 | rhc->rhc_rule = "ip next-hop prefix-list"; | |
574 | rhc->rhc_event = RMAP_EVENT_PLIST_DELETED; | |
575 | rv = rmap_match_set_hook.match_ip_next_hop_prefix_list( | |
576 | NULL, rhc->rhc_rmi, "ip next-hop prefix-list", acl, | |
577 | RMAP_EVENT_PLIST_ADDED); | |
578 | break; | |
579 | case 6: /* ipv6-address-list */ | |
580 | if (rmap_match_set_hook.match_ipv6_address == NULL) | |
581 | return NB_OK; | |
582 | rhc->rhc_mhook = rmap_match_set_hook.no_match_ipv6_address; | |
583 | rhc->rhc_rule = "ipv6 address"; | |
584 | rhc->rhc_event = RMAP_EVENT_FILTER_DELETED; | |
585 | rv = rmap_match_set_hook.match_ipv6_address( | |
586 | NULL, rhc->rhc_rmi, "ipv6 address", acl, | |
587 | RMAP_EVENT_FILTER_ADDED); | |
588 | break; | |
589 | case 7: /* ipv6-prefix-list */ | |
590 | if (rmap_match_set_hook.match_ipv6_address_prefix_list == NULL) | |
591 | return NB_OK; | |
592 | rhc->rhc_mhook = | |
593 | rmap_match_set_hook.no_match_ipv6_address_prefix_list; | |
594 | rhc->rhc_rule = "ipv6 address prefix-list"; | |
595 | rhc->rhc_event = RMAP_EVENT_PLIST_DELETED; | |
596 | rv = rmap_match_set_hook.match_ipv6_address_prefix_list( | |
597 | NULL, rhc->rhc_rmi, "ipv6 address prefix-list", acl, | |
598 | RMAP_EVENT_PLIST_ADDED); | |
599 | break; | |
600 | default: | |
601 | rv = CMD_ERR_NO_MATCH; | |
602 | break; | |
603 | } | |
604 | if (rv != CMD_SUCCESS) { | |
605 | rhc->rhc_mhook = NULL; | |
606 | return NB_ERR_INCONSISTENCY; | |
607 | } | |
608 | ||
609 | return NB_OK; | |
610 | } | |
611 | ||
612 | static int lib_route_map_entry_match_condition_list_name_destroy( | |
60ee8be1 | 613 | struct nb_cb_destroy_args *args) |
686d244f | 614 | { |
60ee8be1 | 615 | return lib_route_map_entry_match_destroy(args); |
686d244f RZ |
616 | } |
617 | ||
618 | /* | |
619 | * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv4-next-hop-type | |
620 | */ | |
621 | static int lib_route_map_entry_match_condition_ipv4_next_hop_type_modify( | |
60ee8be1 | 622 | struct nb_cb_modify_args *args) |
686d244f RZ |
623 | { |
624 | struct routemap_hook_context *rhc; | |
625 | const char *type; | |
626 | int rv; | |
627 | ||
60ee8be1 | 628 | if (args->event != NB_EV_APPLY) |
686d244f RZ |
629 | return NB_OK; |
630 | ||
631 | /* Check for hook function. */ | |
632 | if (rmap_match_set_hook.match_ip_next_hop_type == NULL) | |
633 | return NB_OK; | |
634 | ||
635 | /* Add configuration. */ | |
60ee8be1 RW |
636 | rhc = nb_running_get_entry(args->dnode, NULL, true); |
637 | type = yang_dnode_get_string(args->dnode, NULL); | |
686d244f RZ |
638 | |
639 | /* Set destroy information. */ | |
640 | rhc->rhc_mhook = rmap_match_set_hook.no_match_ip_next_hop_type; | |
641 | rhc->rhc_rule = "ip next-hop type"; | |
642 | rhc->rhc_event = RMAP_EVENT_MATCH_DELETED; | |
643 | ||
644 | rv = rmap_match_set_hook.match_ip_next_hop_type( | |
645 | NULL, rhc->rhc_rmi, "ip next-hop type", type, | |
646 | RMAP_EVENT_MATCH_ADDED); | |
647 | if (rv != CMD_SUCCESS) { | |
648 | rhc->rhc_mhook = NULL; | |
649 | return NB_ERR_INCONSISTENCY; | |
650 | } | |
651 | ||
652 | return NB_OK; | |
653 | } | |
654 | ||
655 | static int lib_route_map_entry_match_condition_ipv4_next_hop_type_destroy( | |
60ee8be1 | 656 | struct nb_cb_destroy_args *args) |
686d244f | 657 | { |
60ee8be1 | 658 | return lib_route_map_entry_match_destroy(args); |
686d244f RZ |
659 | } |
660 | ||
661 | /* | |
662 | * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv6-next-hop-type | |
663 | */ | |
664 | static int lib_route_map_entry_match_condition_ipv6_next_hop_type_modify( | |
60ee8be1 | 665 | struct nb_cb_modify_args *args) |
686d244f RZ |
666 | { |
667 | struct routemap_hook_context *rhc; | |
668 | const char *type; | |
669 | int rv; | |
670 | ||
60ee8be1 | 671 | if (args->event != NB_EV_APPLY) |
686d244f RZ |
672 | return NB_OK; |
673 | ||
674 | /* Check for hook function. */ | |
675 | if (rmap_match_set_hook.match_ipv6_next_hop_type == NULL) | |
676 | return NB_OK; | |
677 | ||
678 | /* Add configuration. */ | |
60ee8be1 RW |
679 | rhc = nb_running_get_entry(args->dnode, NULL, true); |
680 | type = yang_dnode_get_string(args->dnode, NULL); | |
686d244f RZ |
681 | |
682 | /* Set destroy information. */ | |
683 | rhc->rhc_mhook = rmap_match_set_hook.no_match_ipv6_next_hop_type; | |
684 | rhc->rhc_rule = "ipv6 next-hop type"; | |
685 | rhc->rhc_event = RMAP_EVENT_MATCH_DELETED; | |
686 | ||
687 | rv = rmap_match_set_hook.match_ipv6_next_hop_type( | |
688 | NULL, rhc->rhc_rmi, "ipv6 next-hop type", type, | |
689 | RMAP_EVENT_MATCH_ADDED); | |
690 | if (rv != CMD_SUCCESS) { | |
691 | rhc->rhc_mhook = NULL; | |
692 | return NB_ERR_INCONSISTENCY; | |
693 | } | |
694 | ||
695 | return NB_OK; | |
696 | } | |
697 | ||
698 | static int lib_route_map_entry_match_condition_ipv6_next_hop_type_destroy( | |
60ee8be1 | 699 | struct nb_cb_destroy_args *args) |
686d244f | 700 | { |
60ee8be1 | 701 | return lib_route_map_entry_match_destroy(args); |
686d244f RZ |
702 | } |
703 | ||
704 | /* | |
705 | * XPath: /frr-route-map:lib/route-map/entry/match-condition/metric | |
706 | */ | |
60ee8be1 RW |
707 | static int lib_route_map_entry_match_condition_metric_modify( |
708 | struct nb_cb_modify_args *args) | |
686d244f RZ |
709 | { |
710 | struct routemap_hook_context *rhc; | |
711 | const char *type; | |
712 | int rv; | |
713 | ||
60ee8be1 | 714 | if (args->event != NB_EV_APPLY) |
686d244f RZ |
715 | return NB_OK; |
716 | ||
717 | /* Check for hook function. */ | |
718 | if (rmap_match_set_hook.match_metric == NULL) | |
719 | return NB_OK; | |
720 | ||
721 | /* Add configuration. */ | |
60ee8be1 RW |
722 | rhc = nb_running_get_entry(args->dnode, NULL, true); |
723 | type = yang_dnode_get_string(args->dnode, NULL); | |
686d244f RZ |
724 | |
725 | /* Set destroy information. */ | |
726 | rhc->rhc_mhook = rmap_match_set_hook.no_match_metric; | |
727 | rhc->rhc_rule = "metric"; | |
728 | rhc->rhc_event = RMAP_EVENT_MATCH_DELETED; | |
729 | ||
730 | rv = rmap_match_set_hook.match_metric(NULL, rhc->rhc_rmi, "metric", | |
731 | type, RMAP_EVENT_MATCH_ADDED); | |
732 | if (rv != CMD_SUCCESS) { | |
733 | rhc->rhc_mhook = NULL; | |
734 | return NB_ERR_INCONSISTENCY; | |
735 | } | |
736 | ||
737 | return NB_OK; | |
738 | } | |
739 | ||
60ee8be1 RW |
740 | static int lib_route_map_entry_match_condition_metric_destroy( |
741 | struct nb_cb_destroy_args *args) | |
686d244f | 742 | { |
60ee8be1 | 743 | return lib_route_map_entry_match_destroy(args); |
686d244f RZ |
744 | } |
745 | ||
746 | /* | |
747 | * XPath: /frr-route-map:lib/route-map/entry/match-condition/tag | |
748 | */ | |
749 | static int | |
60ee8be1 | 750 | lib_route_map_entry_match_condition_tag_modify(struct nb_cb_modify_args *args) |
686d244f RZ |
751 | { |
752 | struct routemap_hook_context *rhc; | |
753 | const char *tag; | |
754 | int rv; | |
755 | ||
60ee8be1 | 756 | if (args->event != NB_EV_APPLY) |
686d244f RZ |
757 | return NB_OK; |
758 | ||
759 | /* Check for hook function. */ | |
760 | if (rmap_match_set_hook.match_tag == NULL) | |
761 | return NB_OK; | |
762 | ||
763 | /* Add configuration. */ | |
60ee8be1 RW |
764 | rhc = nb_running_get_entry(args->dnode, NULL, true); |
765 | tag = yang_dnode_get_string(args->dnode, NULL); | |
686d244f RZ |
766 | |
767 | /* Set destroy information. */ | |
768 | rhc->rhc_mhook = rmap_match_set_hook.no_match_tag; | |
769 | rhc->rhc_rule = "tag"; | |
770 | rhc->rhc_event = RMAP_EVENT_MATCH_DELETED; | |
771 | ||
772 | rv = rmap_match_set_hook.match_tag(NULL, rhc->rhc_rmi, "tag", tag, | |
773 | RMAP_EVENT_MATCH_ADDED); | |
774 | if (rv != CMD_SUCCESS) { | |
775 | rhc->rhc_mhook = NULL; | |
776 | return NB_ERR_INCONSISTENCY; | |
777 | } | |
778 | ||
779 | return NB_OK; | |
780 | } | |
781 | ||
782 | static int | |
60ee8be1 | 783 | lib_route_map_entry_match_condition_tag_destroy(struct nb_cb_destroy_args *args) |
686d244f | 784 | { |
60ee8be1 | 785 | return lib_route_map_entry_match_destroy(args); |
686d244f RZ |
786 | } |
787 | ||
788 | /* | |
789 | * XPath: /frr-route-map:lib/route-map/entry/set-action | |
790 | */ | |
60ee8be1 | 791 | static int lib_route_map_entry_set_action_create(struct nb_cb_create_args *args) |
686d244f | 792 | { |
60ee8be1 | 793 | return lib_route_map_entry_match_condition_create(args); |
686d244f RZ |
794 | } |
795 | ||
60ee8be1 RW |
796 | static int |
797 | lib_route_map_entry_set_action_destroy(struct nb_cb_destroy_args *args) | |
686d244f RZ |
798 | { |
799 | struct routemap_hook_context *rhc; | |
800 | int rv; | |
801 | ||
60ee8be1 | 802 | if (args->event != NB_EV_APPLY) |
686d244f RZ |
803 | return NB_OK; |
804 | ||
60ee8be1 RW |
805 | rv = lib_route_map_entry_set_destroy(args); |
806 | rhc = nb_running_unset_entry(args->dnode); | |
54a35ff4 | 807 | routemap_hook_context_free(rhc); |
686d244f RZ |
808 | |
809 | return rv; | |
810 | } | |
811 | ||
812 | /* | |
813 | * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv4-address | |
814 | */ | |
60ee8be1 RW |
815 | static int lib_route_map_entry_set_action_ipv4_address_modify( |
816 | struct nb_cb_modify_args *args) | |
686d244f RZ |
817 | { |
818 | struct routemap_hook_context *rhc; | |
819 | const char *address; | |
820 | struct in_addr ia; | |
821 | int rv; | |
822 | ||
60ee8be1 | 823 | switch (args->event) { |
686d244f RZ |
824 | case NB_EV_VALIDATE: |
825 | /* | |
826 | * NOTE: validate if 'action' is 'ipv4-next-hop', | |
827 | * currently it is not necessary because this is the | |
828 | * only implemented action. | |
829 | */ | |
60ee8be1 | 830 | yang_dnode_get_ipv4(&ia, args->dnode, NULL); |
975a328e | 831 | if (ia.s_addr == INADDR_ANY || IPV4_CLASS_DE(ntohl(ia.s_addr))) |
686d244f RZ |
832 | return NB_ERR_VALIDATION; |
833 | /* FALLTHROUGH */ | |
834 | case NB_EV_PREPARE: | |
835 | case NB_EV_ABORT: | |
836 | return NB_OK; | |
837 | case NB_EV_APPLY: | |
838 | break; | |
839 | } | |
840 | ||
841 | /* Check for hook function. */ | |
842 | if (rmap_match_set_hook.set_ip_nexthop == NULL) | |
843 | return NB_OK; | |
844 | ||
845 | /* Add configuration. */ | |
60ee8be1 RW |
846 | rhc = nb_running_get_entry(args->dnode, NULL, true); |
847 | address = yang_dnode_get_string(args->dnode, NULL); | |
686d244f RZ |
848 | |
849 | /* Set destroy information. */ | |
850 | rhc->rhc_shook = rmap_match_set_hook.no_set_ip_nexthop; | |
851 | rhc->rhc_rule = "ip next-hop"; | |
852 | ||
853 | rv = rmap_match_set_hook.set_ip_nexthop(NULL, rhc->rhc_rmi, | |
854 | "ip next-hop", address); | |
855 | if (rv != CMD_SUCCESS) { | |
856 | rhc->rhc_shook = NULL; | |
857 | return NB_ERR_INCONSISTENCY; | |
858 | } | |
859 | ||
860 | return NB_OK; | |
861 | } | |
862 | ||
863 | static int lib_route_map_entry_set_action_ipv4_address_destroy( | |
60ee8be1 | 864 | struct nb_cb_destroy_args *args) |
686d244f | 865 | { |
60ee8be1 | 866 | return lib_route_map_entry_set_destroy(args); |
686d244f RZ |
867 | } |
868 | ||
869 | /* | |
870 | * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv6-address | |
871 | */ | |
60ee8be1 RW |
872 | static int lib_route_map_entry_set_action_ipv6_address_modify( |
873 | struct nb_cb_modify_args *args) | |
686d244f RZ |
874 | { |
875 | struct routemap_hook_context *rhc; | |
876 | const char *address; | |
877 | struct in6_addr i6a; | |
878 | int rv; | |
879 | ||
60ee8be1 | 880 | switch (args->event) { |
686d244f RZ |
881 | case NB_EV_VALIDATE: |
882 | /* | |
883 | * NOTE: validate if 'action' is 'ipv6-next-hop', | |
884 | * currently it is not necessary because this is the | |
885 | * only implemented action. Other actions might have | |
886 | * different validations. | |
887 | */ | |
60ee8be1 | 888 | yang_dnode_get_ipv6(&i6a, args->dnode, NULL); |
686d244f RZ |
889 | if (!IN6_IS_ADDR_LINKLOCAL(&i6a)) |
890 | return NB_ERR_VALIDATION; | |
891 | /* FALLTHROUGH */ | |
892 | case NB_EV_PREPARE: | |
893 | case NB_EV_ABORT: | |
894 | return NB_OK; | |
895 | case NB_EV_APPLY: | |
896 | break; | |
897 | } | |
898 | ||
899 | /* Check for hook function. */ | |
900 | if (rmap_match_set_hook.set_ipv6_nexthop_local == NULL) | |
901 | return NB_OK; | |
902 | ||
903 | /* Add configuration. */ | |
60ee8be1 RW |
904 | rhc = nb_running_get_entry(args->dnode, NULL, true); |
905 | address = yang_dnode_get_string(args->dnode, NULL); | |
686d244f RZ |
906 | |
907 | /* Set destroy information. */ | |
908 | rhc->rhc_shook = rmap_match_set_hook.no_set_ipv6_nexthop_local; | |
909 | rhc->rhc_rule = "ipv6 next-hop local"; | |
910 | ||
911 | rv = rmap_match_set_hook.set_ipv6_nexthop_local( | |
912 | NULL, rhc->rhc_rmi, "ipv6 next-hop local", address); | |
913 | if (rv != CMD_SUCCESS) { | |
914 | rhc->rhc_shook = NULL; | |
915 | return NB_ERR_INCONSISTENCY; | |
916 | } | |
917 | ||
918 | return NB_OK; | |
919 | } | |
920 | ||
921 | static int lib_route_map_entry_set_action_ipv6_address_destroy( | |
60ee8be1 | 922 | struct nb_cb_destroy_args *args) |
686d244f | 923 | { |
60ee8be1 | 924 | return lib_route_map_entry_set_destroy(args); |
686d244f RZ |
925 | } |
926 | ||
927 | /* | |
928 | * XPath: /frr-route-map:lib/route-map/entry/set-action/value | |
929 | */ | |
930 | static int set_action_modify(enum nb_event event, const struct lyd_node *dnode, | |
931 | union nb_resource *resource, const char *value) | |
932 | { | |
933 | struct routemap_hook_context *rhc; | |
934 | int rv; | |
935 | ||
936 | /* | |
937 | * NOTE: validate if 'action' is 'metric', currently it is not | |
938 | * necessary because this is the only implemented action. Other | |
939 | * actions might have different validations. | |
940 | */ | |
941 | if (event != NB_EV_APPLY) | |
942 | return NB_OK; | |
943 | ||
944 | /* Check for hook function. */ | |
945 | if (rmap_match_set_hook.set_metric == NULL) | |
946 | return NB_OK; | |
947 | ||
948 | /* Add configuration. */ | |
949 | rhc = nb_running_get_entry(dnode, NULL, true); | |
950 | ||
951 | /* Set destroy information. */ | |
952 | rhc->rhc_shook = rmap_match_set_hook.no_set_metric; | |
953 | rhc->rhc_rule = "metric"; | |
954 | ||
955 | rv = rmap_match_set_hook.set_metric(NULL, rhc->rhc_rmi, "metric", | |
956 | value); | |
957 | if (rv != CMD_SUCCESS) { | |
958 | rhc->rhc_shook = NULL; | |
959 | return NB_ERR_INCONSISTENCY; | |
960 | } | |
961 | ||
962 | return NB_OK; | |
963 | } | |
964 | ||
965 | static int | |
60ee8be1 | 966 | lib_route_map_entry_set_action_value_modify(struct nb_cb_modify_args *args) |
686d244f | 967 | { |
60ee8be1 | 968 | const char *metric = yang_dnode_get_string(args->dnode, NULL); |
686d244f | 969 | |
60ee8be1 RW |
970 | return set_action_modify(args->event, args->dnode, args->resource, |
971 | metric); | |
686d244f RZ |
972 | } |
973 | ||
974 | static int | |
60ee8be1 | 975 | lib_route_map_entry_set_action_value_destroy(struct nb_cb_destroy_args *args) |
686d244f | 976 | { |
60ee8be1 | 977 | return lib_route_map_entry_set_destroy(args); |
686d244f RZ |
978 | } |
979 | ||
980 | /* | |
981 | * XPath: /frr-route-map:lib/route-map/entry/set-action/add-metric | |
982 | */ | |
983 | static int | |
60ee8be1 | 984 | lib_route_map_entry_set_action_add_metric_modify(struct nb_cb_modify_args *args) |
686d244f | 985 | { |
add39cde RW |
986 | char metric_str[16]; |
987 | ||
988 | if (args->event == NB_EV_VALIDATE | |
989 | && yang_dnode_get_uint32(args->dnode, NULL) == 0) { | |
990 | snprintf(args->errmsg, args->errmsg_len, | |
991 | "Can't add zero to metric"); | |
992 | return NB_ERR_VALIDATION; | |
993 | } | |
994 | ||
995 | snprintf(metric_str, sizeof(metric_str), "+%s", | |
996 | yang_dnode_get_string(args->dnode, NULL)); | |
60ee8be1 | 997 | return set_action_modify(args->event, args->dnode, args->resource, |
add39cde | 998 | metric_str); |
686d244f RZ |
999 | } |
1000 | ||
60ee8be1 RW |
1001 | static int lib_route_map_entry_set_action_add_metric_destroy( |
1002 | struct nb_cb_destroy_args *args) | |
686d244f | 1003 | { |
60ee8be1 | 1004 | return lib_route_map_entry_set_action_value_destroy(args); |
686d244f RZ |
1005 | } |
1006 | ||
1007 | /* | |
1008 | * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-metric | |
1009 | */ | |
1010 | static int lib_route_map_entry_set_action_subtract_metric_modify( | |
60ee8be1 | 1011 | struct nb_cb_modify_args *args) |
686d244f | 1012 | { |
add39cde RW |
1013 | char metric_str[16]; |
1014 | ||
1015 | if (args->event == NB_EV_VALIDATE | |
1016 | && yang_dnode_get_uint32(args->dnode, NULL) == 0) { | |
1017 | snprintf(args->errmsg, args->errmsg_len, | |
1018 | "Can't subtract zero from metric"); | |
1019 | return NB_ERR_VALIDATION; | |
1020 | } | |
1021 | ||
1022 | snprintf(metric_str, sizeof(metric_str), "-%s", | |
1023 | yang_dnode_get_string(args->dnode, NULL)); | |
60ee8be1 | 1024 | return set_action_modify(args->event, args->dnode, args->resource, |
add39cde | 1025 | metric_str); |
686d244f RZ |
1026 | } |
1027 | ||
1028 | static int lib_route_map_entry_set_action_subtract_metric_destroy( | |
60ee8be1 | 1029 | struct nb_cb_destroy_args *args) |
686d244f | 1030 | { |
60ee8be1 | 1031 | return lib_route_map_entry_set_action_value_destroy(args); |
686d244f RZ |
1032 | } |
1033 | ||
1034 | /* | |
1035 | * XPath: /frr-route-map:lib/route-map/entry/set-action/use-round-trip-time | |
1036 | */ | |
1037 | static int lib_route_map_entry_set_action_use_round_trip_time_modify( | |
60ee8be1 | 1038 | struct nb_cb_modify_args *args) |
686d244f | 1039 | { |
60ee8be1 RW |
1040 | return set_action_modify(args->event, args->dnode, args->resource, |
1041 | "rtt"); | |
686d244f RZ |
1042 | } |
1043 | ||
1044 | static int lib_route_map_entry_set_action_use_round_trip_time_destroy( | |
60ee8be1 | 1045 | struct nb_cb_destroy_args *args) |
686d244f | 1046 | { |
60ee8be1 | 1047 | return lib_route_map_entry_set_action_value_destroy(args); |
686d244f RZ |
1048 | } |
1049 | ||
1050 | /* | |
1051 | * XPath: /frr-route-map:lib/route-map/entry/set-action/add-round-trip-time | |
1052 | */ | |
1053 | static int lib_route_map_entry_set_action_add_round_trip_time_modify( | |
60ee8be1 | 1054 | struct nb_cb_modify_args *args) |
686d244f | 1055 | { |
60ee8be1 RW |
1056 | return set_action_modify(args->event, args->dnode, args->resource, |
1057 | "+rtt"); | |
686d244f RZ |
1058 | } |
1059 | ||
1060 | static int lib_route_map_entry_set_action_add_round_trip_time_destroy( | |
60ee8be1 | 1061 | struct nb_cb_destroy_args *args) |
686d244f | 1062 | { |
60ee8be1 | 1063 | return lib_route_map_entry_set_action_value_destroy(args); |
686d244f RZ |
1064 | } |
1065 | ||
1066 | /* | |
1067 | * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-round-trip-time | |
1068 | */ | |
1069 | static int lib_route_map_entry_set_action_subtract_round_trip_time_modify( | |
60ee8be1 | 1070 | struct nb_cb_modify_args *args) |
686d244f | 1071 | { |
60ee8be1 RW |
1072 | return set_action_modify(args->event, args->dnode, args->resource, |
1073 | "-rtt"); | |
686d244f RZ |
1074 | } |
1075 | ||
1076 | static int lib_route_map_entry_set_action_subtract_round_trip_time_destroy( | |
60ee8be1 | 1077 | struct nb_cb_destroy_args *args) |
686d244f | 1078 | { |
60ee8be1 | 1079 | return lib_route_map_entry_set_action_value_destroy(args); |
686d244f RZ |
1080 | } |
1081 | ||
1082 | /* | |
1083 | * XPath: /frr-route-map:lib/route-map/entry/set-action/tag | |
1084 | */ | |
1085 | static int | |
60ee8be1 | 1086 | lib_route_map_entry_set_action_tag_modify(struct nb_cb_modify_args *args) |
686d244f RZ |
1087 | { |
1088 | struct routemap_hook_context *rhc; | |
1089 | const char *tag; | |
1090 | int rv; | |
1091 | ||
1092 | /* | |
1093 | * NOTE: validate if 'action' is 'tag', currently it is not | |
1094 | * necessary because this is the only implemented action. Other | |
1095 | * actions might have different validations. | |
1096 | */ | |
60ee8be1 | 1097 | if (args->event != NB_EV_APPLY) |
686d244f RZ |
1098 | return NB_OK; |
1099 | ||
1100 | /* Check for hook function. */ | |
1101 | if (rmap_match_set_hook.set_tag == NULL) | |
1102 | return NB_OK; | |
1103 | ||
1104 | /* Add configuration. */ | |
60ee8be1 RW |
1105 | rhc = nb_running_get_entry(args->dnode, NULL, true); |
1106 | tag = yang_dnode_get_string(args->dnode, NULL); | |
686d244f RZ |
1107 | |
1108 | /* Set destroy information. */ | |
1109 | rhc->rhc_shook = rmap_match_set_hook.no_set_tag; | |
1110 | rhc->rhc_rule = "tag"; | |
1111 | ||
1112 | rv = rmap_match_set_hook.set_tag(NULL, rhc->rhc_rmi, "tag", tag); | |
1113 | if (rv != CMD_SUCCESS) { | |
1114 | rhc->rhc_shook = NULL; | |
1115 | return NB_ERR_INCONSISTENCY; | |
1116 | } | |
1117 | ||
1118 | return NB_OK; | |
1119 | } | |
1120 | ||
1121 | static int | |
60ee8be1 | 1122 | lib_route_map_entry_set_action_tag_destroy(struct nb_cb_destroy_args *args) |
686d244f | 1123 | { |
60ee8be1 | 1124 | return lib_route_map_entry_set_destroy(args); |
686d244f RZ |
1125 | } |
1126 | ||
1127 | /* clang-format off */ | |
1128 | const struct frr_yang_module_info frr_route_map_info = { | |
1129 | .name = "frr-route-map", | |
1130 | .nodes = { | |
1131 | { | |
1132 | .xpath = "/frr-route-map:lib/route-map", | |
1133 | .cbs = { | |
1134 | .create = lib_route_map_create, | |
1135 | .destroy = lib_route_map_destroy, | |
1136 | } | |
1137 | }, | |
1138 | { | |
1139 | .xpath = "/frr-route-map:lib/route-map/entry", | |
1140 | .cbs = { | |
1141 | .create = lib_route_map_entry_create, | |
1142 | .destroy = lib_route_map_entry_destroy, | |
de8936be | 1143 | .cli_cmp = route_map_instance_cmp, |
2b3e4807 RZ |
1144 | .cli_show = route_map_instance_show, |
1145 | .cli_show_end = route_map_instance_show_end, | |
686d244f RZ |
1146 | } |
1147 | }, | |
1148 | { | |
1149 | .xpath = "/frr-route-map:lib/route-map/entry/description", | |
1150 | .cbs = { | |
1151 | .modify = lib_route_map_entry_description_modify, | |
1152 | .destroy = lib_route_map_entry_description_destroy, | |
2b3e4807 | 1153 | .cli_show = route_map_description_show, |
686d244f RZ |
1154 | } |
1155 | }, | |
1156 | { | |
1157 | .xpath = "/frr-route-map:lib/route-map/entry/action", | |
1158 | .cbs = { | |
1159 | .modify = lib_route_map_entry_action_modify, | |
1160 | } | |
1161 | }, | |
1162 | { | |
1163 | .xpath = "/frr-route-map:lib/route-map/entry/call", | |
1164 | .cbs = { | |
1165 | .modify = lib_route_map_entry_call_modify, | |
1166 | .destroy = lib_route_map_entry_call_destroy, | |
2b3e4807 | 1167 | .cli_show = route_map_call_show, |
686d244f RZ |
1168 | } |
1169 | }, | |
1170 | { | |
1171 | .xpath = "/frr-route-map:lib/route-map/entry/exit-policy", | |
1172 | .cbs = { | |
1173 | .modify = lib_route_map_entry_exit_policy_modify, | |
2b3e4807 | 1174 | .cli_show = route_map_exit_policy_show, |
686d244f RZ |
1175 | } |
1176 | }, | |
1177 | { | |
1178 | .xpath = "/frr-route-map:lib/route-map/entry/goto-value", | |
1179 | .cbs = { | |
1180 | .modify = lib_route_map_entry_goto_value_modify, | |
1181 | .destroy = lib_route_map_entry_goto_value_destroy, | |
1182 | } | |
1183 | }, | |
1184 | { | |
1185 | .xpath = "/frr-route-map:lib/route-map/entry/match-condition", | |
1186 | .cbs = { | |
1187 | .create = lib_route_map_entry_match_condition_create, | |
1188 | .destroy = lib_route_map_entry_match_condition_destroy, | |
2b3e4807 | 1189 | .cli_show = route_map_condition_show, |
686d244f RZ |
1190 | } |
1191 | }, | |
1192 | { | |
1193 | .xpath = "/frr-route-map:lib/route-map/entry/match-condition/interface", | |
1194 | .cbs = { | |
1195 | .modify = lib_route_map_entry_match_condition_interface_modify, | |
1196 | .destroy = lib_route_map_entry_match_condition_interface_destroy, | |
1197 | } | |
1198 | }, | |
686d244f RZ |
1199 | { |
1200 | .xpath = "/frr-route-map:lib/route-map/entry/match-condition/list-name", | |
1201 | .cbs = { | |
1202 | .modify = lib_route_map_entry_match_condition_list_name_modify, | |
1203 | .destroy = lib_route_map_entry_match_condition_list_name_destroy, | |
1204 | } | |
1205 | }, | |
1206 | { | |
1207 | .xpath = "/frr-route-map:lib/route-map/entry/match-condition/ipv4-next-hop-type", | |
1208 | .cbs = { | |
1209 | .modify = lib_route_map_entry_match_condition_ipv4_next_hop_type_modify, | |
1210 | .destroy = lib_route_map_entry_match_condition_ipv4_next_hop_type_destroy, | |
1211 | } | |
1212 | }, | |
1213 | { | |
1214 | .xpath = "/frr-route-map:lib/route-map/entry/match-condition/ipv6-next-hop-type", | |
1215 | .cbs = { | |
1216 | .modify = lib_route_map_entry_match_condition_ipv6_next_hop_type_modify, | |
1217 | .destroy = lib_route_map_entry_match_condition_ipv6_next_hop_type_destroy, | |
1218 | } | |
1219 | }, | |
1220 | { | |
1221 | .xpath = "/frr-route-map:lib/route-map/entry/match-condition/metric", | |
1222 | .cbs = { | |
1223 | .modify = lib_route_map_entry_match_condition_metric_modify, | |
1224 | .destroy = lib_route_map_entry_match_condition_metric_destroy, | |
1225 | } | |
1226 | }, | |
1227 | { | |
1228 | .xpath = "/frr-route-map:lib/route-map/entry/match-condition/tag", | |
1229 | .cbs = { | |
1230 | .modify = lib_route_map_entry_match_condition_tag_modify, | |
1231 | .destroy = lib_route_map_entry_match_condition_tag_destroy, | |
1232 | } | |
1233 | }, | |
1234 | { | |
1235 | .xpath = "/frr-route-map:lib/route-map/entry/set-action", | |
1236 | .cbs = { | |
1237 | .create = lib_route_map_entry_set_action_create, | |
1238 | .destroy = lib_route_map_entry_set_action_destroy, | |
2b3e4807 | 1239 | .cli_show = route_map_action_show, |
686d244f RZ |
1240 | } |
1241 | }, | |
1242 | { | |
1243 | .xpath = "/frr-route-map:lib/route-map/entry/set-action/ipv4-address", | |
1244 | .cbs = { | |
1245 | .modify = lib_route_map_entry_set_action_ipv4_address_modify, | |
1246 | .destroy = lib_route_map_entry_set_action_ipv4_address_destroy, | |
1247 | } | |
1248 | }, | |
1249 | { | |
1250 | .xpath = "/frr-route-map:lib/route-map/entry/set-action/ipv6-address", | |
1251 | .cbs = { | |
1252 | .modify = lib_route_map_entry_set_action_ipv6_address_modify, | |
1253 | .destroy = lib_route_map_entry_set_action_ipv6_address_destroy, | |
1254 | } | |
1255 | }, | |
1256 | { | |
1257 | .xpath = "/frr-route-map:lib/route-map/entry/set-action/value", | |
1258 | .cbs = { | |
1259 | .modify = lib_route_map_entry_set_action_value_modify, | |
1260 | .destroy = lib_route_map_entry_set_action_value_destroy, | |
1261 | } | |
1262 | }, | |
1263 | { | |
1264 | .xpath = "/frr-route-map:lib/route-map/entry/set-action/add-metric", | |
1265 | .cbs = { | |
1266 | .modify = lib_route_map_entry_set_action_add_metric_modify, | |
1267 | .destroy = lib_route_map_entry_set_action_add_metric_destroy, | |
1268 | } | |
1269 | }, | |
1270 | { | |
1271 | .xpath = "/frr-route-map:lib/route-map/entry/set-action/subtract-metric", | |
1272 | .cbs = { | |
1273 | .modify = lib_route_map_entry_set_action_subtract_metric_modify, | |
1274 | .destroy = lib_route_map_entry_set_action_subtract_metric_destroy, | |
1275 | } | |
1276 | }, | |
1277 | { | |
1278 | .xpath = "/frr-route-map:lib/route-map/entry/set-action/use-round-trip-time", | |
1279 | .cbs = { | |
1280 | .modify = lib_route_map_entry_set_action_use_round_trip_time_modify, | |
1281 | .destroy = lib_route_map_entry_set_action_use_round_trip_time_destroy, | |
1282 | } | |
1283 | }, | |
1284 | { | |
1285 | .xpath = "/frr-route-map:lib/route-map/entry/set-action/add-round-trip-time", | |
1286 | .cbs = { | |
1287 | .modify = lib_route_map_entry_set_action_add_round_trip_time_modify, | |
1288 | .destroy = lib_route_map_entry_set_action_add_round_trip_time_destroy, | |
1289 | } | |
1290 | }, | |
1291 | { | |
1292 | .xpath = "/frr-route-map:lib/route-map/entry/set-action/subtract-round-trip-time", | |
1293 | .cbs = { | |
1294 | .modify = lib_route_map_entry_set_action_subtract_round_trip_time_modify, | |
1295 | .destroy = lib_route_map_entry_set_action_subtract_round_trip_time_destroy, | |
1296 | } | |
1297 | }, | |
1298 | { | |
1299 | .xpath = "/frr-route-map:lib/route-map/entry/set-action/tag", | |
1300 | .cbs = { | |
1301 | .modify = lib_route_map_entry_set_action_tag_modify, | |
1302 | .destroy = lib_route_map_entry_set_action_tag_destroy, | |
1303 | } | |
1304 | }, | |
1305 | { | |
1306 | .xpath = NULL, | |
1307 | }, | |
1308 | } | |
1309 | }; |