mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-31 06:24:59 +00:00
pimd: Moving the common functions from pim_cmd.c
Moving the functions that are used by both IPV4 and IPV6 to a common file pim_cmd_common.c file Signed-off-by: Abhishek N R <abnr@vmware.com>
This commit is contained in:
parent
633a50d11c
commit
3b767e4b6d
530
pimd/pim_cmd.c
530
pimd/pim_cmd.c
@ -3766,383 +3766,6 @@ DEFPY (show_ip_multicast_count_vrf_all,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void show_mroute(struct pim_instance *pim, struct vty *vty,
|
||||
pim_sgaddr *sg, bool fill, bool uj)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct channel_oil *c_oil;
|
||||
struct static_route *s_route;
|
||||
time_t now;
|
||||
json_object *json = NULL;
|
||||
json_object *json_group = NULL;
|
||||
json_object *json_source = NULL;
|
||||
json_object *json_oil = NULL;
|
||||
json_object *json_ifp_out = NULL;
|
||||
int found_oif;
|
||||
int first;
|
||||
char grp_str[INET_ADDRSTRLEN];
|
||||
char src_str[INET_ADDRSTRLEN];
|
||||
char in_ifname[INTERFACE_NAMSIZ + 1];
|
||||
char out_ifname[INTERFACE_NAMSIZ + 1];
|
||||
int oif_vif_index;
|
||||
struct interface *ifp_in;
|
||||
char proto[100];
|
||||
char state_str[PIM_REG_STATE_STR_LEN];
|
||||
char mroute_uptime[10];
|
||||
|
||||
if (uj) {
|
||||
json = json_object_new_object();
|
||||
} else {
|
||||
vty_out(vty, "IP Multicast Routing Table\n");
|
||||
vty_out(vty, "Flags: S - Sparse, C - Connected, P - Pruned\n");
|
||||
vty_out(vty,
|
||||
" R - SGRpt Pruned, F - Register flag, T - SPT-bit set\n");
|
||||
vty_out(vty,
|
||||
"\nSource Group Flags Proto Input Output TTL Uptime\n");
|
||||
}
|
||||
|
||||
now = pim_time_monotonic_sec();
|
||||
|
||||
/* print list of PIM and IGMP routes */
|
||||
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
|
||||
found_oif = 0;
|
||||
first = 1;
|
||||
if (!c_oil->installed)
|
||||
continue;
|
||||
|
||||
if (!pim_addr_is_any(sg->grp) &&
|
||||
pim_addr_cmp(sg->grp, c_oil->oil.mfcc_mcastgrp))
|
||||
continue;
|
||||
if (!pim_addr_is_any(sg->src) &&
|
||||
pim_addr_cmp(sg->src, c_oil->oil.mfcc_origin))
|
||||
continue;
|
||||
|
||||
pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str,
|
||||
sizeof(grp_str));
|
||||
pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str,
|
||||
sizeof(src_str));
|
||||
|
||||
strlcpy(state_str, "S", sizeof(state_str));
|
||||
/* When a non DR receives a igmp join, it creates a (*,G)
|
||||
* channel_oil without any upstream creation */
|
||||
if (c_oil->up) {
|
||||
if (PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(c_oil->up->flags))
|
||||
strlcat(state_str, "C", sizeof(state_str));
|
||||
if (pim_upstream_is_sg_rpt(c_oil->up))
|
||||
strlcat(state_str, "R", sizeof(state_str));
|
||||
if (PIM_UPSTREAM_FLAG_TEST_FHR(c_oil->up->flags))
|
||||
strlcat(state_str, "F", sizeof(state_str));
|
||||
if (c_oil->up->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
|
||||
strlcat(state_str, "T", sizeof(state_str));
|
||||
}
|
||||
if (pim_channel_oil_empty(c_oil))
|
||||
strlcat(state_str, "P", sizeof(state_str));
|
||||
|
||||
ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent);
|
||||
|
||||
if (ifp_in)
|
||||
strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
|
||||
else
|
||||
strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
|
||||
|
||||
|
||||
pim_time_uptime(mroute_uptime, sizeof(mroute_uptime),
|
||||
now - c_oil->mroute_creation);
|
||||
|
||||
if (uj) {
|
||||
|
||||
/* Find the group, create it if it doesn't exist */
|
||||
json_object_object_get_ex(json, grp_str, &json_group);
|
||||
|
||||
if (!json_group) {
|
||||
json_group = json_object_new_object();
|
||||
json_object_object_add(json, grp_str,
|
||||
json_group);
|
||||
}
|
||||
|
||||
/* Find the source nested under the group, create it if
|
||||
* it doesn't exist
|
||||
*/
|
||||
json_object_object_get_ex(json_group, src_str,
|
||||
&json_source);
|
||||
|
||||
if (!json_source) {
|
||||
json_source = json_object_new_object();
|
||||
json_object_object_add(json_group, src_str,
|
||||
json_source);
|
||||
}
|
||||
|
||||
/* Find the inbound interface nested under the source,
|
||||
* create it if it doesn't exist */
|
||||
json_object_string_add(json_source, "source",
|
||||
src_str);
|
||||
json_object_string_add(json_source, "group",
|
||||
grp_str);
|
||||
json_object_int_add(json_source, "installed",
|
||||
c_oil->installed);
|
||||
json_object_int_add(json_source, "refCount",
|
||||
c_oil->oil_ref_count);
|
||||
json_object_int_add(json_source, "oilSize",
|
||||
c_oil->oil_size);
|
||||
json_object_int_add(json_source, "OilInheritedRescan",
|
||||
c_oil->oil_inherited_rescan);
|
||||
json_object_int_add(json_source, "oilInheritedRescan",
|
||||
c_oil->oil_inherited_rescan);
|
||||
json_object_string_add(json_source, "iif", in_ifname);
|
||||
json_object_string_add(json_source, "upTime",
|
||||
mroute_uptime);
|
||||
json_oil = NULL;
|
||||
}
|
||||
|
||||
for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
|
||||
++oif_vif_index) {
|
||||
struct interface *ifp_out;
|
||||
int ttl;
|
||||
|
||||
ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
|
||||
if (ttl < 1)
|
||||
continue;
|
||||
|
||||
/* do not display muted OIFs */
|
||||
if (c_oil->oif_flags[oif_vif_index]
|
||||
& PIM_OIF_FLAG_MUTE)
|
||||
continue;
|
||||
|
||||
if (c_oil->oil.mfcc_parent == oif_vif_index &&
|
||||
!pim_mroute_allow_iif_in_oil(c_oil,
|
||||
oif_vif_index))
|
||||
continue;
|
||||
|
||||
ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
|
||||
found_oif = 1;
|
||||
|
||||
if (ifp_out)
|
||||
strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname));
|
||||
else
|
||||
strlcpy(out_ifname, "<oif?>", sizeof(out_ifname));
|
||||
|
||||
if (uj) {
|
||||
json_ifp_out = json_object_new_object();
|
||||
json_object_string_add(json_ifp_out, "source",
|
||||
src_str);
|
||||
json_object_string_add(json_ifp_out, "group",
|
||||
grp_str);
|
||||
|
||||
if (c_oil->oif_flags[oif_vif_index]
|
||||
& PIM_OIF_FLAG_PROTO_PIM)
|
||||
json_object_boolean_true_add(
|
||||
json_ifp_out, "protocolPim");
|
||||
|
||||
if (c_oil->oif_flags[oif_vif_index] &
|
||||
PIM_OIF_FLAG_PROTO_GM)
|
||||
json_object_boolean_true_add(
|
||||
json_ifp_out, "protocolIgmp");
|
||||
|
||||
if (c_oil->oif_flags[oif_vif_index]
|
||||
& PIM_OIF_FLAG_PROTO_VXLAN)
|
||||
json_object_boolean_true_add(
|
||||
json_ifp_out, "protocolVxlan");
|
||||
|
||||
if (c_oil->oif_flags[oif_vif_index]
|
||||
& PIM_OIF_FLAG_PROTO_STAR)
|
||||
json_object_boolean_true_add(
|
||||
json_ifp_out,
|
||||
"protocolInherited");
|
||||
|
||||
json_object_string_add(json_ifp_out,
|
||||
"inboundInterface",
|
||||
in_ifname);
|
||||
json_object_int_add(json_ifp_out, "iVifI",
|
||||
c_oil->oil.mfcc_parent);
|
||||
json_object_string_add(json_ifp_out,
|
||||
"outboundInterface",
|
||||
out_ifname);
|
||||
json_object_int_add(json_ifp_out, "oVifI",
|
||||
oif_vif_index);
|
||||
json_object_int_add(json_ifp_out, "ttl", ttl);
|
||||
json_object_string_add(json_ifp_out, "upTime",
|
||||
mroute_uptime);
|
||||
json_object_string_add(json_source, "flags",
|
||||
state_str);
|
||||
if (!json_oil) {
|
||||
json_oil = json_object_new_object();
|
||||
json_object_object_add(json_source,
|
||||
"oil", json_oil);
|
||||
}
|
||||
json_object_object_add(json_oil, out_ifname,
|
||||
json_ifp_out);
|
||||
} else {
|
||||
proto[0] = '\0';
|
||||
if (c_oil->oif_flags[oif_vif_index]
|
||||
& PIM_OIF_FLAG_PROTO_PIM) {
|
||||
strlcpy(proto, "PIM", sizeof(proto));
|
||||
}
|
||||
|
||||
if (c_oil->oif_flags[oif_vif_index] &
|
||||
PIM_OIF_FLAG_PROTO_GM) {
|
||||
strlcpy(proto, "IGMP", sizeof(proto));
|
||||
}
|
||||
|
||||
if (c_oil->oif_flags[oif_vif_index]
|
||||
& PIM_OIF_FLAG_PROTO_VXLAN) {
|
||||
strlcpy(proto, "VxLAN", sizeof(proto));
|
||||
}
|
||||
|
||||
if (c_oil->oif_flags[oif_vif_index]
|
||||
& PIM_OIF_FLAG_PROTO_STAR) {
|
||||
strlcpy(proto, "STAR", sizeof(proto));
|
||||
}
|
||||
|
||||
vty_out(vty,
|
||||
"%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
|
||||
src_str, grp_str, state_str, proto,
|
||||
in_ifname, out_ifname, ttl,
|
||||
mroute_uptime);
|
||||
|
||||
if (first) {
|
||||
src_str[0] = '\0';
|
||||
grp_str[0] = '\0';
|
||||
in_ifname[0] = '\0';
|
||||
state_str[0] = '\0';
|
||||
mroute_uptime[0] = '\0';
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!uj && !found_oif) {
|
||||
vty_out(vty,
|
||||
"%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
|
||||
src_str, grp_str, state_str, "none", in_ifname,
|
||||
"none", 0, "--:--:--");
|
||||
}
|
||||
}
|
||||
|
||||
/* Print list of static routes */
|
||||
for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
|
||||
first = 1;
|
||||
|
||||
if (!s_route->c_oil.installed)
|
||||
continue;
|
||||
|
||||
pim_inet4_dump("<group?>", s_route->group, grp_str,
|
||||
sizeof(grp_str));
|
||||
pim_inet4_dump("<source?>", s_route->source, src_str,
|
||||
sizeof(src_str));
|
||||
ifp_in = pim_if_find_by_vif_index(pim, s_route->iif);
|
||||
found_oif = 0;
|
||||
|
||||
if (ifp_in)
|
||||
strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
|
||||
else
|
||||
strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
|
||||
|
||||
if (uj) {
|
||||
|
||||
/* Find the group, create it if it doesn't exist */
|
||||
json_object_object_get_ex(json, grp_str, &json_group);
|
||||
|
||||
if (!json_group) {
|
||||
json_group = json_object_new_object();
|
||||
json_object_object_add(json, grp_str,
|
||||
json_group);
|
||||
}
|
||||
|
||||
/* Find the source nested under the group, create it if
|
||||
* it doesn't exist */
|
||||
json_object_object_get_ex(json_group, src_str,
|
||||
&json_source);
|
||||
|
||||
if (!json_source) {
|
||||
json_source = json_object_new_object();
|
||||
json_object_object_add(json_group, src_str,
|
||||
json_source);
|
||||
}
|
||||
|
||||
json_object_string_add(json_source, "iif", in_ifname);
|
||||
json_oil = NULL;
|
||||
} else {
|
||||
strlcpy(proto, "STATIC", sizeof(proto));
|
||||
}
|
||||
|
||||
for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
|
||||
++oif_vif_index) {
|
||||
struct interface *ifp_out;
|
||||
char oif_uptime[10];
|
||||
int ttl;
|
||||
|
||||
ttl = s_route->oif_ttls[oif_vif_index];
|
||||
if (ttl < 1)
|
||||
continue;
|
||||
|
||||
ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
|
||||
pim_time_uptime(
|
||||
oif_uptime, sizeof(oif_uptime),
|
||||
now
|
||||
- s_route->c_oil
|
||||
.oif_creation[oif_vif_index]);
|
||||
found_oif = 1;
|
||||
|
||||
if (ifp_out)
|
||||
strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname));
|
||||
else
|
||||
strlcpy(out_ifname, "<oif?>", sizeof(out_ifname));
|
||||
|
||||
if (uj) {
|
||||
json_ifp_out = json_object_new_object();
|
||||
json_object_string_add(json_ifp_out, "source",
|
||||
src_str);
|
||||
json_object_string_add(json_ifp_out, "group",
|
||||
grp_str);
|
||||
json_object_boolean_true_add(json_ifp_out,
|
||||
"protocolStatic");
|
||||
json_object_string_add(json_ifp_out,
|
||||
"inboundInterface",
|
||||
in_ifname);
|
||||
json_object_int_add(
|
||||
json_ifp_out, "iVifI",
|
||||
s_route->c_oil.oil.mfcc_parent);
|
||||
json_object_string_add(json_ifp_out,
|
||||
"outboundInterface",
|
||||
out_ifname);
|
||||
json_object_int_add(json_ifp_out, "oVifI",
|
||||
oif_vif_index);
|
||||
json_object_int_add(json_ifp_out, "ttl", ttl);
|
||||
json_object_string_add(json_ifp_out, "upTime",
|
||||
oif_uptime);
|
||||
if (!json_oil) {
|
||||
json_oil = json_object_new_object();
|
||||
json_object_object_add(json_source,
|
||||
"oil", json_oil);
|
||||
}
|
||||
json_object_object_add(json_oil, out_ifname,
|
||||
json_ifp_out);
|
||||
} else {
|
||||
vty_out(vty,
|
||||
"%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
|
||||
src_str, grp_str, "-", proto, in_ifname,
|
||||
out_ifname, ttl, oif_uptime);
|
||||
if (first && !fill) {
|
||||
src_str[0] = '\0';
|
||||
grp_str[0] = '\0';
|
||||
in_ifname[0] = '\0';
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!uj && !found_oif) {
|
||||
vty_out(vty,
|
||||
"%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
|
||||
src_str, grp_str, "-", proto, in_ifname, "none",
|
||||
0, "--:--:--");
|
||||
}
|
||||
}
|
||||
|
||||
if (uj)
|
||||
vty_json(vty, json);
|
||||
}
|
||||
|
||||
DEFPY (show_ip_mroute,
|
||||
show_ip_mroute_cmd,
|
||||
"show ip mroute [vrf NAME] [A.B.C.D$s_or_g [A.B.C.D$g]] [fill$fill] [json$json]",
|
||||
@ -4264,78 +3887,6 @@ DEFUN (clear_ip_mroute_count,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void show_mroute_count_per_channel_oil(struct channel_oil *c_oil,
|
||||
json_object *json,
|
||||
struct vty *vty)
|
||||
{
|
||||
char group_str[INET_ADDRSTRLEN];
|
||||
char source_str[INET_ADDRSTRLEN];
|
||||
json_object *json_group = NULL;
|
||||
json_object *json_source = NULL;
|
||||
|
||||
if (!c_oil->installed)
|
||||
return;
|
||||
|
||||
pim_mroute_update_counters(c_oil);
|
||||
|
||||
pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str,
|
||||
sizeof(group_str));
|
||||
pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str,
|
||||
sizeof(source_str));
|
||||
|
||||
if (json) {
|
||||
json_object_object_get_ex(json, group_str, &json_group);
|
||||
|
||||
if (!json_group) {
|
||||
json_group = json_object_new_object();
|
||||
json_object_object_add(json, group_str, json_group);
|
||||
}
|
||||
|
||||
json_source = json_object_new_object();
|
||||
json_object_object_add(json_group, source_str, json_source);
|
||||
json_object_int_add(json_source, "lastUsed",
|
||||
c_oil->cc.lastused / 100);
|
||||
json_object_int_add(json_source, "packets", c_oil->cc.pktcnt);
|
||||
json_object_int_add(json_source, "bytes", c_oil->cc.bytecnt);
|
||||
json_object_int_add(json_source, "wrongIf", c_oil->cc.wrong_if);
|
||||
|
||||
} else {
|
||||
vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n",
|
||||
source_str, group_str, c_oil->cc.lastused / 100,
|
||||
c_oil->cc.pktcnt - c_oil->cc.origpktcnt,
|
||||
c_oil->cc.bytecnt - c_oil->cc.origbytecnt,
|
||||
c_oil->cc.wrong_if - c_oil->cc.origwrong_if);
|
||||
}
|
||||
}
|
||||
|
||||
static void show_mroute_count(struct pim_instance *pim, struct vty *vty,
|
||||
bool uj)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct channel_oil *c_oil;
|
||||
struct static_route *sr;
|
||||
json_object *json = NULL;
|
||||
|
||||
if (uj)
|
||||
json = json_object_new_object();
|
||||
else {
|
||||
vty_out(vty, "\n");
|
||||
|
||||
vty_out(vty,
|
||||
"Source Group LastUsed Packets Bytes WrongIf \n");
|
||||
}
|
||||
|
||||
/* Print PIM and IGMP route counts */
|
||||
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
|
||||
show_mroute_count_per_channel_oil(c_oil, json, vty);
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr))
|
||||
show_mroute_count_per_channel_oil(&sr->c_oil, json, vty);
|
||||
|
||||
if (uj)
|
||||
vty_json(vty, json);
|
||||
}
|
||||
|
||||
DEFUN (show_ip_mroute_count,
|
||||
show_ip_mroute_count_cmd,
|
||||
"show ip mroute [vrf NAME] count [json]",
|
||||
@ -4389,87 +3940,6 @@ DEFUN (show_ip_mroute_count_vrf_all,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void show_mroute_summary(struct pim_instance *pim, struct vty *vty,
|
||||
json_object *json)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct channel_oil *c_oil;
|
||||
struct static_route *s_route;
|
||||
uint32_t starg_sw_mroute_cnt = 0;
|
||||
uint32_t sg_sw_mroute_cnt = 0;
|
||||
uint32_t starg_hw_mroute_cnt = 0;
|
||||
uint32_t sg_hw_mroute_cnt = 0;
|
||||
json_object *json_starg = NULL;
|
||||
json_object *json_sg = NULL;
|
||||
|
||||
if (!json)
|
||||
vty_out(vty, "Mroute Type Installed/Total\n");
|
||||
|
||||
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
|
||||
if (!c_oil->installed) {
|
||||
if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
|
||||
starg_sw_mroute_cnt++;
|
||||
else
|
||||
sg_sw_mroute_cnt++;
|
||||
} else {
|
||||
if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
|
||||
starg_hw_mroute_cnt++;
|
||||
else
|
||||
sg_hw_mroute_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
|
||||
if (!s_route->c_oil.installed) {
|
||||
if (s_route->c_oil.oil.mfcc_origin.s_addr == INADDR_ANY)
|
||||
starg_sw_mroute_cnt++;
|
||||
else
|
||||
sg_sw_mroute_cnt++;
|
||||
} else {
|
||||
if (s_route->c_oil.oil.mfcc_origin.s_addr == INADDR_ANY)
|
||||
starg_hw_mroute_cnt++;
|
||||
else
|
||||
sg_hw_mroute_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!json) {
|
||||
vty_out(vty, "%-20s %u/%u\n", "(*, G)", starg_hw_mroute_cnt,
|
||||
starg_sw_mroute_cnt + starg_hw_mroute_cnt);
|
||||
vty_out(vty, "%-20s %u/%u\n", "(S, G)", sg_hw_mroute_cnt,
|
||||
sg_sw_mroute_cnt + sg_hw_mroute_cnt);
|
||||
vty_out(vty, "------\n");
|
||||
vty_out(vty, "%-20s %u/%u\n", "Total",
|
||||
(starg_hw_mroute_cnt + sg_hw_mroute_cnt),
|
||||
(starg_sw_mroute_cnt + starg_hw_mroute_cnt
|
||||
+ sg_sw_mroute_cnt + sg_hw_mroute_cnt));
|
||||
} else {
|
||||
/* (*,G) route details */
|
||||
json_starg = json_object_new_object();
|
||||
json_object_object_add(json, "wildcardGroup", json_starg);
|
||||
|
||||
json_object_int_add(json_starg, "installed",
|
||||
starg_hw_mroute_cnt);
|
||||
json_object_int_add(json_starg, "total",
|
||||
starg_sw_mroute_cnt + starg_hw_mroute_cnt);
|
||||
|
||||
/* (S, G) route details */
|
||||
json_sg = json_object_new_object();
|
||||
json_object_object_add(json, "sourceGroup", json_sg);
|
||||
|
||||
json_object_int_add(json_sg, "installed", sg_hw_mroute_cnt);
|
||||
json_object_int_add(json_sg, "total",
|
||||
sg_sw_mroute_cnt + sg_hw_mroute_cnt);
|
||||
|
||||
json_object_int_add(json, "totalNumOfInstalledMroutes",
|
||||
starg_hw_mroute_cnt + sg_hw_mroute_cnt);
|
||||
json_object_int_add(json, "totalNumOfMroutes",
|
||||
starg_sw_mroute_cnt + starg_hw_mroute_cnt
|
||||
+ sg_sw_mroute_cnt
|
||||
+ sg_hw_mroute_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
DEFUN (show_ip_mroute_summary,
|
||||
show_ip_mroute_summary_cmd,
|
||||
"show ip mroute [vrf NAME] summary [json]",
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "pim_sock.h"
|
||||
#include "pim_ssm.h"
|
||||
#include "pim_addr.h"
|
||||
#include "pim_static.h"
|
||||
|
||||
/**
|
||||
* Get current node VRF name.
|
||||
@ -3007,3 +3008,534 @@ void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim, struct vty *vty)
|
||||
|
||||
show_multicast_interfaces(pim, vty, NULL);
|
||||
}
|
||||
#if PIM_IPV == 4
|
||||
void show_mroute(struct pim_instance *pim, struct vty *vty,
|
||||
pim_sgaddr *sg, bool fill, bool uj)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct channel_oil *c_oil;
|
||||
struct static_route *s_route;
|
||||
time_t now;
|
||||
json_object *json = NULL;
|
||||
json_object *json_group = NULL;
|
||||
json_object *json_source = NULL;
|
||||
json_object *json_oil = NULL;
|
||||
json_object *json_ifp_out = NULL;
|
||||
int found_oif;
|
||||
int first;
|
||||
char grp_str[INET_ADDRSTRLEN];
|
||||
char src_str[INET_ADDRSTRLEN];
|
||||
char in_ifname[INTERFACE_NAMSIZ + 1];
|
||||
char out_ifname[INTERFACE_NAMSIZ + 1];
|
||||
int oif_vif_index;
|
||||
struct interface *ifp_in;
|
||||
char proto[100];
|
||||
char state_str[PIM_REG_STATE_STR_LEN];
|
||||
char mroute_uptime[10];
|
||||
|
||||
if (uj) {
|
||||
json = json_object_new_object();
|
||||
} else {
|
||||
vty_out(vty, "IP Multicast Routing Table\n");
|
||||
vty_out(vty, "Flags: S - Sparse, C - Connected, P - Pruned\n");
|
||||
vty_out(vty,
|
||||
" R - SGRpt Pruned, F - Register flag, T - SPT-bit set\n");
|
||||
vty_out(vty,
|
||||
"\nSource Group Flags Proto Input Output TTL Uptime\n");
|
||||
}
|
||||
|
||||
now = pim_time_monotonic_sec();
|
||||
|
||||
/* print list of PIM and IGMP routes */
|
||||
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
|
||||
found_oif = 0;
|
||||
first = 1;
|
||||
if (!c_oil->installed)
|
||||
continue;
|
||||
|
||||
if (!pim_addr_is_any(sg->grp) &&
|
||||
pim_addr_cmp(sg->grp, c_oil->oil.mfcc_mcastgrp))
|
||||
continue;
|
||||
if (!pim_addr_is_any(sg->src) &&
|
||||
pim_addr_cmp(sg->src, c_oil->oil.mfcc_origin))
|
||||
continue;
|
||||
|
||||
pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str,
|
||||
sizeof(grp_str));
|
||||
pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str,
|
||||
sizeof(src_str));
|
||||
|
||||
strlcpy(state_str, "S", sizeof(state_str));
|
||||
/* When a non DR receives a igmp join, it creates a (*,G)
|
||||
* channel_oil without any upstream creation */
|
||||
if (c_oil->up) {
|
||||
if (PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(c_oil->up->flags))
|
||||
strlcat(state_str, "C", sizeof(state_str));
|
||||
if (pim_upstream_is_sg_rpt(c_oil->up))
|
||||
strlcat(state_str, "R", sizeof(state_str));
|
||||
if (PIM_UPSTREAM_FLAG_TEST_FHR(c_oil->up->flags))
|
||||
strlcat(state_str, "F", sizeof(state_str));
|
||||
if (c_oil->up->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
|
||||
strlcat(state_str, "T", sizeof(state_str));
|
||||
}
|
||||
if (pim_channel_oil_empty(c_oil))
|
||||
strlcat(state_str, "P", sizeof(state_str));
|
||||
|
||||
ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent);
|
||||
|
||||
if (ifp_in)
|
||||
strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
|
||||
else
|
||||
strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
|
||||
|
||||
|
||||
pim_time_uptime(mroute_uptime, sizeof(mroute_uptime),
|
||||
now - c_oil->mroute_creation);
|
||||
|
||||
if (uj) {
|
||||
|
||||
/* Find the group, create it if it doesn't exist */
|
||||
json_object_object_get_ex(json, grp_str, &json_group);
|
||||
|
||||
if (!json_group) {
|
||||
json_group = json_object_new_object();
|
||||
json_object_object_add(json, grp_str,
|
||||
json_group);
|
||||
}
|
||||
|
||||
/* Find the source nested under the group, create it if
|
||||
* it doesn't exist
|
||||
*/
|
||||
json_object_object_get_ex(json_group, src_str,
|
||||
&json_source);
|
||||
|
||||
if (!json_source) {
|
||||
json_source = json_object_new_object();
|
||||
json_object_object_add(json_group, src_str,
|
||||
json_source);
|
||||
}
|
||||
|
||||
/* Find the inbound interface nested under the source,
|
||||
* create it if it doesn't exist */
|
||||
json_object_string_add(json_source, "source",
|
||||
src_str);
|
||||
json_object_string_add(json_source, "group",
|
||||
grp_str);
|
||||
json_object_int_add(json_source, "installed",
|
||||
c_oil->installed);
|
||||
json_object_int_add(json_source, "refCount",
|
||||
c_oil->oil_ref_count);
|
||||
json_object_int_add(json_source, "oilSize",
|
||||
c_oil->oil_size);
|
||||
json_object_int_add(json_source, "OilInheritedRescan",
|
||||
c_oil->oil_inherited_rescan);
|
||||
json_object_int_add(json_source, "oilInheritedRescan",
|
||||
c_oil->oil_inherited_rescan);
|
||||
json_object_string_add(json_source, "iif", in_ifname);
|
||||
json_object_string_add(json_source, "upTime",
|
||||
mroute_uptime);
|
||||
json_oil = NULL;
|
||||
}
|
||||
|
||||
for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
|
||||
++oif_vif_index) {
|
||||
struct interface *ifp_out;
|
||||
int ttl;
|
||||
|
||||
ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
|
||||
if (ttl < 1)
|
||||
continue;
|
||||
|
||||
/* do not display muted OIFs */
|
||||
if (c_oil->oif_flags[oif_vif_index]
|
||||
& PIM_OIF_FLAG_MUTE)
|
||||
continue;
|
||||
|
||||
if (c_oil->oil.mfcc_parent == oif_vif_index &&
|
||||
!pim_mroute_allow_iif_in_oil(c_oil,
|
||||
oif_vif_index))
|
||||
continue;
|
||||
|
||||
ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
|
||||
found_oif = 1;
|
||||
|
||||
if (ifp_out)
|
||||
strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname));
|
||||
else
|
||||
strlcpy(out_ifname, "<oif?>", sizeof(out_ifname));
|
||||
|
||||
if (uj) {
|
||||
json_ifp_out = json_object_new_object();
|
||||
json_object_string_add(json_ifp_out, "source",
|
||||
src_str);
|
||||
json_object_string_add(json_ifp_out, "group",
|
||||
grp_str);
|
||||
|
||||
if (c_oil->oif_flags[oif_vif_index]
|
||||
& PIM_OIF_FLAG_PROTO_PIM)
|
||||
json_object_boolean_true_add(
|
||||
json_ifp_out, "protocolPim");
|
||||
|
||||
if (c_oil->oif_flags[oif_vif_index]
|
||||
& PIM_OIF_FLAG_PROTO_IGMP)
|
||||
json_object_boolean_true_add(
|
||||
json_ifp_out, "protocolIgmp");
|
||||
|
||||
if (c_oil->oif_flags[oif_vif_index]
|
||||
& PIM_OIF_FLAG_PROTO_VXLAN)
|
||||
json_object_boolean_true_add(
|
||||
json_ifp_out, "protocolVxlan");
|
||||
|
||||
if (c_oil->oif_flags[oif_vif_index]
|
||||
& PIM_OIF_FLAG_PROTO_STAR)
|
||||
json_object_boolean_true_add(
|
||||
json_ifp_out,
|
||||
"protocolInherited");
|
||||
|
||||
json_object_string_add(json_ifp_out,
|
||||
"inboundInterface",
|
||||
in_ifname);
|
||||
json_object_int_add(json_ifp_out, "iVifI",
|
||||
c_oil->oil.mfcc_parent);
|
||||
json_object_string_add(json_ifp_out,
|
||||
"outboundInterface",
|
||||
out_ifname);
|
||||
json_object_int_add(json_ifp_out, "oVifI",
|
||||
oif_vif_index);
|
||||
json_object_int_add(json_ifp_out, "ttl", ttl);
|
||||
json_object_string_add(json_ifp_out, "upTime",
|
||||
mroute_uptime);
|
||||
json_object_string_add(json_source, "flags",
|
||||
state_str);
|
||||
if (!json_oil) {
|
||||
json_oil = json_object_new_object();
|
||||
json_object_object_add(json_source,
|
||||
"oil", json_oil);
|
||||
}
|
||||
json_object_object_add(json_oil, out_ifname,
|
||||
json_ifp_out);
|
||||
} else {
|
||||
proto[0] = '\0';
|
||||
if (c_oil->oif_flags[oif_vif_index]
|
||||
& PIM_OIF_FLAG_PROTO_PIM) {
|
||||
strlcpy(proto, "PIM", sizeof(proto));
|
||||
}
|
||||
|
||||
if (c_oil->oif_flags[oif_vif_index]
|
||||
& PIM_OIF_FLAG_PROTO_IGMP) {
|
||||
strlcpy(proto, "IGMP", sizeof(proto));
|
||||
}
|
||||
|
||||
if (c_oil->oif_flags[oif_vif_index]
|
||||
& PIM_OIF_FLAG_PROTO_VXLAN) {
|
||||
strlcpy(proto, "VxLAN", sizeof(proto));
|
||||
}
|
||||
|
||||
if (c_oil->oif_flags[oif_vif_index]
|
||||
& PIM_OIF_FLAG_PROTO_STAR) {
|
||||
strlcpy(proto, "STAR", sizeof(proto));
|
||||
}
|
||||
|
||||
vty_out(vty,
|
||||
"%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
|
||||
src_str, grp_str, state_str, proto,
|
||||
in_ifname, out_ifname, ttl,
|
||||
mroute_uptime);
|
||||
|
||||
if (first) {
|
||||
src_str[0] = '\0';
|
||||
grp_str[0] = '\0';
|
||||
in_ifname[0] = '\0';
|
||||
state_str[0] = '\0';
|
||||
mroute_uptime[0] = '\0';
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!uj && !found_oif) {
|
||||
vty_out(vty,
|
||||
"%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
|
||||
src_str, grp_str, state_str, "none", in_ifname,
|
||||
"none", 0, "--:--:--");
|
||||
}
|
||||
}
|
||||
|
||||
/* Print list of static routes */
|
||||
for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
|
||||
first = 1;
|
||||
|
||||
if (!s_route->c_oil.installed)
|
||||
continue;
|
||||
|
||||
pim_inet4_dump("<group?>", s_route->group, grp_str,
|
||||
sizeof(grp_str));
|
||||
pim_inet4_dump("<source?>", s_route->source, src_str,
|
||||
sizeof(src_str));
|
||||
ifp_in = pim_if_find_by_vif_index(pim, s_route->iif);
|
||||
found_oif = 0;
|
||||
|
||||
if (ifp_in)
|
||||
strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
|
||||
else
|
||||
strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
|
||||
|
||||
if (uj) {
|
||||
|
||||
/* Find the group, create it if it doesn't exist */
|
||||
json_object_object_get_ex(json, grp_str, &json_group);
|
||||
|
||||
if (!json_group) {
|
||||
json_group = json_object_new_object();
|
||||
json_object_object_add(json, grp_str,
|
||||
json_group);
|
||||
}
|
||||
|
||||
/* Find the source nested under the group, create it if
|
||||
* it doesn't exist */
|
||||
json_object_object_get_ex(json_group, src_str,
|
||||
&json_source);
|
||||
|
||||
if (!json_source) {
|
||||
json_source = json_object_new_object();
|
||||
json_object_object_add(json_group, src_str,
|
||||
json_source);
|
||||
}
|
||||
|
||||
json_object_string_add(json_source, "iif", in_ifname);
|
||||
json_oil = NULL;
|
||||
} else {
|
||||
strlcpy(proto, "STATIC", sizeof(proto));
|
||||
}
|
||||
|
||||
for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
|
||||
++oif_vif_index) {
|
||||
struct interface *ifp_out;
|
||||
char oif_uptime[10];
|
||||
int ttl;
|
||||
|
||||
ttl = s_route->oif_ttls[oif_vif_index];
|
||||
if (ttl < 1)
|
||||
continue;
|
||||
|
||||
ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
|
||||
pim_time_uptime(
|
||||
oif_uptime, sizeof(oif_uptime),
|
||||
now
|
||||
- s_route->c_oil
|
||||
.oif_creation[oif_vif_index]);
|
||||
found_oif = 1;
|
||||
|
||||
if (ifp_out)
|
||||
strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname));
|
||||
else
|
||||
strlcpy(out_ifname, "<oif?>", sizeof(out_ifname));
|
||||
|
||||
if (uj) {
|
||||
json_ifp_out = json_object_new_object();
|
||||
json_object_string_add(json_ifp_out, "source",
|
||||
src_str);
|
||||
json_object_string_add(json_ifp_out, "group",
|
||||
grp_str);
|
||||
json_object_boolean_true_add(json_ifp_out,
|
||||
"protocolStatic");
|
||||
json_object_string_add(json_ifp_out,
|
||||
"inboundInterface",
|
||||
in_ifname);
|
||||
json_object_int_add(
|
||||
json_ifp_out, "iVifI",
|
||||
s_route->c_oil.oil.mfcc_parent);
|
||||
json_object_string_add(json_ifp_out,
|
||||
"outboundInterface",
|
||||
out_ifname);
|
||||
json_object_int_add(json_ifp_out, "oVifI",
|
||||
oif_vif_index);
|
||||
json_object_int_add(json_ifp_out, "ttl", ttl);
|
||||
json_object_string_add(json_ifp_out, "upTime",
|
||||
oif_uptime);
|
||||
if (!json_oil) {
|
||||
json_oil = json_object_new_object();
|
||||
json_object_object_add(json_source,
|
||||
"oil", json_oil);
|
||||
}
|
||||
json_object_object_add(json_oil, out_ifname,
|
||||
json_ifp_out);
|
||||
} else {
|
||||
vty_out(vty,
|
||||
"%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
|
||||
src_str, grp_str, "-", proto, in_ifname,
|
||||
out_ifname, ttl, oif_uptime);
|
||||
if (first && !fill) {
|
||||
src_str[0] = '\0';
|
||||
grp_str[0] = '\0';
|
||||
in_ifname[0] = '\0';
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!uj && !found_oif) {
|
||||
vty_out(vty,
|
||||
"%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
|
||||
src_str, grp_str, "-", proto, in_ifname, "none",
|
||||
0, "--:--:--");
|
||||
}
|
||||
}
|
||||
|
||||
if (uj)
|
||||
vty_json(vty, json);
|
||||
}
|
||||
|
||||
static void show_mroute_count_per_channel_oil(struct channel_oil *c_oil,
|
||||
json_object *json,
|
||||
struct vty *vty)
|
||||
{
|
||||
char group_str[INET_ADDRSTRLEN];
|
||||
char source_str[INET_ADDRSTRLEN];
|
||||
json_object *json_group = NULL;
|
||||
json_object *json_source = NULL;
|
||||
|
||||
if (!c_oil->installed)
|
||||
return;
|
||||
|
||||
pim_mroute_update_counters(c_oil);
|
||||
|
||||
pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str,
|
||||
sizeof(group_str));
|
||||
pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str,
|
||||
sizeof(source_str));
|
||||
|
||||
if (json) {
|
||||
json_object_object_get_ex(json, group_str, &json_group);
|
||||
|
||||
if (!json_group) {
|
||||
json_group = json_object_new_object();
|
||||
json_object_object_add(json, group_str, json_group);
|
||||
}
|
||||
|
||||
json_source = json_object_new_object();
|
||||
json_object_object_add(json_group, source_str, json_source);
|
||||
json_object_int_add(json_source, "lastUsed",
|
||||
c_oil->cc.lastused / 100);
|
||||
json_object_int_add(json_source, "packets", c_oil->cc.pktcnt);
|
||||
json_object_int_add(json_source, "bytes", c_oil->cc.bytecnt);
|
||||
json_object_int_add(json_source, "wrongIf", c_oil->cc.wrong_if);
|
||||
|
||||
} else {
|
||||
vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n",
|
||||
source_str, group_str, c_oil->cc.lastused / 100,
|
||||
c_oil->cc.pktcnt - c_oil->cc.origpktcnt,
|
||||
c_oil->cc.bytecnt - c_oil->cc.origbytecnt,
|
||||
c_oil->cc.wrong_if - c_oil->cc.origwrong_if);
|
||||
}
|
||||
}
|
||||
|
||||
void show_mroute_count(struct pim_instance *pim, struct vty *vty,
|
||||
bool uj)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct channel_oil *c_oil;
|
||||
struct static_route *sr;
|
||||
json_object *json = NULL;
|
||||
|
||||
if (uj)
|
||||
json = json_object_new_object();
|
||||
else {
|
||||
vty_out(vty, "\n");
|
||||
|
||||
vty_out(vty,
|
||||
"Source Group LastUsed Packets Bytes WrongIf \n");
|
||||
}
|
||||
|
||||
/* Print PIM and IGMP route counts */
|
||||
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
|
||||
show_mroute_count_per_channel_oil(c_oil, json, vty);
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr))
|
||||
show_mroute_count_per_channel_oil(&sr->c_oil, json, vty);
|
||||
|
||||
if (uj)
|
||||
vty_json(vty, json);
|
||||
}
|
||||
|
||||
void show_mroute_summary(struct pim_instance *pim, struct vty *vty,
|
||||
json_object *json)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct channel_oil *c_oil;
|
||||
struct static_route *s_route;
|
||||
uint32_t starg_sw_mroute_cnt = 0;
|
||||
uint32_t sg_sw_mroute_cnt = 0;
|
||||
uint32_t starg_hw_mroute_cnt = 0;
|
||||
uint32_t sg_hw_mroute_cnt = 0;
|
||||
json_object *json_starg = NULL;
|
||||
json_object *json_sg = NULL;
|
||||
|
||||
if (!json)
|
||||
vty_out(vty, "Mroute Type Installed/Total\n");
|
||||
|
||||
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
|
||||
if (!c_oil->installed) {
|
||||
if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
|
||||
starg_sw_mroute_cnt++;
|
||||
else
|
||||
sg_sw_mroute_cnt++;
|
||||
} else {
|
||||
if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
|
||||
starg_hw_mroute_cnt++;
|
||||
else
|
||||
sg_hw_mroute_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
|
||||
if (!s_route->c_oil.installed) {
|
||||
if (s_route->c_oil.oil.mfcc_origin.s_addr == INADDR_ANY)
|
||||
starg_sw_mroute_cnt++;
|
||||
else
|
||||
sg_sw_mroute_cnt++;
|
||||
} else {
|
||||
if (s_route->c_oil.oil.mfcc_origin.s_addr == INADDR_ANY)
|
||||
starg_hw_mroute_cnt++;
|
||||
else
|
||||
sg_hw_mroute_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!json) {
|
||||
vty_out(vty, "%-20s %u/%u\n", "(*, G)", starg_hw_mroute_cnt,
|
||||
starg_sw_mroute_cnt + starg_hw_mroute_cnt);
|
||||
vty_out(vty, "%-20s %u/%u\n", "(S, G)", sg_hw_mroute_cnt,
|
||||
sg_sw_mroute_cnt + sg_hw_mroute_cnt);
|
||||
vty_out(vty, "------\n");
|
||||
vty_out(vty, "%-20s %u/%u\n", "Total",
|
||||
(starg_hw_mroute_cnt + sg_hw_mroute_cnt),
|
||||
(starg_sw_mroute_cnt + starg_hw_mroute_cnt
|
||||
+ sg_sw_mroute_cnt + sg_hw_mroute_cnt));
|
||||
} else {
|
||||
/* (*,G) route details */
|
||||
json_starg = json_object_new_object();
|
||||
json_object_object_add(json, "wildcardGroup", json_starg);
|
||||
|
||||
json_object_int_add(json_starg, "installed",
|
||||
starg_hw_mroute_cnt);
|
||||
json_object_int_add(json_starg, "total",
|
||||
starg_sw_mroute_cnt + starg_hw_mroute_cnt);
|
||||
|
||||
/* (S, G) route details */
|
||||
json_sg = json_object_new_object();
|
||||
json_object_object_add(json, "sourceGroup", json_sg);
|
||||
|
||||
json_object_int_add(json_sg, "installed", sg_hw_mroute_cnt);
|
||||
json_object_int_add(json_sg, "total",
|
||||
sg_sw_mroute_cnt + sg_hw_mroute_cnt);
|
||||
|
||||
json_object_int_add(json, "totalNumOfInstalledMroutes",
|
||||
starg_hw_mroute_cnt + sg_hw_mroute_cnt);
|
||||
json_object_int_add(json, "totalNumOfMroutes",
|
||||
starg_sw_mroute_cnt + starg_hw_mroute_cnt
|
||||
+ sg_sw_mroute_cnt
|
||||
+ sg_hw_mroute_cnt);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -108,6 +108,12 @@ void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim,
|
||||
struct vty *vty);
|
||||
void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty,
|
||||
json_object *json);
|
||||
void show_mroute(struct pim_instance *pim, struct vty *vty,
|
||||
pim_sgaddr *sg, bool fill, bool uj);
|
||||
void show_mroute_count(struct pim_instance *pim, struct vty *vty,
|
||||
bool uj);
|
||||
void show_mroute_summary(struct pim_instance *pim, struct vty *vty,
|
||||
json_object *json);
|
||||
|
||||
/*
|
||||
* Special Macro to allow us to get the correct pim_instance;
|
||||
|
Loading…
Reference in New Issue
Block a user