]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_cmd_common.c
pim6d: Adding "ipv6 pim" CLI
[mirror_frr.git] / pimd / pim_cmd_common.c
1 /*
2 * PIM for IPv6 FRR
3 * Copyright (C) 2022 Vmware, Inc.
4 * Mobashshera Rasool <mrasool@vmware.com>
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include <zebra.h>
22
23 #include "lib/json.h"
24 #include "command.h"
25 #include "if.h"
26 #include "prefix.h"
27 #include "zclient.h"
28 #include "plist.h"
29 #include "hash.h"
30 #include "nexthop.h"
31 #include "vrf.h"
32 #include "ferr.h"
33
34 #include "pimd.h"
35 #include "pim_vty.h"
36 #include "lib/northbound_cli.h"
37 #include "pim_errors.h"
38 #include "pim_nb.h"
39 #include "pim_cmd_common.h"
40
41 /**
42 * Get current node VRF name.
43 *
44 * NOTE:
45 * In case of failure it will print error message to user.
46 *
47 * \returns name or NULL if failed to get VRF.
48 */
49 const char *pim_cli_get_vrf_name(struct vty *vty)
50 {
51 const struct lyd_node *vrf_node;
52
53 /* Not inside any VRF context. */
54 if (vty->xpath_index == 0)
55 return VRF_DEFAULT_NAME;
56
57 vrf_node = yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
58 if (vrf_node == NULL) {
59 vty_out(vty, "%% Failed to get vrf dnode in configuration\n");
60 return NULL;
61 }
62
63 return yang_dnode_get_string(vrf_node, "./name");
64 }
65
66 int pim_process_join_prune_cmd(struct vty *vty, const char *jpi_str)
67 {
68 char xpath[XPATH_MAXLEN];
69
70 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
71 FRR_PIM_AF_XPATH_VAL);
72 strlcat(xpath, "/join-prune-interval", sizeof(xpath));
73
74 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, jpi_str);
75
76 return nb_cli_apply_changes(vty, NULL);
77 }
78
79 int pim_process_no_join_prune_cmd(struct vty *vty)
80 {
81 char xpath[XPATH_MAXLEN];
82
83 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
84 FRR_PIM_AF_XPATH_VAL);
85 strlcat(xpath, "/join-prune-interval", sizeof(xpath));
86
87 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
88
89 return nb_cli_apply_changes(vty, NULL);
90 }
91
92 int pim_process_spt_switchover_infinity_cmd(struct vty *vty)
93 {
94 const char *vrfname;
95 char spt_plist_xpath[XPATH_MAXLEN];
96 char spt_action_xpath[XPATH_MAXLEN];
97
98 vrfname = pim_cli_get_vrf_name(vty);
99 if (vrfname == NULL)
100 return CMD_WARNING_CONFIG_FAILED;
101
102 snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
103 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
104 FRR_PIM_AF_XPATH_VAL);
105 strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
106 sizeof(spt_plist_xpath));
107
108 snprintf(spt_action_xpath, sizeof(spt_action_xpath),
109 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
110 FRR_PIM_AF_XPATH_VAL);
111 strlcat(spt_action_xpath, "/spt-switchover/spt-action",
112 sizeof(spt_action_xpath));
113
114 if (yang_dnode_exists(vty->candidate_config->dnode, spt_plist_xpath))
115 nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY,
116 NULL);
117 nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
118 "PIM_SPT_INFINITY");
119
120 return nb_cli_apply_changes(vty, NULL);
121 }
122
123 int pim_process_spt_switchover_prefixlist_cmd(struct vty *vty,
124 const char *plist)
125 {
126 const char *vrfname;
127 char spt_plist_xpath[XPATH_MAXLEN];
128 char spt_action_xpath[XPATH_MAXLEN];
129
130 vrfname = pim_cli_get_vrf_name(vty);
131 if (vrfname == NULL)
132 return CMD_WARNING_CONFIG_FAILED;
133
134 snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
135 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
136 FRR_PIM_AF_XPATH_VAL);
137 strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
138 sizeof(spt_plist_xpath));
139
140 snprintf(spt_action_xpath, sizeof(spt_action_xpath),
141 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
142 FRR_PIM_AF_XPATH_VAL);
143 strlcat(spt_action_xpath, "/spt-switchover/spt-action",
144 sizeof(spt_action_xpath));
145
146 nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
147 "PIM_SPT_INFINITY");
148 nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_MODIFY,
149 plist);
150
151 return nb_cli_apply_changes(vty, NULL);
152 }
153
154 int pim_process_no_spt_switchover_cmd(struct vty *vty)
155 {
156 const char *vrfname;
157 char spt_plist_xpath[XPATH_MAXLEN];
158 char spt_action_xpath[XPATH_MAXLEN];
159
160 vrfname = pim_cli_get_vrf_name(vty);
161 if (vrfname == NULL)
162 return CMD_WARNING_CONFIG_FAILED;
163
164 snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
165 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
166 FRR_PIM_AF_XPATH_VAL);
167 strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
168 sizeof(spt_plist_xpath));
169
170 snprintf(spt_action_xpath, sizeof(spt_action_xpath),
171 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
172 FRR_PIM_AF_XPATH_VAL);
173 strlcat(spt_action_xpath, "/spt-switchover/spt-action",
174 sizeof(spt_action_xpath));
175
176 nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY, NULL);
177 nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
178 "PIM_SPT_IMMEDIATE");
179
180 return nb_cli_apply_changes(vty, NULL);
181 }
182
183 int pim_process_pim_packet_cmd(struct vty *vty, const char *packet)
184 {
185 char xpath[XPATH_MAXLEN];
186
187 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
188 FRR_PIM_AF_XPATH_VAL);
189 strlcat(xpath, "/packets", sizeof(xpath));
190
191 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, packet);
192
193 return nb_cli_apply_changes(vty, NULL);
194 }
195
196 int pim_process_no_pim_packet_cmd(struct vty *vty)
197 {
198 char xpath[XPATH_MAXLEN];
199
200 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
201 FRR_PIM_AF_XPATH_VAL);
202 strlcat(xpath, "/packets", sizeof(xpath));
203
204 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
205
206 return nb_cli_apply_changes(vty, NULL);
207 }
208
209 int pim_process_keepalivetimer_cmd(struct vty *vty, const char *kat)
210 {
211 const char *vrfname;
212 char ka_timer_xpath[XPATH_MAXLEN];
213
214 vrfname = pim_cli_get_vrf_name(vty);
215 if (vrfname == NULL)
216 return CMD_WARNING_CONFIG_FAILED;
217
218 snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_VRF_XPATH,
219 "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL);
220 strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
221
222 nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_MODIFY,
223 kat);
224
225 return nb_cli_apply_changes(vty, NULL);
226 }
227
228 int pim_process_no_keepalivetimer_cmd(struct vty *vty)
229 {
230 const char *vrfname;
231 char ka_timer_xpath[XPATH_MAXLEN];
232
233 vrfname = pim_cli_get_vrf_name(vty);
234 if (vrfname == NULL)
235 return CMD_WARNING_CONFIG_FAILED;
236
237 snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_VRF_XPATH,
238 "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL);
239 strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
240
241 nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_DESTROY, NULL);
242
243 return nb_cli_apply_changes(vty, NULL);
244 }
245
246 int pim_process_rp_kat_cmd(struct vty *vty, const char *rpkat)
247 {
248 const char *vrfname;
249 char rp_ka_timer_xpath[XPATH_MAXLEN];
250
251 vrfname = pim_cli_get_vrf_name(vty);
252 if (vrfname == NULL)
253 return CMD_WARNING_CONFIG_FAILED;
254
255 snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
256 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
257 FRR_PIM_AF_XPATH_VAL);
258 strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
259 sizeof(rp_ka_timer_xpath));
260
261 nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
262 rpkat);
263
264 return nb_cli_apply_changes(vty, NULL);
265 }
266
267 int pim_process_no_rp_kat_cmd(struct vty *vty)
268 {
269 const char *vrfname;
270 char rp_ka_timer[6];
271 char rp_ka_timer_xpath[XPATH_MAXLEN];
272 uint v;
273 char rs_timer_xpath[XPATH_MAXLEN];
274
275 snprintf(rs_timer_xpath, sizeof(rs_timer_xpath),
276 FRR_PIM_ROUTER_XPATH, FRR_PIM_AF_XPATH_VAL);
277 strlcat(rs_timer_xpath, "/register-suppress-time",
278 sizeof(rs_timer_xpath));
279
280 /* RFC4601 */
281 v = yang_dnode_get_uint16(vty->candidate_config->dnode,
282 rs_timer_xpath);
283 v = 3 * v + PIM_REGISTER_PROBE_TIME_DEFAULT;
284 if (v > UINT16_MAX)
285 v = UINT16_MAX;
286 snprintf(rp_ka_timer, sizeof(rp_ka_timer), "%u", v);
287
288 vrfname = pim_cli_get_vrf_name(vty);
289 if (vrfname == NULL)
290 return CMD_WARNING_CONFIG_FAILED;
291
292 snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
293 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
294 FRR_PIM_AF_XPATH_VAL);
295 strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
296 sizeof(rp_ka_timer_xpath));
297
298 nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
299 rp_ka_timer);
300
301 return nb_cli_apply_changes(vty, NULL);
302 }
303
304 int pim_process_register_suppress_cmd(struct vty *vty, const char *rst)
305 {
306 char xpath[XPATH_MAXLEN];
307
308 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
309 FRR_PIM_AF_XPATH_VAL);
310 strlcat(xpath, "/register-suppress-time", sizeof(xpath));
311
312 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, rst);
313
314 return nb_cli_apply_changes(vty, NULL);
315 }
316
317 int pim_process_no_register_suppress_cmd(struct vty *vty)
318 {
319 char xpath[XPATH_MAXLEN];
320
321 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
322 FRR_PIM_AF_XPATH_VAL);
323 strlcat(xpath, "/register-suppress-time", sizeof(xpath));
324
325 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
326
327 return nb_cli_apply_changes(vty, NULL);
328 }
329
330 int pim_process_ip_pim_cmd(struct vty *vty)
331 {
332 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
333
334 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
335 FRR_PIM_AF_XPATH_VAL);
336 }
337
338 int pim_process_no_ip_pim_cmd(struct vty *vty)
339 {
340 const struct lyd_node *mld_enable_dnode;
341 char mld_if_xpath[XPATH_MAXLEN];
342
343 int printed =
344 snprintf(mld_if_xpath, sizeof(mld_if_xpath),
345 "%s/frr-gmp:gmp/address-family[address-family='%s']",
346 VTY_CURR_XPATH, FRR_PIM_AF_XPATH_VAL);
347
348 if (printed >= (int)(sizeof(mld_if_xpath))) {
349 vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
350 XPATH_MAXLEN);
351 return CMD_WARNING_CONFIG_FAILED;
352 }
353
354 mld_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
355 FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
356 FRR_PIM_AF_XPATH_VAL);
357
358 if (!mld_enable_dnode) {
359 nb_cli_enqueue_change(vty, mld_if_xpath, NB_OP_DESTROY, NULL);
360 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
361 } else {
362 if (!yang_dnode_get_bool(mld_enable_dnode, ".")) {
363 nb_cli_enqueue_change(vty, mld_if_xpath, NB_OP_DESTROY,
364 NULL);
365 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
366 } else
367 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
368 "false");
369 }
370
371 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
372 FRR_PIM_AF_XPATH_VAL);
373 }