3 * Copyright (C) 2022 Vmware, Inc.
4 * Mobashshera Rasool <mrasool@vmware.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include "lib/srcdest_table.h"
37 #include "lib/northbound_cli.h"
38 #include "pim_errors.h"
40 #include "pim_cmd_common.h"
43 * Get current node VRF name.
46 * In case of failure it will print error message to user.
48 * \returns name or NULL if failed to get VRF.
50 const char *pim_cli_get_vrf_name(struct vty
*vty
)
52 const struct lyd_node
*vrf_node
;
54 /* Not inside any VRF context. */
55 if (vty
->xpath_index
== 0)
56 return VRF_DEFAULT_NAME
;
58 vrf_node
= yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
59 if (vrf_node
== NULL
) {
60 vty_out(vty
, "%% Failed to get vrf dnode in configuration\n");
64 return yang_dnode_get_string(vrf_node
, "./name");
67 int pim_process_join_prune_cmd(struct vty
*vty
, const char *jpi_str
)
69 char xpath
[XPATH_MAXLEN
];
71 snprintf(xpath
, sizeof(xpath
), FRR_PIM_ROUTER_XPATH
,
72 FRR_PIM_AF_XPATH_VAL
);
73 strlcat(xpath
, "/join-prune-interval", sizeof(xpath
));
75 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, jpi_str
);
77 return nb_cli_apply_changes(vty
, NULL
);
80 int pim_process_no_join_prune_cmd(struct vty
*vty
)
82 char xpath
[XPATH_MAXLEN
];
84 snprintf(xpath
, sizeof(xpath
), FRR_PIM_ROUTER_XPATH
,
85 FRR_PIM_AF_XPATH_VAL
);
86 strlcat(xpath
, "/join-prune-interval", sizeof(xpath
));
88 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
90 return nb_cli_apply_changes(vty
, NULL
);
93 int pim_process_spt_switchover_infinity_cmd(struct vty
*vty
)
96 char spt_plist_xpath
[XPATH_MAXLEN
];
97 char spt_action_xpath
[XPATH_MAXLEN
];
99 vrfname
= pim_cli_get_vrf_name(vty
);
101 return CMD_WARNING_CONFIG_FAILED
;
103 snprintf(spt_plist_xpath
, sizeof(spt_plist_xpath
),
104 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
105 FRR_PIM_AF_XPATH_VAL
);
106 strlcat(spt_plist_xpath
, "/spt-switchover/spt-infinity-prefix-list",
107 sizeof(spt_plist_xpath
));
109 snprintf(spt_action_xpath
, sizeof(spt_action_xpath
),
110 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
111 FRR_PIM_AF_XPATH_VAL
);
112 strlcat(spt_action_xpath
, "/spt-switchover/spt-action",
113 sizeof(spt_action_xpath
));
115 if (yang_dnode_exists(vty
->candidate_config
->dnode
, spt_plist_xpath
))
116 nb_cli_enqueue_change(vty
, spt_plist_xpath
, NB_OP_DESTROY
,
118 nb_cli_enqueue_change(vty
, spt_action_xpath
, NB_OP_MODIFY
,
121 return nb_cli_apply_changes(vty
, NULL
);
124 int pim_process_spt_switchover_prefixlist_cmd(struct vty
*vty
,
128 char spt_plist_xpath
[XPATH_MAXLEN
];
129 char spt_action_xpath
[XPATH_MAXLEN
];
131 vrfname
= pim_cli_get_vrf_name(vty
);
133 return CMD_WARNING_CONFIG_FAILED
;
135 snprintf(spt_plist_xpath
, sizeof(spt_plist_xpath
),
136 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
137 FRR_PIM_AF_XPATH_VAL
);
138 strlcat(spt_plist_xpath
, "/spt-switchover/spt-infinity-prefix-list",
139 sizeof(spt_plist_xpath
));
141 snprintf(spt_action_xpath
, sizeof(spt_action_xpath
),
142 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
143 FRR_PIM_AF_XPATH_VAL
);
144 strlcat(spt_action_xpath
, "/spt-switchover/spt-action",
145 sizeof(spt_action_xpath
));
147 nb_cli_enqueue_change(vty
, spt_action_xpath
, NB_OP_MODIFY
,
149 nb_cli_enqueue_change(vty
, spt_plist_xpath
, NB_OP_MODIFY
,
152 return nb_cli_apply_changes(vty
, NULL
);
155 int pim_process_no_spt_switchover_cmd(struct vty
*vty
)
158 char spt_plist_xpath
[XPATH_MAXLEN
];
159 char spt_action_xpath
[XPATH_MAXLEN
];
161 vrfname
= pim_cli_get_vrf_name(vty
);
163 return CMD_WARNING_CONFIG_FAILED
;
165 snprintf(spt_plist_xpath
, sizeof(spt_plist_xpath
),
166 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
167 FRR_PIM_AF_XPATH_VAL
);
168 strlcat(spt_plist_xpath
, "/spt-switchover/spt-infinity-prefix-list",
169 sizeof(spt_plist_xpath
));
171 snprintf(spt_action_xpath
, sizeof(spt_action_xpath
),
172 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
173 FRR_PIM_AF_XPATH_VAL
);
174 strlcat(spt_action_xpath
, "/spt-switchover/spt-action",
175 sizeof(spt_action_xpath
));
177 nb_cli_enqueue_change(vty
, spt_plist_xpath
, NB_OP_DESTROY
, NULL
);
178 nb_cli_enqueue_change(vty
, spt_action_xpath
, NB_OP_MODIFY
,
179 "PIM_SPT_IMMEDIATE");
181 return nb_cli_apply_changes(vty
, NULL
);
184 int pim_process_pim_packet_cmd(struct vty
*vty
, const char *packet
)
186 char xpath
[XPATH_MAXLEN
];
188 snprintf(xpath
, sizeof(xpath
), FRR_PIM_ROUTER_XPATH
,
189 FRR_PIM_AF_XPATH_VAL
);
190 strlcat(xpath
, "/packets", sizeof(xpath
));
192 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, packet
);
194 return nb_cli_apply_changes(vty
, NULL
);
197 int pim_process_no_pim_packet_cmd(struct vty
*vty
)
199 char xpath
[XPATH_MAXLEN
];
201 snprintf(xpath
, sizeof(xpath
), FRR_PIM_ROUTER_XPATH
,
202 FRR_PIM_AF_XPATH_VAL
);
203 strlcat(xpath
, "/packets", sizeof(xpath
));
205 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
207 return nb_cli_apply_changes(vty
, NULL
);
210 int pim_process_keepalivetimer_cmd(struct vty
*vty
, const char *kat
)
213 char ka_timer_xpath
[XPATH_MAXLEN
];
215 vrfname
= pim_cli_get_vrf_name(vty
);
217 return CMD_WARNING_CONFIG_FAILED
;
219 snprintf(ka_timer_xpath
, sizeof(ka_timer_xpath
), FRR_PIM_VRF_XPATH
,
220 "frr-pim:pimd", "pim", vrfname
, FRR_PIM_AF_XPATH_VAL
);
221 strlcat(ka_timer_xpath
, "/keep-alive-timer", sizeof(ka_timer_xpath
));
223 nb_cli_enqueue_change(vty
, ka_timer_xpath
, NB_OP_MODIFY
,
226 return nb_cli_apply_changes(vty
, NULL
);
229 int pim_process_no_keepalivetimer_cmd(struct vty
*vty
)
232 char ka_timer_xpath
[XPATH_MAXLEN
];
234 vrfname
= pim_cli_get_vrf_name(vty
);
236 return CMD_WARNING_CONFIG_FAILED
;
238 snprintf(ka_timer_xpath
, sizeof(ka_timer_xpath
), FRR_PIM_VRF_XPATH
,
239 "frr-pim:pimd", "pim", vrfname
, FRR_PIM_AF_XPATH_VAL
);
240 strlcat(ka_timer_xpath
, "/keep-alive-timer", sizeof(ka_timer_xpath
));
242 nb_cli_enqueue_change(vty
, ka_timer_xpath
, NB_OP_DESTROY
, NULL
);
244 return nb_cli_apply_changes(vty
, NULL
);
247 int pim_process_rp_kat_cmd(struct vty
*vty
, const char *rpkat
)
250 char rp_ka_timer_xpath
[XPATH_MAXLEN
];
252 vrfname
= pim_cli_get_vrf_name(vty
);
254 return CMD_WARNING_CONFIG_FAILED
;
256 snprintf(rp_ka_timer_xpath
, sizeof(rp_ka_timer_xpath
),
257 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
258 FRR_PIM_AF_XPATH_VAL
);
259 strlcat(rp_ka_timer_xpath
, "/rp-keep-alive-timer",
260 sizeof(rp_ka_timer_xpath
));
262 nb_cli_enqueue_change(vty
, rp_ka_timer_xpath
, NB_OP_MODIFY
,
265 return nb_cli_apply_changes(vty
, NULL
);
268 int pim_process_no_rp_kat_cmd(struct vty
*vty
)
272 char rp_ka_timer_xpath
[XPATH_MAXLEN
];
274 char rs_timer_xpath
[XPATH_MAXLEN
];
276 snprintf(rs_timer_xpath
, sizeof(rs_timer_xpath
),
277 FRR_PIM_ROUTER_XPATH
, FRR_PIM_AF_XPATH_VAL
);
278 strlcat(rs_timer_xpath
, "/register-suppress-time",
279 sizeof(rs_timer_xpath
));
282 v
= yang_dnode_get_uint16(vty
->candidate_config
->dnode
,
284 v
= 3 * v
+ PIM_REGISTER_PROBE_TIME_DEFAULT
;
287 snprintf(rp_ka_timer
, sizeof(rp_ka_timer
), "%u", v
);
289 vrfname
= pim_cli_get_vrf_name(vty
);
291 return CMD_WARNING_CONFIG_FAILED
;
293 snprintf(rp_ka_timer_xpath
, sizeof(rp_ka_timer_xpath
),
294 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
295 FRR_PIM_AF_XPATH_VAL
);
296 strlcat(rp_ka_timer_xpath
, "/rp-keep-alive-timer",
297 sizeof(rp_ka_timer_xpath
));
299 nb_cli_enqueue_change(vty
, rp_ka_timer_xpath
, NB_OP_MODIFY
,
302 return nb_cli_apply_changes(vty
, NULL
);
305 int pim_process_register_suppress_cmd(struct vty
*vty
, const char *rst
)
307 char xpath
[XPATH_MAXLEN
];
309 snprintf(xpath
, sizeof(xpath
), FRR_PIM_ROUTER_XPATH
,
310 FRR_PIM_AF_XPATH_VAL
);
311 strlcat(xpath
, "/register-suppress-time", sizeof(xpath
));
313 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, rst
);
315 return nb_cli_apply_changes(vty
, NULL
);
318 int pim_process_no_register_suppress_cmd(struct vty
*vty
)
320 char xpath
[XPATH_MAXLEN
];
322 snprintf(xpath
, sizeof(xpath
), FRR_PIM_ROUTER_XPATH
,
323 FRR_PIM_AF_XPATH_VAL
);
324 strlcat(xpath
, "/register-suppress-time", sizeof(xpath
));
326 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
328 return nb_cli_apply_changes(vty
, NULL
);
331 int pim_process_ip_pim_cmd(struct vty
*vty
)
333 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
, "true");
335 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
336 FRR_PIM_AF_XPATH_VAL
);
339 int pim_process_no_ip_pim_cmd(struct vty
*vty
)
341 const struct lyd_node
*mld_enable_dnode
;
342 char mld_if_xpath
[XPATH_MAXLEN
];
345 snprintf(mld_if_xpath
, sizeof(mld_if_xpath
),
346 "%s/frr-gmp:gmp/address-family[address-family='%s']",
347 VTY_CURR_XPATH
, FRR_PIM_AF_XPATH_VAL
);
349 if (printed
>= (int)(sizeof(mld_if_xpath
))) {
350 vty_out(vty
, "Xpath too long (%d > %u)", printed
+ 1,
352 return CMD_WARNING_CONFIG_FAILED
;
355 mld_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
356 FRR_GMP_ENABLE_XPATH
, VTY_CURR_XPATH
,
357 FRR_PIM_AF_XPATH_VAL
);
359 if (!mld_enable_dnode
) {
360 nb_cli_enqueue_change(vty
, mld_if_xpath
, NB_OP_DESTROY
, NULL
);
361 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
363 if (!yang_dnode_get_bool(mld_enable_dnode
, ".")) {
364 nb_cli_enqueue_change(vty
, mld_if_xpath
, NB_OP_DESTROY
,
366 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
368 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
372 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
373 FRR_PIM_AF_XPATH_VAL
);
376 int pim_process_ip_pim_drprio_cmd(struct vty
*vty
, const char *drpriority_str
)
378 nb_cli_enqueue_change(vty
, "./dr-priority", NB_OP_MODIFY
,
381 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
382 FRR_PIM_AF_XPATH_VAL
);
385 int pim_process_no_ip_pim_drprio_cmd(struct vty
*vty
)
387 nb_cli_enqueue_change(vty
, "./dr-priority", NB_OP_DESTROY
, NULL
);
389 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
390 FRR_PIM_AF_XPATH_VAL
);
393 int pim_process_ip_pim_hello_cmd(struct vty
*vty
, const char *hello_str
,
394 const char *hold_str
)
396 const struct lyd_node
*mld_enable_dnode
;
398 mld_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
399 FRR_GMP_ENABLE_XPATH
, VTY_CURR_XPATH
,
400 FRR_PIM_AF_XPATH_VAL
);
402 if (!mld_enable_dnode
) {
403 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
406 if (!yang_dnode_get_bool(mld_enable_dnode
, "."))
407 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
411 nb_cli_enqueue_change(vty
, "./hello-interval", NB_OP_MODIFY
, hello_str
);
414 nb_cli_enqueue_change(vty
, "./hello-holdtime", NB_OP_MODIFY
,
417 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
418 FRR_PIM_AF_XPATH_VAL
);
421 int pim_process_no_ip_pim_hello_cmd(struct vty
*vty
)
423 nb_cli_enqueue_change(vty
, "./hello-interval", NB_OP_DESTROY
, NULL
);
424 nb_cli_enqueue_change(vty
, "./hello-holdtime", NB_OP_DESTROY
, NULL
);
426 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
427 FRR_PIM_AF_XPATH_VAL
);
430 int pim_process_ip_pim_activeactive_cmd(struct vty
*vty
, const char *no
)
433 nb_cli_enqueue_change(vty
, "./active-active", NB_OP_MODIFY
,
436 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
439 nb_cli_enqueue_change(vty
, "./active-active", NB_OP_MODIFY
,
443 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
444 FRR_PIM_AF_XPATH_VAL
);
447 int pim_process_ip_pim_boundary_oil_cmd(struct vty
*vty
, const char *oil
)
449 nb_cli_enqueue_change(vty
, "./multicast-boundary-oil", NB_OP_MODIFY
,
452 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
453 FRR_PIM_AF_XPATH_VAL
);
456 int pim_process_no_ip_pim_boundary_oil_cmd(struct vty
*vty
)
458 nb_cli_enqueue_change(vty
, "./multicast-boundary-oil", NB_OP_DESTROY
,
461 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
462 FRR_PIM_AF_XPATH_VAL
);
465 int pim_process_ip_mroute_cmd(struct vty
*vty
, const char *interface
,
466 const char *group_str
, const char *source_str
)
468 nb_cli_enqueue_change(vty
, "./oif", NB_OP_MODIFY
, interface
);
471 char buf
[SRCDEST2STR_BUFFER
];
473 inet_ntop(AF_INET6
, &in6addr_any
, buf
, sizeof(buf
));
474 return nb_cli_apply_changes(vty
, FRR_PIM_MROUTE_XPATH
,
475 FRR_PIM_AF_XPATH_VAL
, buf
,
479 return nb_cli_apply_changes(vty
, FRR_PIM_MROUTE_XPATH
,
480 FRR_PIM_AF_XPATH_VAL
, source_str
,
484 int pim_process_no_ip_mroute_cmd(struct vty
*vty
, const char *interface
,
485 const char *group_str
, const char *source_str
)
487 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
490 char buf
[SRCDEST2STR_BUFFER
];
492 inet_ntop(AF_INET6
, &in6addr_any
, buf
, sizeof(buf
));
493 return nb_cli_apply_changes(vty
, FRR_PIM_MROUTE_XPATH
,
494 FRR_PIM_AF_XPATH_VAL
, buf
,
498 return nb_cli_apply_changes(vty
, FRR_PIM_MROUTE_XPATH
,
499 FRR_PIM_AF_XPATH_VAL
, source_str
,
503 int pim_process_rp_cmd(struct vty
*vty
, const char *rp_str
,
504 const char *group_str
)
507 char rp_group_xpath
[XPATH_MAXLEN
];
512 result
= str2prefix(group_str
, &group
);
516 prefix_copy(&temp
, &group
);
518 if (!prefix_same(&group
, &temp
)) {
519 vty_out(vty
, "%% Inconsistent address and mask: %s\n",
521 return CMD_WARNING_CONFIG_FAILED
;
526 vty_out(vty
, "%% Bad group address specified: %s\n", group_str
);
527 return CMD_WARNING_CONFIG_FAILED
;
530 result
= inet_pton(PIM_AF
, rp_str
, &rp_addr
);
532 vty_out(vty
, "%% Bad RP address specified: %s\n", rp_str
);
533 return CMD_WARNING_CONFIG_FAILED
;
536 vrfname
= pim_cli_get_vrf_name(vty
);
538 return CMD_WARNING_CONFIG_FAILED
;
540 snprintf(rp_group_xpath
, sizeof(rp_group_xpath
),
541 FRR_PIM_STATIC_RP_XPATH
, "frr-pim:pimd", "pim", vrfname
,
542 FRR_PIM_AF_XPATH_VAL
, rp_str
);
543 strlcat(rp_group_xpath
, "/group-list", sizeof(rp_group_xpath
));
545 nb_cli_enqueue_change(vty
, rp_group_xpath
, NB_OP_CREATE
, group_str
);
547 return nb_cli_apply_changes(vty
, NULL
);
550 int pim_process_no_rp_cmd(struct vty
*vty
, const char *rp_str
,
551 const char *group_str
)
553 char group_list_xpath
[XPATH_MAXLEN
];
554 char group_xpath
[XPATH_MAXLEN
];
555 char rp_xpath
[XPATH_MAXLEN
];
558 const struct lyd_node
*group_dnode
;
560 vrfname
= pim_cli_get_vrf_name(vty
);
562 return CMD_WARNING_CONFIG_FAILED
;
564 snprintf(rp_xpath
, sizeof(rp_xpath
), FRR_PIM_STATIC_RP_XPATH
,
565 "frr-pim:pimd", "pim", vrfname
, FRR_PIM_AF_XPATH_VAL
, rp_str
);
567 printed
= snprintf(group_list_xpath
, sizeof(group_list_xpath
),
568 "%s/group-list", rp_xpath
);
570 if (printed
>= (int)(sizeof(group_list_xpath
))) {
571 vty_out(vty
, "Xpath too long (%d > %u)", printed
+ 1,
573 return CMD_WARNING_CONFIG_FAILED
;
576 printed
= snprintf(group_xpath
, sizeof(group_xpath
), "%s[.='%s']",
577 group_list_xpath
, group_str
);
579 if (printed
>= (int)(sizeof(group_xpath
))) {
580 vty_out(vty
, "Xpath too long (%d > %u)", printed
+ 1,
582 return CMD_WARNING_CONFIG_FAILED
;
585 if (!yang_dnode_exists(vty
->candidate_config
->dnode
, group_xpath
)) {
586 vty_out(vty
, "%% Unable to find specified RP\n");
590 group_dnode
= yang_dnode_get(vty
->candidate_config
->dnode
, group_xpath
);
592 if (yang_is_last_list_dnode(group_dnode
))
593 nb_cli_enqueue_change(vty
, rp_xpath
, NB_OP_DESTROY
, NULL
);
595 nb_cli_enqueue_change(vty
, group_list_xpath
, NB_OP_DESTROY
,
598 return nb_cli_apply_changes(vty
, NULL
);