mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-27 13:46:45 +00:00
pimd: Clean up pim RPF/NHT show commands
Moved `show ip rpf A.B.C.D` command here from zebra, deprecated and aliased to `show ip pim nexthop-lookup`. Allow group to be optional in the lookup command. Only validate group if source is ANY. Documented setting source via RP if not provided. Added new output if ANY source + group lookup is performed and no RP is found for the group. Updated output to include souce and group for lookup. Signed-off-by: Nathan Bahr <nbahr@atcorp.com>
This commit is contained in:
parent
9ce7f9b8e8
commit
5cce666d49
@ -2914,7 +2914,7 @@ DEFPY (show_ip_pim_nexthop,
|
|||||||
|
|
||||||
DEFPY (show_ip_pim_nexthop_lookup,
|
DEFPY (show_ip_pim_nexthop_lookup,
|
||||||
show_ip_pim_nexthop_lookup_cmd,
|
show_ip_pim_nexthop_lookup_cmd,
|
||||||
"show ip pim [vrf NAME] nexthop-lookup A.B.C.D$source A.B.C.D$group",
|
"show ip pim [vrf NAME] nexthop-lookup A.B.C.D$source [A.B.C.D$group]",
|
||||||
SHOW_STR
|
SHOW_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
PIM_STR
|
PIM_STR
|
||||||
@ -2926,6 +2926,14 @@ DEFPY (show_ip_pim_nexthop_lookup,
|
|||||||
return pim_show_nexthop_lookup_cmd_helper(vrf, vty, source, group);
|
return pim_show_nexthop_lookup_cmd_helper(vrf, vty, source, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALIAS_DEPRECATED (show_ip_pim_nexthop_lookup,
|
||||||
|
show_ip_rpf_source_cmd,
|
||||||
|
"show ip rpf A.B.C.D$source",
|
||||||
|
SHOW_STR
|
||||||
|
IP_STR
|
||||||
|
"Display RPF information for multicast source\n"
|
||||||
|
"Nexthop lookup for specific source address\n");
|
||||||
|
|
||||||
DEFPY (show_ip_pim_interface_traffic,
|
DEFPY (show_ip_pim_interface_traffic,
|
||||||
show_ip_pim_interface_traffic_cmd,
|
show_ip_pim_interface_traffic_cmd,
|
||||||
"show ip pim [vrf NAME] interface traffic [WORD$if_name] [json$json]",
|
"show ip pim [vrf NAME] interface traffic [WORD$if_name] [json$json]",
|
||||||
@ -9160,6 +9168,7 @@ void pim_cmd_init(void)
|
|||||||
install_element(VIEW_NODE, &show_ip_ssmpingd_cmd);
|
install_element(VIEW_NODE, &show_ip_ssmpingd_cmd);
|
||||||
install_element(VIEW_NODE, &show_ip_pim_nexthop_cmd);
|
install_element(VIEW_NODE, &show_ip_pim_nexthop_cmd);
|
||||||
install_element(VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd);
|
install_element(VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd);
|
||||||
|
install_element(VIEW_NODE, &show_ip_rpf_source_cmd);
|
||||||
install_element(VIEW_NODE, &show_ip_pim_bsrp_cmd);
|
install_element(VIEW_NODE, &show_ip_pim_bsrp_cmd);
|
||||||
install_element(VIEW_NODE, &show_ip_pim_bsm_db_cmd);
|
install_element(VIEW_NODE, &show_ip_pim_bsm_db_cmd);
|
||||||
install_element(VIEW_NODE, &show_ip_pim_bsr_rpinfo_cmd);
|
install_element(VIEW_NODE, &show_ip_pim_bsr_rpinfo_cmd);
|
||||||
|
@ -2825,31 +2825,39 @@ static int pim_print_vty_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg)
|
|||||||
struct vty *vty = cwd->vty;
|
struct vty *vty = cwd->vty;
|
||||||
struct pim_instance *pim = cwd->pim;
|
struct pim_instance *pim = cwd->pim;
|
||||||
struct nexthop *nh_node = NULL;
|
struct nexthop *nh_node = NULL;
|
||||||
ifindex_t first_ifindex;
|
|
||||||
struct interface *ifp = NULL;
|
struct interface *ifp = NULL;
|
||||||
struct ttable *tt = NULL;
|
struct ttable *tt = NULL;
|
||||||
char *table = NULL;
|
char *table = NULL;
|
||||||
|
|
||||||
/* Prepare table. */
|
/* Prepare table. */
|
||||||
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
|
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
|
||||||
ttable_add_row(tt, "Address|Interface|Nexthop");
|
ttable_add_row(tt, "Address|Interface|Nexthop|Table");
|
||||||
tt->style.cell.rpad = 2;
|
tt->style.cell.rpad = 2;
|
||||||
tt->style.corner = '+';
|
tt->style.corner = '+';
|
||||||
ttable_restyle(tt);
|
ttable_restyle(tt);
|
||||||
|
|
||||||
for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
|
for (nh_node = pnc->mrib.nexthop; nh_node; nh_node = nh_node->next) {
|
||||||
first_ifindex = nh_node->ifindex;
|
ifp = if_lookup_by_index(nh_node->ifindex, pim->vrf->vrf_id);
|
||||||
|
|
||||||
ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id);
|
|
||||||
|
|
||||||
#if PIM_IPV == 4
|
#if PIM_IPV == 4
|
||||||
ttable_add_row(tt, "%pPA|%s|%pI4", &pnc->rpf.rpf_addr,
|
ttable_add_row(tt, "%pPA|%s|%pI4|%s", &pnc->addr, ifp ? ifp->name : "NULL",
|
||||||
ifp ? ifp->name : "NULL", &nh_node->gate.ipv4);
|
&nh_node->gate.ipv4, "MRIB");
|
||||||
#else
|
#else
|
||||||
ttable_add_row(tt, "%pPA|%s|%pI6", &pnc->rpf.rpf_addr,
|
ttable_add_row(tt, "%pPA|%s|%pI6|%s", &pnc->addr, ifp ? ifp->name : "NULL",
|
||||||
ifp ? ifp->name : "NULL", &nh_node->gate.ipv6);
|
&nh_node->gate.ipv6, "MRIB");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (nh_node = pnc->urib.nexthop; nh_node; nh_node = nh_node->next) {
|
||||||
|
ifp = if_lookup_by_index(nh_node->ifindex, pim->vrf->vrf_id);
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
ttable_add_row(tt, "%pPA|%s|%pI4|%s", &pnc->addr, ifp ? ifp->name : "NULL",
|
||||||
|
&nh_node->gate.ipv4, "URIB");
|
||||||
|
#else
|
||||||
|
ttable_add_row(tt, "%pPA|%s|%pI6|%s", &pnc->addr, ifp ? ifp->name : "NULL",
|
||||||
|
&nh_node->gate.ipv6, "URIB");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* Dump the generated table. */
|
/* Dump the generated table. */
|
||||||
table = ttable_dump(tt, "\n");
|
table = ttable_dump(tt, "\n");
|
||||||
vty_out(vty, "%s\n", table);
|
vty_out(vty, "%s\n", table);
|
||||||
@ -2859,64 +2867,65 @@ static int pim_print_vty_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg)
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pim_print_json_pnc_cache_walkcb(struct hash_bucket *backet,
|
static void pim_print_json_nexthop(json_object *json_obj, struct nexthop *nh_node,
|
||||||
void *arg)
|
struct interface *ifp, char *addr_str, const char *type)
|
||||||
{
|
{
|
||||||
struct pim_nexthop_cache *pnc = backet->data;
|
|
||||||
struct json_pnc_cache_walk_data *cwd = arg;
|
|
||||||
struct pim_instance *pim = cwd->pim;
|
|
||||||
struct nexthop *nh_node = NULL;
|
|
||||||
ifindex_t first_ifindex;
|
|
||||||
struct interface *ifp = NULL;
|
|
||||||
char addr_str[PIM_ADDRSTRLEN];
|
|
||||||
json_object *json_row = NULL;
|
json_object *json_row = NULL;
|
||||||
json_object *json_ifp = NULL;
|
json_object *json_ifp = NULL;
|
||||||
json_object *json_arr = NULL;
|
json_object *json_arr = NULL;
|
||||||
struct pim_interface *pim_ifp = NULL;
|
struct pim_interface *pim_ifp = NULL;
|
||||||
bool pim_enable = false;
|
|
||||||
|
|
||||||
for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
|
|
||||||
first_ifindex = nh_node->ifindex;
|
|
||||||
ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id);
|
|
||||||
snprintfrr(addr_str, sizeof(addr_str), "%pPA",
|
|
||||||
&pnc->rpf.rpf_addr);
|
|
||||||
json_object_object_get_ex(cwd->json_obj, addr_str, &json_row);
|
|
||||||
if (!json_row) {
|
|
||||||
json_row = json_object_new_object();
|
|
||||||
json_object_string_addf(json_row, "address", "%pPA",
|
|
||||||
&pnc->rpf.rpf_addr);
|
|
||||||
json_object_object_addf(cwd->json_obj, json_row, "%pPA",
|
|
||||||
&pnc->rpf.rpf_addr);
|
|
||||||
json_arr = json_object_new_array();
|
|
||||||
json_object_object_add(json_row, "nexthops", json_arr);
|
|
||||||
}
|
|
||||||
json_ifp = json_object_new_object();
|
|
||||||
json_object_string_add(json_ifp, "interface",
|
|
||||||
ifp ? ifp->name : "NULL");
|
|
||||||
|
|
||||||
if (ifp)
|
if (ifp)
|
||||||
pim_ifp = ifp->info;
|
pim_ifp = ifp->info;
|
||||||
|
|
||||||
if (pim_ifp && pim_ifp->pim_enable)
|
json_object_object_get_ex(json_obj, addr_str, &json_row);
|
||||||
pim_enable = true;
|
|
||||||
|
|
||||||
json_object_boolean_add(json_ifp, "pimEnabled", pim_enable);
|
if (!json_row) {
|
||||||
|
json_row = json_object_new_object();
|
||||||
|
json_object_string_addf(json_row, "address", "%s", addr_str);
|
||||||
|
json_object_object_addf(json_obj, json_row, "%s", addr_str);
|
||||||
|
json_arr = json_object_new_array();
|
||||||
|
json_object_object_add(json_row, "nexthops", json_arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
json_ifp = json_object_new_object();
|
||||||
|
json_object_string_add(json_ifp, "interface", ifp ? ifp->name : "NULL");
|
||||||
|
json_object_boolean_add(json_ifp, "pimEnabled", (pim_ifp && pim_ifp->pim_enable));
|
||||||
#if PIM_IPV == 4
|
#if PIM_IPV == 4
|
||||||
json_object_string_addf(json_ifp, "nexthop", "%pI4",
|
json_object_string_addf(json_ifp, "nexthop", "%pI4", &nh_node->gate.ipv4);
|
||||||
&nh_node->gate.ipv4);
|
|
||||||
#else
|
#else
|
||||||
json_object_string_addf(json_ifp, "nexthop", "%pI6",
|
json_object_string_addf(json_ifp, "nexthop", "%pI6", &nh_node->gate.ipv6);
|
||||||
&nh_node->gate.ipv6);
|
|
||||||
#endif
|
#endif
|
||||||
|
json_object_string_add(json_ifp, "table", type);
|
||||||
json_object_array_add(json_arr, json_ifp);
|
json_object_array_add(json_arr, json_ifp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pim_print_json_pnc_cache_walkcb(struct hash_bucket *backet, void *arg)
|
||||||
|
{
|
||||||
|
struct pim_nexthop_cache *pnc = backet->data;
|
||||||
|
struct json_pnc_cache_walk_data *cwd = arg;
|
||||||
|
json_object *json_obj = cwd->json_obj;
|
||||||
|
struct pim_instance *pim = cwd->pim;
|
||||||
|
char addr_str[PIM_ADDRSTRLEN];
|
||||||
|
struct nexthop *nh_node = NULL;
|
||||||
|
struct interface *ifp = NULL;
|
||||||
|
|
||||||
|
snprintfrr(addr_str, sizeof(addr_str), "%pPA", &pnc->addr);
|
||||||
|
for (nh_node = pnc->mrib.nexthop; nh_node; nh_node = nh_node->next) {
|
||||||
|
ifp = if_lookup_by_index(nh_node->ifindex, pim->vrf->vrf_id);
|
||||||
|
pim_print_json_nexthop(json_obj, nh_node, ifp, addr_str, "MRIB");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (nh_node = pnc->urib.nexthop; nh_node; nh_node = nh_node->next) {
|
||||||
|
ifp = if_lookup_by_index(nh_node->ifindex, pim->vrf->vrf_id);
|
||||||
|
pim_print_json_nexthop(json_obj, nh_node, ifp, addr_str, "URIB");
|
||||||
|
}
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pim_show_nexthop_lookup_cmd_helper(const char *vrf, struct vty *vty,
|
int pim_show_nexthop_lookup_cmd_helper(const char *vrf, struct vty *vty,
|
||||||
pim_addr source, pim_addr group)
|
pim_addr source, pim_addr group)
|
||||||
{
|
{
|
||||||
int result = 0;
|
|
||||||
pim_addr vif_source;
|
pim_addr vif_source;
|
||||||
struct prefix grp;
|
struct prefix grp;
|
||||||
struct pim_nexthop nexthop;
|
struct pim_nexthop nexthop;
|
||||||
@ -2929,31 +2938,36 @@ int pim_show_nexthop_lookup_cmd_helper(const char *vrf, struct vty *vty,
|
|||||||
|
|
||||||
#if PIM_IPV == 4
|
#if PIM_IPV == 4
|
||||||
if (pim_is_group_224_4(source)) {
|
if (pim_is_group_224_4(source)) {
|
||||||
vty_out(vty,
|
vty_out(vty, "Invalid argument. Expected Valid Source Address.\n");
|
||||||
"Invalid argument. Expected Valid Source Address.\n");
|
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
|
/* Only require group if source is not provided */
|
||||||
if (!pim_is_group_224_4(group)) {
|
if (pim_addr_is_any(source) && !pim_is_group_224_4(group)) {
|
||||||
vty_out(vty,
|
vty_out(vty, "Invalid argument. Expected Valid Multicast Group Address.\n");
|
||||||
"Invalid argument. Expected Valid Multicast Group Address.\n");
|
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!pim_rp_set_upstream_addr(v->info, &vif_source, source, group))
|
/* This call will set vif_source=source, if source is not ANY. Otherwise vif_source
|
||||||
|
* will be set to the RP address according to the group address. If no RP is configured
|
||||||
|
* for the group, then return 0 and set vif_source to ANY
|
||||||
|
*/
|
||||||
|
if (!pim_rp_set_upstream_addr(v->info, &vif_source, source, group)) {
|
||||||
|
vty_out(vty, "(%pPAs, %pPA) --- Nexthop Lookup failed, no RP.\n", &source, &group);
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pim_addr_to_prefix(&grp, group);
|
pim_addr_to_prefix(&grp, group);
|
||||||
memset(&nexthop, 0, sizeof(nexthop));
|
memset(&nexthop, 0, sizeof(nexthop));
|
||||||
|
|
||||||
if (!pim_nht_lookup_ecmp(v->info, &nexthop, vif_source, &grp, false)) {
|
if (!pim_nht_lookup_ecmp(v->info, &nexthop, vif_source, &grp, false)) {
|
||||||
vty_out(vty,
|
vty_out(vty, "(%pPAs, %pPA) --- Nexthop Lookup failed, no usable routes returned.\n",
|
||||||
"Nexthop Lookup failed, no usable routes returned.\n");
|
&source, &group);
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
vty_out(vty, "Group %pFXh --- Nexthop %pPAs Interface %s\n", &grp,
|
vty_out(vty, "(%pPAs, %pPAs) --- Nexthop %pPAs Interface %s\n", &source, &group,
|
||||||
&nexthop.mrib_nexthop_addr, nexthop.interface->name);
|
&nexthop.mrib_nexthop_addr, nexthop.interface->name);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
@ -2982,19 +2996,16 @@ void pim_show_nexthop(struct pim_instance *pim, struct vty *vty, bool uj)
|
|||||||
cwd.pim = pim;
|
cwd.pim = pim;
|
||||||
jcwd.pim = pim;
|
jcwd.pim = pim;
|
||||||
|
|
||||||
if (uj) {
|
if (uj)
|
||||||
jcwd.json_obj = json_object_new_object();
|
jcwd.json_obj = json_object_new_object();
|
||||||
} else {
|
else
|
||||||
vty_out(vty, "Number of registered addresses: %lu\n",
|
vty_out(vty, "Number of registered addresses: %lu\n", pim->nht_hash->count);
|
||||||
pim->rpf_hash->count);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uj) {
|
if (uj) {
|
||||||
hash_walk(pim->rpf_hash, pim_print_json_pnc_cache_walkcb,
|
hash_walk(pim->nht_hash, pim_print_json_pnc_cache_walkcb, &jcwd);
|
||||||
&jcwd);
|
|
||||||
vty_json(vty, jcwd.json_obj);
|
vty_json(vty, jcwd.json_obj);
|
||||||
} else
|
} else
|
||||||
hash_walk(pim->rpf_hash, pim_print_vty_pnc_cache_walkcb, &cwd);
|
hash_walk(pim->nht_hash, pim_print_vty_pnc_cache_walkcb, &cwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pim_show_neighbors_cmd_helper(const char *vrf, struct vty *vty,
|
int pim_show_neighbors_cmd_helper(const char *vrf, struct vty *vty,
|
||||||
|
Loading…
Reference in New Issue
Block a user