diff options
author | Sarita Patra <saritap@vmware.com> | 2020-10-23 16:52:41 +0200 |
---|---|---|
committer | Sarita Patra <saritap@vmware.com> | 2020-11-06 12:42:00 +0100 |
commit | 7003f6361359f58b9a7bc1a9ca0f4a3423e35b49 (patch) | |
tree | 642d0f96edaa6717943f26cb2a23f5534ee3feba /pimd | |
parent | pimd: Northbound implementation for mlag, register-accept-list commands (diff) | |
download | frr-7003f6361359f58b9a7bc1a9ca0f4a3423e35b49.tar.xz frr-7003f6361359f58b9a7bc1a9ca0f4a3423e35b49.zip |
pimd: Northbound implementation for rp commands.
ip_pim_rp
ip_pim_rp_prefix_list
no_ip_pim_rp
no_ip_pim_rp_prefix_list
module: frr-pim-rp
augment /frr-routing:routing/frr-routing:control-plane-protocols/frr-routing:control-plane-protocol/frr-pim:pim/frr-pim:address-family:
+--rw rp
+--rw static-rp
+--rw rp-list* [rp-address]
+--rw rp-address ietf-inet-types:ip-address
+--rw (group-list-or-prefix-list)?
+--:(group-list)
| +--rw group-list* ip-multicast-group-address-prefix
+--:(prefix-list)
+--rw prefix-list? plist-ref
Signed-off-by: Sarita Patra <saritap@vmware.com>
Diffstat (limited to 'pimd')
-rw-r--r-- | pimd/pim_cmd.c | 267 | ||||
-rw-r--r-- | pimd/pim_nb_config.c | 243 | ||||
-rw-r--r-- | pimd/pim_rp.c | 33 | ||||
-rw-r--r-- | pimd/pim_rp.h | 2 |
4 files changed, 375 insertions, 170 deletions
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 137dd8a7f..bac9165bd 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -6689,57 +6689,6 @@ DEFUN (show_ip_ssmpingd, return CMD_SUCCESS; } -static int pim_rp_cmd_worker(struct pim_instance *pim, struct vty *vty, - const char *rp, const char *group, - const char *plist) -{ - int result; - - result = pim_rp_new_config(pim, rp, group, plist); - - if (result == PIM_GROUP_BAD_ADDR_MASK_COMBO) { - vty_out(vty, "%% Inconsistent address and mask: %s\n", - group ? group : "No Group Address"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (result == PIM_GROUP_BAD_ADDRESS) { - vty_out(vty, "%% Bad group address specified: %s\n", - group ? group : "No Group Address"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (result == PIM_RP_BAD_ADDRESS) { - vty_out(vty, "%% Bad RP address specified: %s\n", rp); - return CMD_WARNING_CONFIG_FAILED; - } - - if (result == PIM_RP_NO_PATH) { - vty_out(vty, "%% No Path to RP address specified: %s\n", rp); - return CMD_WARNING; - } - - if (result == PIM_GROUP_OVERLAP) { - vty_out(vty, - "%% Group range specified cannot exact match another\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (result == PIM_GROUP_PFXLIST_OVERLAP) { - vty_out(vty, - "%% This group is already covered by a RP prefix-list\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (result == PIM_RP_PFXLIST_IN_USE) { - vty_out(vty, - "%% The same prefix-list cannot be applied to multiple RPs\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; -} - DEFUN (ip_pim_spt_switchover_infinity, ip_pim_spt_switchover_infinity_cmd, "ip pim spt-switchover infinity-and-beyond", @@ -7345,15 +7294,66 @@ DEFUN (ip_pim_rp, "ip address of RP\n" "Group Address range to cover\n") { - PIM_DECLVAR_CONTEXT(vrf, pim); - int idx_ipv4 = 3; + const struct lyd_node *vrf_dnode; + const char *vrfname; + int idx_rp = 3, idx_group = 4; + char rp_group_xpath[XPATH_MAXLEN]; + int result = 0; + struct prefix group; + struct in_addr rp_addr; + const char *group_str = + (argc == 5) ? argv[idx_group]->arg : "224.0.0.0/4"; + + result = str2prefix(group_str, &group); + if (result) { + struct prefix temp; + + prefix_copy(&temp, &group); + apply_mask(&temp); + if (!prefix_same(&group, &temp)) { + vty_out(vty, "%% Inconsistent address and mask: %s\n", + group_str); + return CMD_WARNING_CONFIG_FAILED; + } + } - if (argc == (idx_ipv4 + 1)) - return pim_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg, NULL, - NULL); - else - return pim_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg, - argv[idx_ipv4 + 1]->arg, NULL); + if (!result) { + vty_out(vty, "%% Bad group address specified: %s\n", + group_str); + return CMD_WARNING_CONFIG_FAILED; + } + + result = inet_pton(AF_INET, argv[idx_rp]->arg, &rp_addr); + if (result <= 0) { + vty_out(vty, "%% Bad RP address specified: %s\n", + argv[idx_rp]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + if (vty->xpath_index) { + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, + VTY_CURR_XPATH); + + if (!vrf_dnode) { + vty_out(vty, + "%% Failed to get vrf dnode in candidate db\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); + } else + vrfname = VRF_DEFAULT_NAME; + + snprintf(rp_group_xpath, sizeof(rp_group_xpath), + FRR_PIM_STATIC_RP_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", + argv[idx_rp]->arg); + strlcat(rp_group_xpath, "/group-list", sizeof(rp_group_xpath)); + + nb_cli_enqueue_change(vty, rp_group_xpath, NB_OP_CREATE, group_str); + + return nb_cli_apply_changes(vty, NULL); } DEFUN (ip_pim_rp_prefix_list, @@ -7366,33 +7366,36 @@ DEFUN (ip_pim_rp_prefix_list, "group prefix-list filter\n" "Name of a prefix-list\n") { - PIM_DECLVAR_CONTEXT(vrf, pim); - return pim_rp_cmd_worker(pim, vty, argv[3]->arg, NULL, argv[5]->arg); -} + int idx_rp = 3, idx_plist = 5; + const struct lyd_node *vrf_dnode; + const char *vrfname; + char rp_plist_xpath[XPATH_MAXLEN]; -static int pim_no_rp_cmd_worker(struct pim_instance *pim, struct vty *vty, - const char *rp, const char *group, - const char *plist) -{ - int result = pim_rp_del_config(pim, rp, group, plist); + if (vty->xpath_index) { + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, + VTY_CURR_XPATH); - if (result == PIM_GROUP_BAD_ADDRESS) { - vty_out(vty, "%% Bad group address specified: %s\n", - group ? group : "No Group Address"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!vrf_dnode) { + vty_out(vty, + "%% Failed to get vrf dnode in candidate db\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_RP_BAD_ADDRESS) { - vty_out(vty, "%% Bad RP address specified: %s\n", rp); - return CMD_WARNING_CONFIG_FAILED; - } + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); + } else + vrfname = VRF_DEFAULT_NAME; - if (result == PIM_RP_NOT_FOUND) { - vty_out(vty, "%% Unable to find specified RP\n"); - return CMD_WARNING_CONFIG_FAILED; - } + snprintf(rp_plist_xpath, sizeof(rp_plist_xpath), + FRR_PIM_STATIC_RP_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", + argv[idx_rp]->arg); + strlcat(rp_plist_xpath, "/prefix-list", sizeof(rp_plist_xpath)); - return CMD_SUCCESS; + nb_cli_enqueue_change(vty, rp_plist_xpath, NB_OP_MODIFY, + argv[idx_plist]->arg); + + return nb_cli_apply_changes(vty, NULL); } DEFUN (no_ip_pim_rp, @@ -7405,15 +7408,55 @@ DEFUN (no_ip_pim_rp, "ip address of RP\n" "Group Address range to cover\n") { - PIM_DECLVAR_CONTEXT(vrf, pim); - int idx_ipv4 = 4, idx_group = 0; + int idx_rp = 4, idx_group = 5; + const char *group_str = + (argc == 6) ? argv[idx_group]->arg : "224.0.0.0/4"; + char group_xpath[XPATH_MAXLEN]; + char temp_xpath[XPATH_MAXLEN]; + char rp_xpath[XPATH_MAXLEN]; + const struct lyd_node *vrf_dnode; + const char *vrfname; + const struct lyd_node *group_dnode; - if (argv_find(argv, argc, "A.B.C.D/M", &idx_group)) - return pim_no_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg, - argv[idx_group]->arg, NULL); + if (vty->xpath_index) { + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, + VTY_CURR_XPATH); + + if (!vrf_dnode) { + vty_out(vty, + "%% Failed to get vrf dnode in candidate db\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); + } else + vrfname = VRF_DEFAULT_NAME; + + snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", + argv[idx_rp]->arg); + + snprintf(group_xpath, sizeof(group_xpath), FRR_PIM_STATIC_RP_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", + argv[idx_rp]->arg); + snprintf(temp_xpath, sizeof(temp_xpath), "/group-list[.='%s']", + group_str); + strlcat(group_xpath, temp_xpath, sizeof(group_xpath)); + + if (!yang_dnode_exists(vty->candidate_config->dnode, group_xpath)) { + vty_out(vty, "%% Unable to find specified RP\n"); + return NB_OK; + } + + group_dnode = yang_dnode_get(vty->candidate_config->dnode, group_xpath); + + if (yang_is_last_list_dnode(group_dnode)) + nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL); else - return pim_no_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg, NULL, - NULL); + nb_cli_enqueue_change(vty, group_xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); } DEFUN (no_ip_pim_rp_prefix_list, @@ -7427,8 +7470,52 @@ DEFUN (no_ip_pim_rp_prefix_list, "group prefix-list filter\n" "Name of a prefix-list\n") { - PIM_DECLVAR_CONTEXT(vrf, pim); - return pim_no_rp_cmd_worker(pim, vty, argv[4]->arg, NULL, argv[6]->arg); + int idx_rp = 4; + int idx_plist = 6; + char rp_xpath[XPATH_MAXLEN]; + char plist_xpath[XPATH_MAXLEN]; + const struct lyd_node *vrf_dnode; + const char *vrfname; + const struct lyd_node *plist_dnode; + const char *plist; + + if (vty->xpath_index) { + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, + VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, + "%% Failed to get vrf dnode in candidate db\n"); + return CMD_WARNING_CONFIG_FAILED; + } + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); + } else + vrfname = VRF_DEFAULT_NAME; + + snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", + argv[idx_rp]->arg); + + snprintf(plist_xpath, sizeof(plist_xpath), FRR_PIM_STATIC_RP_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", + argv[idx_rp]->arg); + strlcat(plist_xpath, "/prefix-list", sizeof(plist_xpath)); + + plist_dnode = yang_dnode_get(vty->candidate_config->dnode, plist_xpath); + if (!plist_dnode) { + vty_out(vty, "%% Unable to find specified RP\n"); + return NB_OK; + } + + plist = yang_dnode_get_string(plist_dnode, plist_xpath); + if (strcmp(argv[idx_plist]->arg, plist)) { + vty_out(vty, "%% Unable to find specified RP\n"); + return NB_OK; + } + + nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); } DEFUN (ip_pim_ssm_prefix_list, diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c index c7ebebbeb..7f6d31c9f 100644 --- a/pimd/pim_nb_config.c +++ b/pimd/pim_nb_config.c @@ -439,6 +439,79 @@ static int ip_no_msdp_peer_cmd_worker(struct pim_instance *pim, return result ? NB_ERR : NB_OK; } +static int pim_rp_cmd_worker(struct pim_instance *pim, + struct in_addr rp_addr, + struct prefix group, const char *plist, + char *errmsg, size_t errmsg_len) +{ + char rp_str[INET_ADDRSTRLEN]; + int result; + + inet_ntop(AF_INET, &rp_addr, rp_str, sizeof(rp_str)); + + result = pim_rp_new(pim, rp_addr, group, plist, RP_SRC_STATIC); + + if (result == PIM_RP_NO_PATH) { + snprintf(errmsg, errmsg_len, + "No Path to RP address specified: %s", rp_str); + return NB_ERR_INCONSISTENCY; + } + + if (result == PIM_GROUP_OVERLAP) { + snprintf(errmsg, errmsg_len, + "Group range specified cannot exact match another"); + return NB_ERR_INCONSISTENCY; + } + + if (result == PIM_GROUP_PFXLIST_OVERLAP) { + snprintf(errmsg, errmsg_len, + "This group is already covered by a RP prefix-list"); + return NB_ERR_INCONSISTENCY; + } + + if (result == PIM_RP_PFXLIST_IN_USE) { + snprintf(errmsg, errmsg_len, + "The same prefix-list cannot be applied to multiple RPs"); + return NB_ERR_INCONSISTENCY; + } + + return NB_OK; +} + +static int pim_no_rp_cmd_worker(struct pim_instance *pim, + struct in_addr rp_addr, struct prefix group, + const char *plist, + char *errmsg, size_t errmsg_len) +{ + char rp_str[INET_ADDRSTRLEN]; + char group_str[PREFIX2STR_BUFFER]; + int result; + + inet_ntop(AF_INET, &rp_addr, rp_str, sizeof(rp_str)); + prefix2str(&group, group_str, sizeof(group_str)); + + result = pim_rp_del(pim, rp_addr, group, plist, RP_SRC_STATIC); + + if (result == PIM_GROUP_BAD_ADDRESS) { + snprintf(errmsg, errmsg_len, + "Bad group address specified: %s", group_str); + return NB_ERR_INCONSISTENCY; + } + + if (result == PIM_RP_BAD_ADDRESS) { + snprintf(errmsg, errmsg_len, + "Bad RP address specified: %s", rp_str); + return NB_ERR_INCONSISTENCY; + } + + if (result == PIM_RP_NOT_FOUND) { + snprintf(errmsg, errmsg_len, + "Unable to find specified RP"); + return NB_ERR_INCONSISTENCY; + } + + return NB_OK; +} static bool is_pim_interface(const struct lyd_node *dnode) { @@ -2346,16 +2419,47 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_destroy(struct nb_cb_destroy_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + struct vrf *vrf; + struct pim_instance *pim; + struct prefix group; + struct ipaddr rp_addr; + const char *plist; + int result = 0; - return NB_OK; + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + yang_dnode_get_ip(&rp_addr, args->dnode, "./rp-address"); + + if (yang_dnode_get(args->dnode, "./group-list")) { + yang_dnode_get_ipv4p(&group, args->dnode, + "./group-list"); + result = pim_no_rp_cmd_worker(pim, rp_addr.ip._v4_addr, + group, NULL, args->errmsg, + args->errmsg_len); + } + + else if (yang_dnode_get(args->dnode, "./prefix-list")) { + plist = yang_dnode_get_string(args->dnode, + "./prefix-list"); + str2prefix("224.0.0.0/4", &group); + result = pim_no_rp_cmd_worker(pim, rp_addr.ip._v4_addr, + group, plist, + args->errmsg, + args->errmsg_len); + } + + if (result) + return NB_ERR_INCONSISTENCY; + break; + } + + return NB_OK; } /* @@ -2363,30 +2467,53 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp */ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_group_list_create(struct nb_cb_create_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + struct vrf *vrf; + struct pim_instance *pim; + struct prefix group; + struct ipaddr rp_addr; - return NB_OK; + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + yang_dnode_get_ip(&rp_addr, args->dnode, "../rp-address"); + yang_dnode_get_ipv4p(&group, args->dnode, NULL); + + return pim_rp_cmd_worker(pim, rp_addr.ip._v4_addr, group, + NULL, args->errmsg, args->errmsg_len); + } + + return NB_OK; } int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_group_list_destroy(struct nb_cb_destroy_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + struct vrf *vrf; + struct pim_instance *pim; + struct prefix group; + struct ipaddr rp_addr; - return NB_OK; + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + yang_dnode_get_ip(&rp_addr, args->dnode, "../rp-address"); + yang_dnode_get_ipv4p(&group, args->dnode, NULL); + + return pim_no_rp_cmd_worker(pim, rp_addr.ip._v4_addr, group, + NULL, args->errmsg, + args->errmsg_len); + } + + return NB_OK; } /* @@ -2394,30 +2521,56 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp */ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_modify(struct nb_cb_modify_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + struct vrf *vrf; + struct pim_instance *pim; + struct prefix group; + struct ipaddr rp_addr; + const char *plist; - return NB_OK; + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + plist = yang_dnode_get_string(args->dnode, NULL); + yang_dnode_get_ip(&rp_addr, args->dnode, "../rp-address"); + str2prefix("224.0.0.0/4", &group); + return pim_rp_cmd_worker(pim, rp_addr.ip._v4_addr, group, + plist, args->errmsg, args->errmsg_len); + } + + return NB_OK; } int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_destroy(struct nb_cb_destroy_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + struct vrf *vrf; + struct pim_instance *pim; + struct prefix group; + struct ipaddr rp_addr; + const char *plist; - return NB_OK; + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + yang_dnode_get_ip(&rp_addr, args->dnode, "../rp-address"); + plist = yang_dnode_get_string(args->dnode, NULL); + str2prefix("224.0.0.0/4", &group); + return pim_no_rp_cmd_worker(pim, rp_addr.ip._v4_addr, group, + plist, args->errmsg, + args->errmsg_len); + break; + } + + return NB_OK; } /* diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 93fe787a9..c0aaf38c7 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -402,39 +402,6 @@ void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up) pim_zebra_update_all_interfaces(pim); } -int pim_rp_new_config(struct pim_instance *pim, const char *rp, - const char *group_range, const char *plist) -{ - int result = 0; - struct prefix group; - struct in_addr rp_addr; - - if (group_range == NULL) - result = str2prefix("224.0.0.0/4", &group); - else { - result = str2prefix(group_range, &group); - if (result) { - struct prefix temp; - - prefix_copy(&temp, &group); - apply_mask(&temp); - if (!prefix_same(&group, &temp)) - return PIM_GROUP_BAD_ADDR_MASK_COMBO; - } - } - - if (!result) - return PIM_GROUP_BAD_ADDRESS; - - result = inet_pton(AF_INET, rp, &rp_addr); - - if (result <= 0) - return PIM_RP_BAD_ADDRESS; - - result = pim_rp_new(pim, rp_addr, group, plist, RP_SRC_STATIC); - return result; -} - int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr, struct prefix group, const char *plist, enum rp_source rp_src_flag) diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index 6dc26c07a..8a12cb076 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -46,8 +46,6 @@ void pim_rp_free(struct pim_instance *pim); void pim_rp_list_hash_clean(void *data); -int pim_rp_new_config(struct pim_instance *pim, const char *rp, - const char *group, const char *plist); int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr, struct prefix group, const char *plist, enum rp_source rp_src_flag); |