]> git.proxmox.com Git - mirror_frr.git/blob - lib/routemap_cli.c
Merge pull request #11003 from anlancs/bgpd-mh-trival-remove
[mirror_frr.git] / lib / routemap_cli.c
1 /*
2 * Route map northbound CLI 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/northbound_cli.h"
27 #include "lib/routemap.h"
28
29 #ifndef VTYSH_EXTRACT_PL
30 #include "lib/routemap_cli_clippy.c"
31 #endif /* VTYSH_EXTRACT_PL */
32
33 #define ROUTE_MAP_CMD_STR \
34 "Create route-map or enter route-map command mode\n" \
35 "Route map tag\n"
36 #define ROUTE_MAP_OP_CMD_STR \
37 "Route map denies set operations\n" \
38 "Route map permits set operations\n"
39 #define ROUTE_MAP_SEQUENCE_CMD_STR \
40 "Sequence to insert to/delete from existing route-map entry\n"
41
42 DEFPY_YANG_NOSH(
43 route_map, route_map_cmd,
44 "route-map RMAP_NAME$name <deny|permit>$action (1-65535)$sequence",
45 ROUTE_MAP_CMD_STR
46 ROUTE_MAP_OP_CMD_STR
47 ROUTE_MAP_SEQUENCE_CMD_STR)
48 {
49 char xpath_action[XPATH_MAXLEN + 64];
50 char xpath_index[XPATH_MAXLEN + 32];
51 char xpath[XPATH_MAXLEN];
52 int rv;
53
54 snprintf(xpath, sizeof(xpath),
55 "/frr-route-map:lib/route-map[name='%s']", name);
56 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
57
58 snprintf(xpath_index, sizeof(xpath_index), "%s/entry[sequence='%lu']",
59 xpath, sequence);
60 nb_cli_enqueue_change(vty, xpath_index, NB_OP_CREATE, NULL);
61
62 snprintf(xpath_action, sizeof(xpath_action), "%s/action", xpath_index);
63 nb_cli_enqueue_change(vty, xpath_action, NB_OP_MODIFY, action);
64
65 rv = nb_cli_apply_changes(vty, NULL);
66 if (rv == CMD_SUCCESS)
67 VTY_PUSH_XPATH(RMAP_NODE, xpath_index);
68
69 return rv;
70 }
71
72 DEFPY_YANG(
73 no_route_map_all, no_route_map_all_cmd,
74 "no route-map RMAP_NAME$name",
75 NO_STR
76 ROUTE_MAP_CMD_STR)
77 {
78 char xpath[XPATH_MAXLEN];
79
80 snprintf(xpath, sizeof(xpath),
81 "/frr-route-map:lib/route-map[name='%s']", name);
82 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
83
84 return nb_cli_apply_changes(vty, NULL);
85 }
86
87 DEFPY_YANG(
88 no_route_map, no_route_map_cmd,
89 "no route-map RMAP_NAME$name <deny|permit>$action (1-65535)$sequence",
90 NO_STR
91 ROUTE_MAP_CMD_STR
92 ROUTE_MAP_OP_CMD_STR
93 ROUTE_MAP_SEQUENCE_CMD_STR)
94 {
95 char xpath[XPATH_MAXLEN];
96
97 snprintf(xpath, sizeof(xpath),
98 "/frr-route-map:lib/route-map[name='%s']/entry[sequence='%lu']",
99 name, sequence);
100
101 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
102
103 return nb_cli_apply_changes(vty, NULL);
104 }
105
106 int route_map_instance_cmp(const struct lyd_node *dnode1,
107 const struct lyd_node *dnode2)
108 {
109 uint16_t seq1 = yang_dnode_get_uint16(dnode1, "./sequence");
110 uint16_t seq2 = yang_dnode_get_uint16(dnode2, "./sequence");
111
112 return seq1 - seq2;
113 }
114
115 void route_map_instance_show(struct vty *vty, const struct lyd_node *dnode,
116 bool show_defaults)
117 {
118 const char *name = yang_dnode_get_string(dnode, "../name");
119 const char *action = yang_dnode_get_string(dnode, "./action");
120 const char *sequence = yang_dnode_get_string(dnode, "./sequence");
121
122 vty_out(vty, "route-map %s %s %s\n", name, action, sequence);
123
124 }
125
126 void route_map_instance_show_end(struct vty *vty, const struct lyd_node *dnode)
127 {
128 vty_out(vty, "exit\n");
129 vty_out(vty, "!\n");
130 }
131
132 DEFPY_YANG(
133 match_interface, match_interface_cmd,
134 "match interface IFNAME",
135 MATCH_STR
136 "Match first hop interface of route\n"
137 INTERFACE_STR)
138 {
139 const char *xpath =
140 "./match-condition[condition='frr-route-map:interface']";
141 char xpath_value[XPATH_MAXLEN];
142
143 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
144 snprintf(xpath_value, sizeof(xpath_value),
145 "%s/rmap-match-condition/interface", xpath);
146 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, ifname);
147
148 return nb_cli_apply_changes(vty, NULL);
149 }
150
151 DEFPY_YANG(
152 no_match_interface, no_match_interface_cmd,
153 "no match interface [IFNAME]",
154 NO_STR
155 MATCH_STR
156 "Match first hop interface of route\n"
157 INTERFACE_STR)
158 {
159 const char *xpath =
160 "./match-condition[condition='frr-route-map:interface']";
161
162 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
163
164 return nb_cli_apply_changes(vty, NULL);
165 }
166
167 DEFPY_YANG(
168 match_ip_address, match_ip_address_cmd,
169 "match ip address ACCESSLIST4_NAME$name",
170 MATCH_STR
171 IP_STR
172 "Match address of route\n"
173 "IP Access-list name\n")
174 {
175 const char *xpath =
176 "./match-condition[condition='frr-route-map:ipv4-address-list']";
177 char xpath_value[XPATH_MAXLEN + 32];
178
179 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
180 snprintf(xpath_value, sizeof(xpath_value),
181 "%s/rmap-match-condition/list-name", xpath);
182 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, name);
183
184 return nb_cli_apply_changes(vty, NULL);
185 }
186
187 DEFPY_YANG(
188 no_match_ip_address, no_match_ip_address_cmd,
189 "no match ip address [ACCESSLIST4_NAME]",
190 NO_STR
191 MATCH_STR
192 IP_STR
193 "Match address of route\n"
194 "IP Access-list name\n")
195 {
196 const char *xpath =
197 "./match-condition[condition='frr-route-map:ipv4-address-list']";
198
199 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
200
201 return nb_cli_apply_changes(vty, NULL);
202 }
203
204 DEFPY_YANG(
205 match_ip_address_prefix_list,
206 match_ip_address_prefix_list_cmd,
207 "match ip address prefix-list PREFIXLIST_NAME$name",
208 MATCH_STR
209 IP_STR
210 "Match address of route\n"
211 "Match entries of prefix-lists\n"
212 "IP prefix-list name\n")
213 {
214 const char *xpath =
215 "./match-condition[condition='frr-route-map:ipv4-prefix-list']";
216 char xpath_value[XPATH_MAXLEN];
217
218 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
219 snprintf(xpath_value, sizeof(xpath_value),
220 "%s/rmap-match-condition/list-name", xpath);
221 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, name);
222
223 return nb_cli_apply_changes(vty, NULL);
224 }
225
226 DEFPY_YANG(
227 no_match_ip_address_prefix_list, no_match_ip_address_prefix_list_cmd,
228 "no match ip address prefix-list [PREFIXLIST_NAME]",
229 NO_STR
230 MATCH_STR
231 IP_STR
232 "Match address of route\n"
233 "Match entries of prefix-lists\n"
234 "IP prefix-list name\n")
235 {
236 const char *xpath =
237 "./match-condition[condition='frr-route-map:ipv4-prefix-list']";
238
239 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
240
241 return nb_cli_apply_changes(vty, NULL);
242 }
243
244 DEFPY_YANG(
245 match_ip_next_hop, match_ip_next_hop_cmd,
246 "match ip next-hop ACCESSLIST4_NAME$name",
247 MATCH_STR
248 IP_STR
249 "Match next-hop address of route\n"
250 "IP Access-list name\n")
251 {
252 const char *xpath =
253 "./match-condition[condition='frr-route-map:ipv4-next-hop-list']";
254 char xpath_value[XPATH_MAXLEN + 32];
255
256 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
257 snprintf(xpath_value, sizeof(xpath_value),
258 "%s/rmap-match-condition/list-name", xpath);
259 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, name);
260
261 return nb_cli_apply_changes(vty, NULL);
262 }
263
264 DEFPY_YANG(
265 no_match_ip_next_hop, no_match_ip_next_hop_cmd,
266 "no match ip next-hop [ACCESSLIST4_NAME]",
267 NO_STR
268 MATCH_STR
269 IP_STR
270 "Match address of route\n"
271 "IP Access-list name\n")
272 {
273 const char *xpath =
274 "./match-condition[condition='frr-route-map:ipv4-next-hop-list']";
275
276 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
277
278 return nb_cli_apply_changes(vty, NULL);
279 }
280
281 DEFPY_YANG(
282 match_ip_next_hop_prefix_list,
283 match_ip_next_hop_prefix_list_cmd,
284 "match ip next-hop prefix-list PREFIXLIST_NAME$name",
285 MATCH_STR
286 IP_STR
287 "Match next-hop address of route\n"
288 "Match entries of prefix-lists\n"
289 "IP prefix-list name\n")
290 {
291 const char *xpath =
292 "./match-condition[condition='frr-route-map:ipv4-next-hop-prefix-list']";
293 char xpath_value[XPATH_MAXLEN];
294
295 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
296 snprintf(xpath_value, sizeof(xpath_value),
297 "%s/rmap-match-condition/list-name", xpath);
298 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, name);
299
300 return nb_cli_apply_changes(vty, NULL);
301 }
302
303 DEFPY_YANG(
304 no_match_ip_next_hop_prefix_list,
305 no_match_ip_next_hop_prefix_list_cmd,
306 "no match ip next-hop prefix-list [PREFIXLIST_NAME]",
307 NO_STR
308 MATCH_STR
309 IP_STR
310 "Match next-hop address of route\n"
311 "Match entries of prefix-lists\n"
312 "IP prefix-list name\n")
313 {
314 const char *xpath =
315 "./match-condition[condition='frr-route-map:ipv4-next-hop-prefix-list']";
316
317 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
318
319 return nb_cli_apply_changes(vty, NULL);
320 }
321
322 DEFPY_YANG(
323 match_ip_next_hop_type, match_ip_next_hop_type_cmd,
324 "match ip next-hop type <blackhole>$type",
325 MATCH_STR
326 IP_STR
327 "Match next-hop address of route\n"
328 "Match entries by type\n"
329 "Blackhole\n")
330 {
331 const char *xpath =
332 "./match-condition[condition='frr-route-map:ipv4-next-hop-type']";
333 char xpath_value[XPATH_MAXLEN];
334
335 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
336 snprintf(xpath_value, sizeof(xpath_value),
337 "%s/rmap-match-condition/ipv4-next-hop-type", xpath);
338 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, type);
339
340 return nb_cli_apply_changes(vty, NULL);
341 }
342
343 DEFPY_YANG(
344 no_match_ip_next_hop_type, no_match_ip_next_hop_type_cmd,
345 "no match ip next-hop type [<blackhole>]",
346 NO_STR MATCH_STR IP_STR
347 "Match next-hop address of route\n"
348 "Match entries by type\n"
349 "Blackhole\n")
350 {
351 const char *xpath =
352 "./match-condition[condition='frr-route-map:ipv4-next-hop-type']";
353
354 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
355
356 return nb_cli_apply_changes(vty, NULL);
357 }
358
359 DEFPY_YANG(
360 match_ipv6_address, match_ipv6_address_cmd,
361 "match ipv6 address ACCESSLIST6_NAME$name",
362 MATCH_STR
363 IPV6_STR
364 "Match IPv6 address of route\n"
365 "IPv6 access-list name\n")
366 {
367 const char *xpath =
368 "./match-condition[condition='frr-route-map:ipv6-address-list']";
369 char xpath_value[XPATH_MAXLEN];
370
371 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
372 snprintf(xpath_value, sizeof(xpath_value),
373 "%s/rmap-match-condition/list-name", xpath);
374 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, name);
375
376 return nb_cli_apply_changes(vty, NULL);
377 }
378
379 DEFPY_YANG(
380 no_match_ipv6_address, no_match_ipv6_address_cmd,
381 "no match ipv6 address [ACCESSLIST6_NAME]",
382 NO_STR
383 MATCH_STR
384 IPV6_STR
385 "Match IPv6 address of route\n"
386 "IPv6 access-list name\n")
387 {
388 const char *xpath =
389 "./match-condition[condition='frr-route-map:ipv6-address-list']";
390
391 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
392
393 return nb_cli_apply_changes(vty, NULL);
394 }
395
396 DEFPY_YANG(
397 match_ipv6_address_prefix_list, match_ipv6_address_prefix_list_cmd,
398 "match ipv6 address prefix-list PREFIXLIST_NAME$name",
399 MATCH_STR
400 IPV6_STR
401 "Match address of route\n"
402 "Match entries of prefix-lists\n"
403 "IP prefix-list name\n")
404 {
405 const char *xpath =
406 "./match-condition[condition='frr-route-map:ipv6-prefix-list']";
407 char xpath_value[XPATH_MAXLEN];
408
409 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
410 snprintf(xpath_value, sizeof(xpath_value),
411 "%s/rmap-match-condition/list-name", xpath);
412 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, name);
413
414 return nb_cli_apply_changes(vty, NULL);
415 }
416
417 DEFPY_YANG(
418 no_match_ipv6_address_prefix_list,
419 no_match_ipv6_address_prefix_list_cmd,
420 "no match ipv6 address prefix-list [PREFIXLIST_NAME]",
421 NO_STR
422 MATCH_STR
423 IPV6_STR
424 "Match address of route\n"
425 "Match entries of prefix-lists\n"
426 "IP prefix-list name\n")
427 {
428 const char *xpath =
429 "./match-condition[condition='frr-route-map:ipv6-prefix-list']";
430
431 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
432
433 return nb_cli_apply_changes(vty, NULL);
434 }
435
436 DEFPY_YANG(
437 match_ipv6_next_hop_type, match_ipv6_next_hop_type_cmd,
438 "match ipv6 next-hop type <blackhole>$type",
439 MATCH_STR IPV6_STR
440 "Match next-hop address of route\n"
441 "Match entries by type\n"
442 "Blackhole\n")
443 {
444 const char *xpath =
445 "./match-condition[condition='frr-route-map:ipv6-next-hop-type']";
446 char xpath_value[XPATH_MAXLEN];
447
448 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
449 snprintf(xpath_value, sizeof(xpath_value),
450 "%s/rmap-match-condition/ipv6-next-hop-type", xpath);
451 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, type);
452
453 return nb_cli_apply_changes(vty, NULL);
454 }
455
456 DEFPY_YANG(
457 no_match_ipv6_next_hop_type, no_match_ipv6_next_hop_type_cmd,
458 "no match ipv6 next-hop type [<blackhole>]",
459 NO_STR MATCH_STR IPV6_STR
460 "Match address of route\n"
461 "Match entries by type\n"
462 "Blackhole\n")
463 {
464 const char *xpath =
465 "./match-condition[condition='frr-route-map:ipv6-next-hop-type']";
466
467 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
468
469 return nb_cli_apply_changes(vty, NULL);
470 }
471
472 DEFPY_YANG(
473 match_metric, match_metric_cmd,
474 "match metric (0-4294967295)$metric",
475 MATCH_STR
476 "Match metric of route\n"
477 "Metric value\n")
478 {
479 const char *xpath =
480 "./match-condition[condition='frr-route-map:match-metric']";
481 char xpath_value[XPATH_MAXLEN];
482
483 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
484 snprintf(xpath_value, sizeof(xpath_value),
485 "%s/rmap-match-condition/metric", xpath);
486 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, metric_str);
487
488 return nb_cli_apply_changes(vty, NULL);
489 }
490
491 DEFPY_YANG(
492 no_match_metric, no_match_metric_cmd,
493 "no match metric [(0-4294967295)]",
494 NO_STR
495 MATCH_STR
496 "Match metric of route\n"
497 "Metric value\n")
498 {
499 const char *xpath =
500 "./match-condition[condition='frr-route-map:match-metric']";
501
502 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
503
504 return nb_cli_apply_changes(vty, NULL);
505 }
506
507 DEFPY_YANG(
508 match_tag, match_tag_cmd,
509 "match tag (1-4294967295)$tag",
510 MATCH_STR
511 "Match tag of route\n"
512 "Tag value\n")
513 {
514 const char *xpath =
515 "./match-condition[condition='frr-route-map:match-tag']";
516 char xpath_value[XPATH_MAXLEN];
517
518 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
519 snprintf(xpath_value, sizeof(xpath_value),
520 "%s/rmap-match-condition/tag", xpath);
521 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, tag_str);
522
523 return nb_cli_apply_changes(vty, NULL);
524 }
525
526 DEFPY_YANG(
527 no_match_tag, no_match_tag_cmd,
528 "no match tag [(1-4294967295)]",
529 NO_STR
530 MATCH_STR
531 "Match tag of route\n"
532 "Tag value\n")
533 {
534 const char *xpath =
535 "./match-condition[condition='frr-route-map:match-tag']";
536
537 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
538
539 return nb_cli_apply_changes(vty, NULL);
540 }
541
542 void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
543 bool show_defaults)
544 {
545 const char *condition = yang_dnode_get_string(dnode, "./condition");
546 const struct lyd_node *ln;
547 const char *acl;
548
549 if (IS_MATCH_INTERFACE(condition)) {
550 vty_out(vty, " match interface %s\n",
551 yang_dnode_get_string(
552 dnode, "./rmap-match-condition/interface"));
553 } else if (IS_MATCH_IPv4_ADDRESS_LIST(condition)) {
554 vty_out(vty, " match ip address %s\n",
555 yang_dnode_get_string(
556 dnode, "./rmap-match-condition/list-name"));
557 } else if (IS_MATCH_IPv4_NEXTHOP_LIST(condition)) {
558 vty_out(vty, " match ip next-hop %s\n",
559 yang_dnode_get_string(
560 dnode, "./rmap-match-condition/list-name"));
561 } else if (IS_MATCH_IPv6_NEXTHOP_LIST(condition)) {
562 vty_out(vty, " match ipv6 next-hop %s\n",
563 yang_dnode_get_string(
564 dnode, "./rmap-match-condition/list-name"));
565 } else if (IS_MATCH_IPv4_PREFIX_LIST(condition)) {
566 vty_out(vty, " match ip address prefix-list %s\n",
567 yang_dnode_get_string(
568 dnode, "./rmap-match-condition/list-name"));
569 } else if (IS_MATCH_IPv4_NEXTHOP_PREFIX_LIST(condition)) {
570 vty_out(vty, " match ip next-hop prefix-list %s\n",
571 yang_dnode_get_string(
572 dnode, "./rmap-match-condition/list-name"));
573 } else if (IS_MATCH_IPv6_NEXTHOP_PREFIX_LIST(condition)) {
574 vty_out(vty, " match ipv6 next-hop prefix-list %s\n",
575 yang_dnode_get_string(
576 dnode, "./rmap-match-condition/list-name"));
577 } else if (IS_MATCH_IPv6_ADDRESS_LIST(condition)) {
578 vty_out(vty, " match ipv6 address %s\n",
579 yang_dnode_get_string(
580 dnode, "./rmap-match-condition/list-name"));
581 } else if (IS_MATCH_IPv6_PREFIX_LIST(condition)) {
582 vty_out(vty, " match ipv6 address prefix-list %s\n",
583 yang_dnode_get_string(
584 dnode, "./rmap-match-condition/list-name"));
585 } else if (IS_MATCH_IPv4_NEXTHOP_TYPE(condition)) {
586 vty_out(vty, " match ip next-hop type %s\n",
587 yang_dnode_get_string(
588 dnode,
589 "./rmap-match-condition/ipv4-next-hop-type"));
590 } else if (IS_MATCH_IPv6_NEXTHOP_TYPE(condition)) {
591 vty_out(vty, " match ipv6 next-hop type %s\n",
592 yang_dnode_get_string(
593 dnode,
594 "./rmap-match-condition/ipv6-next-hop-type"));
595 } else if (IS_MATCH_METRIC(condition)) {
596 vty_out(vty, " match metric %s\n",
597 yang_dnode_get_string(dnode,
598 "./rmap-match-condition/metric"));
599 } else if (IS_MATCH_TAG(condition)) {
600 vty_out(vty, " match tag %s\n",
601 yang_dnode_get_string(dnode,
602 "./rmap-match-condition/tag"));
603 } else if (IS_MATCH_IPv4_PREFIX_LEN(condition)) {
604 vty_out(vty, " match ip address prefix-len %s\n",
605 yang_dnode_get_string(
606 dnode,
607 "./rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length"));
608 } else if (IS_MATCH_IPv6_PREFIX_LEN(condition)) {
609 vty_out(vty, " match ipv6 address prefix-len %s\n",
610 yang_dnode_get_string(
611 dnode,
612 "./rmap-match-condition/frr-zebra-route-map:ipv6-prefix-length"));
613 } else if (IS_MATCH_IPv4_NH_PREFIX_LEN(condition)) {
614 vty_out(vty, " match ip next-hop prefix-len %s\n",
615 yang_dnode_get_string(
616 dnode,
617 "./rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length"));
618 } else if (IS_MATCH_SRC_PROTO(condition)) {
619 vty_out(vty, " match source-protocol %s\n",
620 yang_dnode_get_string(
621 dnode,
622 "./rmap-match-condition/frr-zebra-route-map:source-protocol"));
623 } else if (IS_MATCH_SRC_INSTANCE(condition)) {
624 vty_out(vty, " match source-instance %s\n",
625 yang_dnode_get_string(
626 dnode,
627 "./rmap-match-condition/frr-zebra-route-map:source-instance"));
628 } else if (IS_MATCH_LOCAL_PREF(condition)) {
629 vty_out(vty, " match local-preference %s\n",
630 yang_dnode_get_string(
631 dnode,
632 "./rmap-match-condition/frr-bgp-route-map:local-preference"));
633 } else if (IS_MATCH_ALIAS(condition)) {
634 vty_out(vty, " match alias %s\n",
635 yang_dnode_get_string(
636 dnode,
637 "./rmap-match-condition/frr-bgp-route-map:alias"));
638 } else if (IS_MATCH_SCRIPT(condition)) {
639 vty_out(vty, " match script %s\n",
640 yang_dnode_get_string(
641 dnode,
642 "./rmap-match-condition/frr-bgp-route-map:script"));
643 } else if (IS_MATCH_ORIGIN(condition)) {
644 vty_out(vty, " match origin %s\n",
645 yang_dnode_get_string(
646 dnode,
647 "./rmap-match-condition/frr-bgp-route-map:origin"));
648 } else if (IS_MATCH_RPKI(condition)) {
649 vty_out(vty, " match rpki %s\n",
650 yang_dnode_get_string(
651 dnode,
652 "./rmap-match-condition/frr-bgp-route-map:rpki"));
653 } else if (IS_MATCH_PROBABILITY(condition)) {
654 vty_out(vty, " match probability %s\n",
655 yang_dnode_get_string(
656 dnode,
657 "./rmap-match-condition/frr-bgp-route-map:probability"));
658 } else if (IS_MATCH_SRC_VRF(condition)) {
659 vty_out(vty, " match source-vrf %s\n",
660 yang_dnode_get_string(
661 dnode,
662 "./rmap-match-condition/frr-bgp-route-map:source-vrf"));
663 } else if (IS_MATCH_PEER(condition)) {
664 acl = NULL;
665 if ((ln = yang_dnode_get(
666 dnode,
667 "./rmap-match-condition/frr-bgp-route-map:peer-ipv4-address"))
668 != NULL)
669 acl = yang_dnode_get_string(ln, NULL);
670 else if (
671 (ln = yang_dnode_get(
672 dnode,
673 "./rmap-match-condition/frr-bgp-route-map:peer-ipv6-address"))
674 != NULL)
675 acl = yang_dnode_get_string(ln, NULL);
676 else if (
677 (ln = yang_dnode_get(
678 dnode,
679 "./rmap-match-condition/frr-bgp-route-map:peer-interface"))
680 != NULL)
681 acl = yang_dnode_get_string(ln, NULL);
682 else if (yang_dnode_get(
683 dnode,
684 "./rmap-match-condition/frr-bgp-route-map:peer-local")
685 != NULL)
686 acl = "local";
687
688 vty_out(vty, " match peer %s\n", acl);
689 } else if (IS_MATCH_AS_LIST(condition)) {
690 vty_out(vty, " match as-path %s\n",
691 yang_dnode_get_string(
692 dnode,
693 "./rmap-match-condition/frr-bgp-route-map:list-name"));
694 } else if (IS_MATCH_EVPN_ROUTE_TYPE(condition)) {
695 vty_out(vty, " match evpn route-type %s\n",
696 yang_dnode_get_string(
697 dnode,
698 "./rmap-match-condition/frr-bgp-route-map:evpn-route-type"));
699 } else if (IS_MATCH_EVPN_DEFAULT_ROUTE(condition)) {
700 vty_out(vty, " match evpn default-route\n");
701 } else if (IS_MATCH_EVPN_VNI(condition)) {
702 vty_out(vty, " match evpn vni %s\n",
703 yang_dnode_get_string(
704 dnode,
705 "./rmap-match-condition/frr-bgp-route-map:evpn-vni"));
706 } else if (IS_MATCH_EVPN_DEFAULT_ROUTE(condition)) {
707 vty_out(vty, " match evpn default-route %s\n",
708 yang_dnode_get_string(
709 dnode,
710 "./rmap-match-condition/frr-bgp-route-map:evpn-default-route"));
711 } else if (IS_MATCH_EVPN_RD(condition)) {
712 vty_out(vty, " match evpn rd %s\n",
713 yang_dnode_get_string(
714 dnode,
715 "./rmap-match-condition/frr-bgp-route-map:route-distinguisher"));
716 } else if (IS_MATCH_MAC_LIST(condition)) {
717 vty_out(vty, " match mac address %s\n",
718 yang_dnode_get_string(
719 dnode,
720 "./rmap-match-condition/frr-bgp-route-map:list-name"));
721 } else if (IS_MATCH_ROUTE_SRC(condition)) {
722 vty_out(vty, " match ip route-source %s\n",
723 yang_dnode_get_string(
724 dnode,
725 "./rmap-match-condition/frr-bgp-route-map:list-name"));
726 } else if (IS_MATCH_ROUTE_SRC_PL(condition)) {
727 vty_out(vty, " match ip route-source prefix-list %s\n",
728 yang_dnode_get_string(
729 dnode,
730 "./rmap-match-condition/frr-bgp-route-map:list-name"));
731 } else if (IS_MATCH_COMMUNITY(condition)) {
732 vty_out(vty, " match community %s",
733 yang_dnode_get_string(
734 dnode,
735 "./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name"));
736 if (yang_dnode_get_bool(
737 dnode,
738 "./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match"))
739 vty_out(vty, " exact-match");
740 vty_out(vty, "\n");
741 } else if (IS_MATCH_LCOMMUNITY(condition)) {
742 vty_out(vty, " match large-community %s",
743 yang_dnode_get_string(
744 dnode,
745 "./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name"));
746 if (yang_dnode_get_bool(
747 dnode,
748 "./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match"))
749 vty_out(vty, " exact-match");
750 vty_out(vty, "\n");
751 } else if (IS_MATCH_EXTCOMMUNITY(condition)) {
752 vty_out(vty, " match extcommunity %s\n",
753 yang_dnode_get_string(
754 dnode,
755 "./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name"));
756 } else if (IS_MATCH_IPV4_NH(condition)) {
757 vty_out(vty, " match ip next-hop address %s\n",
758 yang_dnode_get_string(
759 dnode,
760 "./rmap-match-condition/frr-bgp-route-map:ipv4-address"));
761 } else if (IS_MATCH_IPV6_NH(condition)) {
762 vty_out(vty, " match ipv6 next-hop address %s\n",
763 yang_dnode_get_string(
764 dnode,
765 "./rmap-match-condition/frr-bgp-route-map:ipv6-address"));
766 }
767 }
768
769 DEFPY_YANG(
770 set_ip_nexthop, set_ip_nexthop_cmd,
771 "set ip next-hop A.B.C.D$addr",
772 SET_STR
773 IP_STR
774 "Next hop address\n"
775 "IP address of next hop\n")
776 {
777 const char *xpath =
778 "./set-action[action='frr-route-map:ipv4-next-hop']";
779 char xpath_value[XPATH_MAXLEN];
780
781 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
782 snprintf(xpath_value, sizeof(xpath_value),
783 "%s/rmap-set-action/ipv4-address", xpath);
784 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, addr_str);
785
786 return nb_cli_apply_changes(vty, NULL);
787 }
788
789 DEFPY_YANG(
790 no_set_ip_nexthop, no_set_ip_nexthop_cmd,
791 "no set ip next-hop [A.B.C.D]",
792 NO_STR
793 SET_STR
794 IP_STR
795 "Next hop address\n"
796 "IP address of next hop\n")
797 {
798 const char *xpath =
799 "./set-action[action='frr-route-map:ipv4-next-hop']";
800
801 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
802
803 return nb_cli_apply_changes(vty, NULL);
804 }
805
806 DEFPY_YANG(
807 set_ipv6_nexthop_local, set_ipv6_nexthop_local_cmd,
808 "set ipv6 next-hop local X:X::X:X$addr",
809 SET_STR
810 IPV6_STR
811 "IPv6 next-hop address\n"
812 "IPv6 local address\n"
813 "IPv6 address of next hop\n")
814 {
815 const char *xpath =
816 "./set-action[action='frr-route-map:ipv6-next-hop']";
817 char xpath_value[XPATH_MAXLEN];
818
819 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
820 snprintf(xpath_value, sizeof(xpath_value),
821 "%s/rmap-set-action/ipv6-address", xpath);
822 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, addr_str);
823
824 return nb_cli_apply_changes(vty, NULL);
825 }
826
827 DEFPY_YANG(
828 no_set_ipv6_nexthop_local, no_set_ipv6_nexthop_local_cmd,
829 "no set ipv6 next-hop local [X:X::X:X]",
830 NO_STR
831 SET_STR
832 IPV6_STR
833 "IPv6 next-hop address\n"
834 "IPv6 local address\n"
835 "IPv6 address of next hop\n")
836 {
837 const char *xpath =
838 "./set-action[action='frr-route-map:ipv6-next-hop']";
839
840 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
841
842 return nb_cli_apply_changes(vty, NULL);
843 }
844
845 DEFPY_YANG(
846 set_metric, set_metric_cmd,
847 "set metric <(-4294967295-4294967295)$metric|rtt$rtt|+rtt$artt|-rtt$srtt>",
848 SET_STR
849 "Metric value for destination routing protocol\n"
850 "Metric value (use +/- for additions or subtractions)\n"
851 "Assign round trip time\n"
852 "Add round trip time\n"
853 "Subtract round trip time\n")
854 {
855 const char *xpath = "./set-action[action='frr-route-map:set-metric']";
856 char xpath_value[XPATH_MAXLEN];
857 char value[64];
858
859 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
860 if (rtt) {
861 snprintf(xpath_value, sizeof(xpath_value),
862 "%s/rmap-set-action/use-round-trip-time", xpath);
863 snprintf(value, sizeof(value), "true");
864 } else if (artt) {
865 snprintf(xpath_value, sizeof(xpath_value),
866 "%s/rmap-set-action/add-round-trip-time", xpath);
867 snprintf(value, sizeof(value), "true");
868 } else if (srtt) {
869 snprintf(xpath_value, sizeof(xpath_value),
870 "%s/rmap-set-action/subtract-round-trip-time", xpath);
871 snprintf(value, sizeof(value), "true");
872 } else if (metric_str && metric_str[0] == '+') {
873 snprintf(xpath_value, sizeof(xpath_value),
874 "%s/rmap-set-action/add-metric", xpath);
875 snprintf(value, sizeof(value), "%s", ++metric_str);
876 } else if (metric_str && metric_str[0] == '-') {
877 snprintf(xpath_value, sizeof(xpath_value),
878 "%s/rmap-set-action/subtract-metric", xpath);
879 snprintf(value, sizeof(value), "%s", ++metric_str);
880 } else {
881 snprintf(xpath_value, sizeof(xpath_value),
882 "%s/rmap-set-action/value", xpath);
883 snprintf(value, sizeof(value), "%s", metric_str);
884 }
885 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, value);
886
887 return nb_cli_apply_changes(vty, NULL);
888 }
889
890 DEFPY_YANG(
891 no_set_metric, no_set_metric_cmd,
892 "no set metric [OPTVAL]",
893 NO_STR
894 SET_STR
895 "Metric value for destination routing protocol\n"
896 "Metric value\n")
897 {
898 const char *xpath = "./set-action[action='frr-route-map:set-metric']";
899
900 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
901 return nb_cli_apply_changes(vty, NULL);
902 }
903
904 DEFPY_YANG(
905 set_tag, set_tag_cmd,
906 "set tag (1-4294967295)$tag",
907 SET_STR
908 "Tag value for routing protocol\n"
909 "Tag value\n")
910 {
911 const char *xpath = "./set-action[action='frr-route-map:set-tag']";
912 char xpath_value[XPATH_MAXLEN];
913
914 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
915 snprintf(xpath_value, sizeof(xpath_value), "%s/rmap-set-action/tag",
916 xpath);
917 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, tag_str);
918
919 return nb_cli_apply_changes(vty, NULL);
920 }
921
922 DEFPY_YANG(
923 no_set_tag, no_set_tag_cmd,
924 "no set tag [(1-4294967295)]",
925 NO_STR
926 SET_STR
927 "Tag value for routing protocol\n"
928 "Tag value\n")
929 {
930 const char *xpath = "./set-action[action='frr-route-map:set-tag']";
931
932 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
933
934 return nb_cli_apply_changes(vty, NULL);
935 }
936
937 DEFUN_YANG (set_srte_color,
938 set_srte_color_cmd,
939 "set sr-te color (1-4294967295)",
940 SET_STR
941 SRTE_STR
942 SRTE_COLOR_STR
943 "Color of the SR-TE Policies to match with\n")
944 {
945 const char *xpath =
946 "./set-action[action='frr-route-map:set-sr-te-color']";
947 char xpath_value[XPATH_MAXLEN];
948 int idx = 0;
949
950 char *arg = argv_find(argv, argc, "(1-4294967295)", &idx)
951 ? argv[idx]->arg
952 : NULL;
953
954 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
955 snprintf(xpath_value, sizeof(xpath_value),
956 "%s/rmap-set-action/policy", xpath);
957 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, arg);
958
959 return nb_cli_apply_changes(vty, NULL);
960 }
961
962 DEFUN_YANG (no_set_srte_color,
963 no_set_srte_color_cmd,
964 "no set sr-te color [(1-4294967295)]",
965 NO_STR
966 SET_STR
967 SRTE_STR
968 SRTE_COLOR_STR
969 "Color of the SR-TE Policies to match with\n")
970 {
971 const char *xpath =
972 "./set-action[action='frr-route-map:set-sr-te-color']";
973
974 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
975
976 return nb_cli_apply_changes(vty, NULL);
977 }
978
979
980 void route_map_action_show(struct vty *vty, const struct lyd_node *dnode,
981 bool show_defaults)
982 {
983 const char *action = yang_dnode_get_string(dnode, "./action");
984 const struct lyd_node *ln;
985 const char *acl;
986
987 if (IS_SET_IPv4_NH(action)) {
988 vty_out(vty, " set ip next-hop %s\n",
989 yang_dnode_get_string(
990 dnode, "./rmap-set-action/ipv4-address"));
991 } else if (IS_SET_IPv6_NH(action)) {
992 vty_out(vty, " set ipv6 next-hop local %s\n",
993 yang_dnode_get_string(
994 dnode, "./rmap-set-action/ipv6-address"));
995 } else if (IS_SET_METRIC(action)) {
996 if (yang_dnode_get(dnode,
997 "./rmap-set-action/use-round-trip-time")) {
998 vty_out(vty, " set metric rtt\n");
999 } else if (yang_dnode_get(
1000 dnode,
1001 "./rmap-set-action/add-round-trip-time")) {
1002 vty_out(vty, " set metric +rtt\n");
1003 } else if (
1004 yang_dnode_get(
1005 dnode,
1006 "./rmap-set-action/subtract-round-trip-time")) {
1007 vty_out(vty, " set metric -rtt\n");
1008 } else if (yang_dnode_get(dnode,
1009 "./rmap-set-action/add-metric")) {
1010 vty_out(vty, " set metric +%s\n",
1011 yang_dnode_get_string(
1012 dnode, "./rmap-set-action/add-metric"));
1013 } else if (yang_dnode_get(
1014 dnode,
1015 "./rmap-set-action/subtract-metric")) {
1016 vty_out(vty, " set metric -%s\n",
1017 yang_dnode_get_string(
1018 dnode,
1019 "./rmap-set-action/subtract-metric"));
1020 } else {
1021 vty_out(vty, " set metric %s\n",
1022 yang_dnode_get_string(
1023 dnode, "./rmap-set-action/value"));
1024 }
1025 } else if (IS_SET_TAG(action)) {
1026 vty_out(vty, " set tag %s\n",
1027 yang_dnode_get_string(dnode, "./rmap-set-action/tag"));
1028 } else if (IS_SET_SR_TE_COLOR(action)) {
1029 vty_out(vty, " set sr-te color %s\n",
1030 yang_dnode_get_string(dnode,
1031 "./rmap-set-action/policy"));
1032 } else if (IS_SET_SRC(action)) {
1033 if (yang_dnode_exists(
1034 dnode,
1035 "./rmap-set-action/frr-zebra-route-map:ipv4-src-address"))
1036 vty_out(vty, " set src %s\n",
1037 yang_dnode_get_string(
1038 dnode,
1039 "./rmap-set-action/frr-zebra-route-map:ipv4-src-address"));
1040 else
1041 vty_out(vty, " set src %s\n",
1042 yang_dnode_get_string(
1043 dnode,
1044 "./rmap-set-action/frr-zebra-route-map:ipv6-src-address"));
1045 } else if (IS_SET_METRIC_TYPE(action)) {
1046 vty_out(vty, " set metric-type %s\n",
1047 yang_dnode_get_string(
1048 dnode,
1049 "./rmap-set-action/frr-ospf-route-map:metric-type"));
1050 } else if (IS_SET_FORWARDING_ADDR(action)) {
1051 vty_out(vty, " set forwarding-address %s\n",
1052 yang_dnode_get_string(
1053 dnode,
1054 "./rmap-set-action/frr-ospf6-route-map:ipv6-address"));
1055 } else if (IS_SET_WEIGHT(action)) {
1056 vty_out(vty, " set weight %s\n",
1057 yang_dnode_get_string(
1058 dnode,
1059 "./rmap-set-action/frr-bgp-route-map:weight"));
1060 } else if (IS_SET_TABLE(action)) {
1061 vty_out(vty, " set table %s\n",
1062 yang_dnode_get_string(
1063 dnode,
1064 "./rmap-set-action/frr-bgp-route-map:table"));
1065 } else if (IS_SET_LOCAL_PREF(action)) {
1066 vty_out(vty, " set local-preference %s\n",
1067 yang_dnode_get_string(
1068 dnode,
1069 "./rmap-set-action/frr-bgp-route-map:local-pref"));
1070 } else if (IS_SET_LABEL_INDEX(action)) {
1071 vty_out(vty, " set label-index %s\n",
1072 yang_dnode_get_string(
1073 dnode,
1074 "./rmap-set-action/frr-bgp-route-map:label-index"));
1075 } else if (IS_SET_DISTANCE(action)) {
1076 vty_out(vty, " set distance %s\n",
1077 yang_dnode_get_string(
1078 dnode,
1079 "./rmap-set-action/frr-bgp-route-map:distance"));
1080 } else if (IS_SET_ORIGIN(action)) {
1081 vty_out(vty, " set origin %s\n",
1082 yang_dnode_get_string(
1083 dnode,
1084 "./rmap-set-action/frr-bgp-route-map:origin"));
1085 } else if (IS_SET_ATOMIC_AGGREGATE(action)) {
1086 vty_out(vty, " set atomic-aggregate\n");
1087 } else if (IS_SET_ORIGINATOR_ID(action)) {
1088 vty_out(vty, " set originator-id %s\n",
1089 yang_dnode_get_string(
1090 dnode,
1091 "./rmap-set-action/frr-bgp-route-map:originator-id"));
1092 } else if (IS_SET_COMM_LIST_DEL(action)) {
1093 acl = NULL;
1094 if ((ln = yang_dnode_get(
1095 dnode,
1096 "./rmap-set-action/frr-bgp-route-map:comm-list-name"))
1097 != NULL)
1098 acl = yang_dnode_get_string(ln, NULL);
1099
1100 assert(acl);
1101
1102 vty_out(vty, " set comm-list %s delete\n", acl);
1103 } else if (IS_SET_LCOMM_LIST_DEL(action)) {
1104 acl = NULL;
1105 if ((ln = yang_dnode_get(
1106 dnode,
1107 "./rmap-set-action/frr-bgp-route-map:comm-list-name"))
1108 != NULL)
1109 acl = yang_dnode_get_string(ln, NULL);
1110
1111 assert(acl);
1112
1113 vty_out(vty, " set large-comm-list %s delete\n", acl);
1114 } else if (IS_SET_LCOMMUNITY(action)) {
1115 if (yang_dnode_exists(
1116 dnode,
1117 "./rmap-set-action/frr-bgp-route-map:large-community-string"))
1118 vty_out(vty, " set large-community %s\n",
1119 yang_dnode_get_string(
1120 dnode,
1121 "./rmap-set-action/frr-bgp-route-map:large-community-string"));
1122 else {
1123 if (true
1124 == yang_dnode_get_bool(
1125 dnode,
1126 "./rmap-set-action/frr-bgp-route-map:large-community-none"))
1127 vty_out(vty, " set large-community none\n");
1128 }
1129 } else if (IS_SET_COMMUNITY(action)) {
1130 if (yang_dnode_exists(
1131 dnode,
1132 "./rmap-set-action/frr-bgp-route-map:community-string"))
1133 vty_out(vty, " set community %s\n",
1134 yang_dnode_get_string(
1135 dnode,
1136 "./rmap-set-action/frr-bgp-route-map:community-string"));
1137 else {
1138 if (true
1139 == yang_dnode_get_bool(
1140 dnode,
1141 "./rmap-set-action/frr-bgp-route-map:community-none"))
1142 vty_out(vty, " set community none\n");
1143 }
1144 } else if (IS_SET_EXTCOMMUNITY_RT(action)) {
1145 vty_out(vty, " set extcommunity rt %s\n",
1146 yang_dnode_get_string(
1147 dnode,
1148 "./rmap-set-action/frr-bgp-route-map:extcommunity-rt"));
1149 } else if (IS_SET_EXTCOMMUNITY_SOO(action)) {
1150 vty_out(vty, " set extcommunity soo %s\n",
1151 yang_dnode_get_string(
1152 dnode,
1153 "./rmap-set-action/frr-bgp-route-map:extcommunity-soo"));
1154 } else if (IS_SET_EXTCOMMUNITY_LB(action)) {
1155 enum ecommunity_lb_type lb_type;
1156 char str[VTY_BUFSIZ];
1157 uint16_t bandwidth;
1158
1159 lb_type = yang_dnode_get_enum(
1160 dnode,
1161 "./rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type");
1162 switch (lb_type) {
1163 case EXPLICIT_BANDWIDTH:
1164 bandwidth = yang_dnode_get_uint16(
1165 dnode,
1166 "./rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth");
1167 snprintf(str, sizeof(str), "%d", bandwidth);
1168 break;
1169 case CUMULATIVE_BANDWIDTH:
1170 snprintf(str, sizeof(str), "%s", "cumulative");
1171 break;
1172 case COMPUTED_BANDWIDTH:
1173 snprintf(str, sizeof(str), "%s", "num-multipaths");
1174 }
1175
1176 if (yang_dnode_get_bool(
1177 dnode,
1178 "./rmap-set-action/frr-bgp-route-map:extcommunity-lb/two-octet-as-specific"))
1179 strlcat(str, " non-transitive", sizeof(str));
1180
1181 vty_out(vty, " set extcommunity bandwidth %s\n", str);
1182 } else if (IS_SET_EXTCOMMUNITY_NONE(action)) {
1183 if (yang_dnode_get_bool(
1184 dnode,
1185 "./rmap-set-action/frr-bgp-route-map:extcommunity-none"))
1186 vty_out(vty, " set extcommunity none\n");
1187 } else if (IS_SET_AGGREGATOR(action)) {
1188 vty_out(vty, " set aggregator as %s %s\n",
1189 yang_dnode_get_string(
1190 dnode,
1191 "./rmap-set-action/frr-bgp-route-map:aggregator/aggregator-asn"),
1192 yang_dnode_get_string(
1193 dnode,
1194 "./rmap-set-action/frr-bgp-route-map:aggregator/aggregator-address"));
1195 } else if (IS_SET_AS_EXCLUDE(action)) {
1196 vty_out(vty, " set as-path exclude %s\n",
1197 yang_dnode_get_string(
1198 dnode,
1199 "./rmap-set-action/frr-bgp-route-map:exclude-as-path"));
1200 } else if (IS_SET_AS_PREPEND(action)) {
1201 if (yang_dnode_exists(
1202 dnode,
1203 "./rmap-set-action/frr-bgp-route-map:prepend-as-path"))
1204 vty_out(vty, " set as-path prepend %s\n",
1205 yang_dnode_get_string(
1206 dnode,
1207 "./rmap-set-action/frr-bgp-route-map:prepend-as-path"));
1208 else {
1209 vty_out(vty, " set as-path prepend last-as %u\n",
1210 yang_dnode_get_uint8(
1211 dnode,
1212 "./rmap-set-action/frr-bgp-route-map:last-as"));
1213 }
1214 } else if (IS_SET_IPV6_NH_GLOBAL(action)) {
1215 vty_out(vty, " set ipv6 next-hop global %s\n",
1216 yang_dnode_get_string(
1217 dnode,
1218 "./rmap-set-action/frr-bgp-route-map:ipv6-address"));
1219 } else if (IS_SET_IPV6_VPN_NH(action)) {
1220 vty_out(vty, " set ipv6 vpn next-hop %s\n",
1221 yang_dnode_get_string(
1222 dnode,
1223 "./rmap-set-action/frr-bgp-route-map:ipv6-address"));
1224 } else if (IS_SET_IPV6_PEER_ADDR(action)) {
1225 if (true
1226 == yang_dnode_get_bool(
1227 dnode,
1228 "./rmap-set-action/frr-bgp-route-map:preference"))
1229 vty_out(vty, " set ipv6 next-hop peer-address\n");
1230 } else if (IS_SET_IPV6_PREFER_GLOBAL(action)) {
1231 if (true
1232 == yang_dnode_get_bool(
1233 dnode,
1234 "./rmap-set-action/frr-bgp-route-map:preference"))
1235 vty_out(vty, " set ipv6 next-hop prefer-global\n");
1236 } else if (IS_SET_IPV4_VPN_NH(action)) {
1237 vty_out(vty, " set ipv4 vpn next-hop %s\n",
1238 yang_dnode_get_string(
1239 dnode,
1240 "./rmap-set-action/frr-bgp-route-map:ipv4-address"));
1241 } else if (IS_SET_BGP_IPV4_NH(action)) {
1242 vty_out(vty, " set ip next-hop %s\n",
1243 yang_dnode_get_string(
1244 dnode,
1245 "./rmap-set-action/frr-bgp-route-map:ipv4-nexthop"));
1246 } else if (IS_SET_BGP_EVPN_GATEWAY_IP_IPV4(action)) {
1247 vty_out(vty, " set evpn gateway-ip ipv4 %s\n",
1248 yang_dnode_get_string(
1249 dnode,
1250 "./rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv4"));
1251 } else if (IS_SET_BGP_EVPN_GATEWAY_IP_IPV6(action)) {
1252 vty_out(vty, " set evpn gateway-ip ipv6 %s\n",
1253 yang_dnode_get_string(
1254 dnode,
1255 "./rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6"));
1256 }
1257 }
1258
1259 DEFPY_YANG(
1260 rmap_onmatch_next, rmap_onmatch_next_cmd,
1261 "on-match next",
1262 "Exit policy on matches\n"
1263 "Next clause\n")
1264 {
1265 nb_cli_enqueue_change(vty, "./exit-policy", NB_OP_MODIFY, "next");
1266
1267 return nb_cli_apply_changes(vty, NULL);
1268 }
1269
1270 DEFPY_YANG(
1271 no_rmap_onmatch_next,
1272 no_rmap_onmatch_next_cmd,
1273 "no on-match next",
1274 NO_STR
1275 "Exit policy on matches\n"
1276 "Next clause\n")
1277 {
1278 nb_cli_enqueue_change(vty, "./exit-policy", NB_OP_DESTROY, NULL);
1279
1280 return nb_cli_apply_changes(vty, NULL);
1281 }
1282
1283 DEFPY_YANG(
1284 rmap_onmatch_goto, rmap_onmatch_goto_cmd,
1285 "on-match goto (1-65535)$rm_num",
1286 "Exit policy on matches\n"
1287 "Goto Clause number\n"
1288 "Number\n")
1289 {
1290 nb_cli_enqueue_change(vty, "./exit-policy", NB_OP_MODIFY, "goto");
1291 nb_cli_enqueue_change(vty, "./goto-value", NB_OP_MODIFY, rm_num_str);
1292
1293 return nb_cli_apply_changes(vty, NULL);
1294 }
1295
1296 DEFPY_YANG(
1297 no_rmap_onmatch_goto, no_rmap_onmatch_goto_cmd,
1298 "no on-match goto",
1299 NO_STR
1300 "Exit policy on matches\n"
1301 "Goto Clause number\n")
1302 {
1303 nb_cli_enqueue_change(vty, "./exit-policy", NB_OP_DESTROY, NULL);
1304
1305 return nb_cli_apply_changes(vty, NULL);
1306 }
1307
1308 /* Cisco/GNU Zebra compatibility aliases */
1309 ALIAS_YANG(
1310 rmap_onmatch_goto, rmap_continue_cmd,
1311 "continue (1-65535)$rm_num",
1312 "Continue on a different entry within the route-map\n"
1313 "Route-map entry sequence number\n")
1314
1315 ALIAS_YANG(
1316 no_rmap_onmatch_goto, no_rmap_continue_cmd,
1317 "no continue [(1-65535)]",
1318 NO_STR
1319 "Continue on a different entry within the route-map\n"
1320 "Route-map entry sequence number\n")
1321
1322 void route_map_exit_policy_show(struct vty *vty, const struct lyd_node *dnode,
1323 bool show_defaults)
1324 {
1325 int exit_policy = yang_dnode_get_enum(dnode, NULL);
1326
1327 switch (exit_policy) {
1328 case 0: /* permit-or-deny */
1329 /* NOTHING: default option. */
1330 break;
1331 case 1: /* next */
1332 vty_out(vty, " on-match next\n");
1333 break;
1334 case 2: /* goto */
1335 vty_out(vty, " on-match goto %s\n",
1336 yang_dnode_get_string(dnode, "../goto-value"));
1337 break;
1338 }
1339 }
1340
1341 DEFPY_YANG(
1342 rmap_call, rmap_call_cmd,
1343 "call WORD$name",
1344 "Jump to another Route-Map after match+set\n"
1345 "Target route-map name\n")
1346 {
1347 nb_cli_enqueue_change(vty, "./call", NB_OP_MODIFY, name);
1348
1349 return nb_cli_apply_changes(vty, NULL);
1350 }
1351
1352 DEFPY_YANG(
1353 no_rmap_call, no_rmap_call_cmd,
1354 "no call [NAME]",
1355 NO_STR
1356 "Jump to another Route-Map after match+set\n"
1357 "Target route-map name\n")
1358 {
1359 nb_cli_enqueue_change(vty, "./call", NB_OP_DESTROY, NULL);
1360
1361 return nb_cli_apply_changes(vty, NULL);
1362 }
1363
1364 void route_map_call_show(struct vty *vty, const struct lyd_node *dnode,
1365 bool show_defaults)
1366 {
1367 vty_out(vty, " call %s\n", yang_dnode_get_string(dnode, NULL));
1368 }
1369
1370 DEFPY_YANG(
1371 rmap_description, rmap_description_cmd,
1372 "description LINE...",
1373 "Route-map comment\n"
1374 "Comment describing this route-map rule\n")
1375 {
1376 char *desc;
1377 int rv;
1378
1379 desc = argv_concat(argv, argc, 1);
1380 nb_cli_enqueue_change(vty, "./description", NB_OP_MODIFY, desc);
1381 rv = nb_cli_apply_changes(vty, NULL);
1382 XFREE(MTYPE_TMP, desc);
1383
1384 return rv;
1385 }
1386
1387 DEFUN_YANG (no_rmap_description,
1388 no_rmap_description_cmd,
1389 "no description",
1390 NO_STR
1391 "Route-map comment\n")
1392 {
1393 nb_cli_enqueue_change(vty, "./description", NB_OP_DESTROY, NULL);
1394
1395 return nb_cli_apply_changes(vty, NULL);
1396 }
1397
1398 void route_map_description_show(struct vty *vty, const struct lyd_node *dnode,
1399 bool show_defaults)
1400 {
1401 vty_out(vty, " description %s\n", yang_dnode_get_string(dnode, NULL));
1402 }
1403
1404 DEFPY_YANG(
1405 route_map_optimization, route_map_optimization_cmd,
1406 "[no] route-map RMAP_NAME$name optimization",
1407 NO_STR
1408 ROUTE_MAP_CMD_STR
1409 "Configure route-map optimization\n")
1410 {
1411 char xpath[XPATH_MAXLEN];
1412
1413 snprintf(xpath, sizeof(xpath),
1414 "/frr-route-map:lib/route-map[name='%s']", name);
1415 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
1416
1417 snprintf(
1418 xpath, sizeof(xpath),
1419 "/frr-route-map:lib/route-map[name='%s']/optimization-disabled",
1420 name);
1421 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, no ? "true" : "false");
1422
1423 return nb_cli_apply_changes(vty, NULL);
1424 }
1425
1426 void route_map_optimization_disabled_show(struct vty *vty,
1427 const struct lyd_node *dnode,
1428 bool show_defaults)
1429 {
1430 const char *name = yang_dnode_get_string(dnode, "../name");
1431 const bool disabled = yang_dnode_get_bool(dnode, NULL);
1432
1433 vty_out(vty, "%sroute-map %s optimization\n", disabled ? "no " : "",
1434 name);
1435 }
1436
1437 static int route_map_config_write(struct vty *vty)
1438 {
1439 const struct lyd_node *dnode;
1440 int written = 0;
1441
1442 dnode = yang_dnode_get(running_config->dnode,
1443 "/frr-route-map:lib");
1444 if (dnode) {
1445 nb_cli_show_dnode_cmds(vty, dnode, false);
1446 written = 1;
1447 }
1448
1449 return written;
1450 }
1451
1452 /* Route map node structure. */
1453 static int route_map_config_write(struct vty *vty);
1454 static struct cmd_node rmap_node = {
1455 .name = "routemap",
1456 .node = RMAP_NODE,
1457 .parent_node = CONFIG_NODE,
1458 .prompt = "%s(config-route-map)# ",
1459 .config_write = route_map_config_write,
1460 };
1461
1462 static void rmap_autocomplete(vector comps, struct cmd_token *token)
1463 {
1464 struct route_map *map;
1465
1466 for (map = route_map_master.head; map; map = map->next)
1467 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, map->name));
1468 }
1469
1470 static const struct cmd_variable_handler rmap_var_handlers[] = {
1471 {.varname = "route_map", .completions = rmap_autocomplete},
1472 {.tokenname = "ROUTEMAP_NAME", .completions = rmap_autocomplete},
1473 {.tokenname = "RMAP_NAME", .completions = rmap_autocomplete},
1474 {.completions = NULL}
1475 };
1476
1477 void route_map_cli_init(void)
1478 {
1479 /* Auto complete handler. */
1480 cmd_variable_handler_register(rmap_var_handlers);
1481
1482 /* CLI commands. */
1483 install_node(&rmap_node);
1484 install_default(RMAP_NODE);
1485 install_element(CONFIG_NODE, &route_map_cmd);
1486 install_element(CONFIG_NODE, &no_route_map_cmd);
1487 install_element(CONFIG_NODE, &no_route_map_all_cmd);
1488 install_element(CONFIG_NODE, &route_map_optimization_cmd);
1489
1490 /* Install the on-match stuff */
1491 install_element(RMAP_NODE, &rmap_onmatch_next_cmd);
1492 install_element(RMAP_NODE, &no_rmap_onmatch_next_cmd);
1493 install_element(RMAP_NODE, &rmap_onmatch_goto_cmd);
1494 install_element(RMAP_NODE, &no_rmap_onmatch_goto_cmd);
1495 install_element(RMAP_NODE, &rmap_continue_cmd);
1496 install_element(RMAP_NODE, &no_rmap_continue_cmd);
1497
1498 /* Install the call stuff. */
1499 install_element(RMAP_NODE, &rmap_call_cmd);
1500 install_element(RMAP_NODE, &no_rmap_call_cmd);
1501
1502 /* Install description commands. */
1503 install_element(RMAP_NODE, &rmap_description_cmd);
1504 install_element(RMAP_NODE, &no_rmap_description_cmd);
1505
1506 /* Install 'match' commands. */
1507 install_element(RMAP_NODE, &match_interface_cmd);
1508 install_element(RMAP_NODE, &no_match_interface_cmd);
1509
1510 install_element(RMAP_NODE, &match_ip_address_cmd);
1511 install_element(RMAP_NODE, &no_match_ip_address_cmd);
1512
1513 install_element(RMAP_NODE, &match_ip_address_prefix_list_cmd);
1514 install_element(RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
1515
1516 install_element(RMAP_NODE, &match_ip_next_hop_cmd);
1517 install_element(RMAP_NODE, &no_match_ip_next_hop_cmd);
1518
1519 install_element(RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
1520 install_element(RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
1521
1522 install_element(RMAP_NODE, &match_ip_next_hop_type_cmd);
1523 install_element(RMAP_NODE, &no_match_ip_next_hop_type_cmd);
1524
1525 install_element(RMAP_NODE, &match_ipv6_address_cmd);
1526 install_element(RMAP_NODE, &no_match_ipv6_address_cmd);
1527
1528 install_element(RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
1529 install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
1530
1531 install_element(RMAP_NODE, &match_ipv6_next_hop_type_cmd);
1532 install_element(RMAP_NODE, &no_match_ipv6_next_hop_type_cmd);
1533
1534 install_element(RMAP_NODE, &match_metric_cmd);
1535 install_element(RMAP_NODE, &no_match_metric_cmd);
1536
1537 install_element(RMAP_NODE, &match_tag_cmd);
1538 install_element(RMAP_NODE, &no_match_tag_cmd);
1539
1540 /* Install 'set' commands. */
1541 install_element(RMAP_NODE, &set_ip_nexthop_cmd);
1542 install_element(RMAP_NODE, &no_set_ip_nexthop_cmd);
1543
1544 install_element(RMAP_NODE, &set_ipv6_nexthop_local_cmd);
1545 install_element(RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
1546
1547 install_element(RMAP_NODE, &set_metric_cmd);
1548 install_element(RMAP_NODE, &no_set_metric_cmd);
1549
1550 install_element(RMAP_NODE, &set_tag_cmd);
1551 install_element(RMAP_NODE, &no_set_tag_cmd);
1552
1553 install_element(RMAP_NODE, &set_srte_color_cmd);
1554 install_element(RMAP_NODE, &no_set_srte_color_cmd);
1555 }