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