mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-28 11:50:21 +00:00
pimd: show ip igmp statistics command
Command showing IGMP Rx statistics, useful for analyzing IGMP activity on interfaces. Signed-off-by: Mladen Sablic <mladen.sablic@gmail.com>
This commit is contained in:
parent
1c96f2fb96
commit
21313cbfda
@ -24,6 +24,7 @@ verification commands:
|
||||
show ip igmp groups retransmissions IGMP group retransmission
|
||||
show ip igmp sources IGMP sources information
|
||||
show ip igmp sources retransmissions IGMP source retransmission
|
||||
show ip igmp statistics IGMP statistics information
|
||||
show ip pim address PIM interface address
|
||||
show ip pim assert PIM interface assert
|
||||
show ip pim assert-internal PIM interface internal assert state
|
||||
|
@ -1294,6 +1294,76 @@ static void pim_show_interfaces_single(struct pim_instance *pim,
|
||||
}
|
||||
}
|
||||
|
||||
static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty,
|
||||
const char *ifname, uint8_t uj)
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct igmp_stats rx_stats;
|
||||
|
||||
igmp_stats_init(&rx_stats);
|
||||
|
||||
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
||||
struct pim_interface *pim_ifp;
|
||||
struct listnode *sock_node;
|
||||
struct igmp_sock *igmp;
|
||||
|
||||
pim_ifp = ifp->info;
|
||||
|
||||
if (!pim_ifp)
|
||||
continue;
|
||||
|
||||
if (ifname && strcmp(ifname, ifp->name))
|
||||
continue;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
|
||||
igmp)) {
|
||||
igmp_stats_add(&rx_stats, &igmp->rx_stats);
|
||||
}
|
||||
}
|
||||
if (uj) {
|
||||
json_object *json = NULL;
|
||||
json_object *json_row = NULL;
|
||||
|
||||
json = json_object_new_object();
|
||||
json_row = json_object_new_object();
|
||||
|
||||
json_object_string_add(json_row, "name", ifname ? ifname :
|
||||
"global");
|
||||
json_object_int_add(json_row, "queryV1", rx_stats.query_v1);
|
||||
json_object_int_add(json_row, "queryV2", rx_stats.query_v2);
|
||||
json_object_int_add(json_row, "queryV3", rx_stats.query_v3);
|
||||
json_object_int_add(json_row, "leaveV3", rx_stats.leave_v2);
|
||||
json_object_int_add(json_row, "reportV1", rx_stats.report_v1);
|
||||
json_object_int_add(json_row, "reportV2", rx_stats.report_v2);
|
||||
json_object_int_add(json_row, "reportV3", rx_stats.report_v3);
|
||||
json_object_int_add(json_row, "mtraceResponse",
|
||||
rx_stats.mtrace_rsp);
|
||||
json_object_int_add(json_row, "mtraceRequest",
|
||||
rx_stats.mtrace_req);
|
||||
json_object_int_add(json_row, "unsupported",
|
||||
rx_stats.unsupported);
|
||||
json_object_object_add(json, ifname ? ifname : "global",
|
||||
json_row);
|
||||
vty_out(vty, "%s\n", json_object_to_json_string_ext(
|
||||
json, JSON_C_TO_STRING_PRETTY));
|
||||
json_object_free(json);
|
||||
} else {
|
||||
vty_out(vty, "IGMP RX statistics\n");
|
||||
vty_out(vty, "Interface : %s\n",
|
||||
ifname ? ifname : "global");
|
||||
vty_out(vty, "V1 query : %u\n", rx_stats.query_v1);
|
||||
vty_out(vty, "V2 query : %u\n", rx_stats.query_v2);
|
||||
vty_out(vty, "V3 query : %u\n", rx_stats.query_v3);
|
||||
vty_out(vty, "V2 leave : %u\n", rx_stats.leave_v2);
|
||||
vty_out(vty, "V1 report : %u\n", rx_stats.report_v1);
|
||||
vty_out(vty, "V2 report : %u\n", rx_stats.report_v2);
|
||||
vty_out(vty, "V3 report : %u\n", rx_stats.report_v3);
|
||||
vty_out(vty, "mtrace response : %u\n", rx_stats.mtrace_rsp);
|
||||
vty_out(vty, "mtrace request : %u\n", rx_stats.mtrace_req);
|
||||
vty_out(vty, "unsupported : %u\n", rx_stats.unsupported);
|
||||
}
|
||||
}
|
||||
|
||||
static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
|
||||
uint8_t uj)
|
||||
{
|
||||
@ -3527,6 +3597,33 @@ DEFUN (show_ip_igmp_sources_retransmissions,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_ip_igmp_statistics,
|
||||
show_ip_igmp_statistics_cmd,
|
||||
"show ip igmp [vrf NAME] statistics [interface WORD] [json]",
|
||||
SHOW_STR
|
||||
IP_STR
|
||||
IGMP_STR
|
||||
VRF_CMD_HELP_STR
|
||||
"IGMP statistics\n"
|
||||
"interface\n"
|
||||
"IGMP interface\n"
|
||||
JSON_STR)
|
||||
{
|
||||
int idx = 2;
|
||||
struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
|
||||
uint8_t uj = use_json(argc, argv);
|
||||
|
||||
if (!vrf)
|
||||
return CMD_WARNING;
|
||||
|
||||
if (argv_find(argv, argc, "WORD", &idx))
|
||||
igmp_show_statistics(vrf->info, vty, argv[idx]->arg, uj);
|
||||
else
|
||||
igmp_show_statistics(vrf->info, vty, NULL, uj);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_ip_pim_assert,
|
||||
show_ip_pim_assert_cmd,
|
||||
"show ip pim [vrf NAME] assert",
|
||||
@ -8644,6 +8741,7 @@ void pim_cmd_init(void)
|
||||
install_element(VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd);
|
||||
install_element(VIEW_NODE, &show_ip_igmp_sources_cmd);
|
||||
install_element(VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd);
|
||||
install_element(VIEW_NODE, &show_ip_igmp_statistics_cmd);
|
||||
install_element(VIEW_NODE, &show_ip_pim_assert_cmd);
|
||||
install_element(VIEW_NODE, &show_ip_pim_assert_internal_cmd);
|
||||
install_element(VIEW_NODE, &show_ip_pim_assert_metric_cmd);
|
||||
|
@ -303,6 +303,21 @@ static int igmp_recv_query(struct igmp_sock *igmp, int query_version,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Collecting IGMP Rx stats */
|
||||
switch (query_version) {
|
||||
case 1:
|
||||
igmp->rx_stats.query_v1++;
|
||||
break;
|
||||
case 2:
|
||||
igmp->rx_stats.query_v2++;
|
||||
break;
|
||||
case 3:
|
||||
igmp->rx_stats.query_v3++;
|
||||
break;
|
||||
default:
|
||||
igmp->rx_stats.unsupported++;
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC 3376 defines some guidelines on operating in backwards
|
||||
* compatibility with older versions of IGMP but there are some gaps in
|
||||
@ -400,6 +415,9 @@ static int igmp_v1_recv_report(struct igmp_sock *igmp, struct in_addr from,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Collecting IGMP Rx stats */
|
||||
igmp->rx_stats.report_v1++;
|
||||
|
||||
if (PIM_DEBUG_IGMP_TRACE) {
|
||||
zlog_warn("%s %s: FIXME WRITEME", __FILE__,
|
||||
__PRETTY_FUNCTION__);
|
||||
@ -524,6 +542,9 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len)
|
||||
|
||||
zlog_warn("Ignoring unsupported IGMP message type: %d", msg_type);
|
||||
|
||||
/* Collecting IGMP Rx stats */
|
||||
igmp->rx_stats.unsupported++;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -867,6 +888,8 @@ static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr,
|
||||
pim_ifp->igmp_default_robustness_variable;
|
||||
igmp->sock_creation = pim_time_monotonic_sec();
|
||||
|
||||
igmp_stats_init(&igmp->rx_stats);
|
||||
|
||||
if (mtrace_only) {
|
||||
igmp->mtrace_only = mtrace_only;
|
||||
return igmp;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <zebra.h>
|
||||
#include "vty.h"
|
||||
#include "linklist.h"
|
||||
#include "pim_igmp_stats.h"
|
||||
|
||||
/*
|
||||
The following sizes are likely to support
|
||||
@ -94,6 +95,8 @@ struct igmp_sock {
|
||||
|
||||
struct list *igmp_group_list; /* list of struct igmp_group */
|
||||
struct hash *igmp_group_hash;
|
||||
|
||||
struct igmp_stats rx_stats;
|
||||
};
|
||||
|
||||
struct igmp_sock *pim_igmp_sock_lookup_ifaddr(struct list *igmp_sock_list,
|
||||
|
@ -671,6 +671,9 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Collecting IGMP Rx stats */
|
||||
igmp->rx_stats.mtrace_req++;
|
||||
|
||||
if (PIM_DEBUG_MTRACE)
|
||||
mtrace_debug(pim_ifp, mtracep, igmp_msg_len);
|
||||
|
||||
@ -881,6 +884,9 @@ int igmp_mtrace_recv_response(struct igmp_sock *igmp, struct ip *ip_hdr,
|
||||
|
||||
mtracep->checksum = checksum;
|
||||
|
||||
/* Collecting IGMP Rx stats */
|
||||
igmp->rx_stats.mtrace_rsp++;
|
||||
|
||||
if (PIM_DEBUG_MTRACE)
|
||||
mtrace_debug(pim_ifp, mtracep, igmp_msg_len);
|
||||
|
||||
|
42
pimd/pim_igmp_stats.c
Normal file
42
pimd/pim_igmp_stats.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* PIM for FRRouting
|
||||
* Copyright (C) 2018 Mladen Sablic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "pim_igmp_stats.h"
|
||||
|
||||
void igmp_stats_init(struct igmp_stats *stats)
|
||||
{
|
||||
memset(stats, 0, sizeof(struct igmp_stats));
|
||||
}
|
||||
|
||||
void igmp_stats_add(struct igmp_stats *a, struct igmp_stats *b)
|
||||
{
|
||||
if (!a || !b)
|
||||
return;
|
||||
|
||||
a->query_v1 += b->query_v1;
|
||||
a->query_v2 += b->query_v2;
|
||||
a->query_v3 += b->query_v3;
|
||||
a->report_v1 += b->report_v1;
|
||||
a->report_v2 += b->report_v2;
|
||||
a->report_v3 += b->report_v3;
|
||||
a->leave_v2 += b->leave_v2;
|
||||
a->mtrace_rsp += b->mtrace_rsp;
|
||||
a->mtrace_req += b->mtrace_req;
|
||||
a->unsupported += b->unsupported;
|
||||
}
|
41
pimd/pim_igmp_stats.h
Normal file
41
pimd/pim_igmp_stats.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* PIM for FRRouting
|
||||
* Copyright (C) 2018 Mladen Sablic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef PIM_IGMP_STATS_H
|
||||
#define PIM_IGMP_STATS_H
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
struct igmp_stats {
|
||||
uint32_t query_v1;
|
||||
uint32_t query_v2;
|
||||
uint32_t query_v3;
|
||||
uint32_t report_v1;
|
||||
uint32_t report_v2;
|
||||
uint32_t report_v3;
|
||||
uint32_t leave_v2;
|
||||
uint32_t mtrace_rsp;
|
||||
uint32_t mtrace_req;
|
||||
uint32_t unsupported;
|
||||
};
|
||||
|
||||
void igmp_stats_init(struct igmp_stats *stats);
|
||||
void igmp_stats_add(struct igmp_stats *a, struct igmp_stats *b);
|
||||
|
||||
#endif /* PIM_IGMP_STATS_H */
|
@ -121,6 +121,9 @@ int igmp_v2_recv_report(struct igmp_sock *igmp, struct in_addr from,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Collecting IGMP Rx stats */
|
||||
igmp->rx_stats.report_v2++;
|
||||
|
||||
memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr));
|
||||
|
||||
if (PIM_DEBUG_IGMP_PACKETS) {
|
||||
@ -167,6 +170,9 @@ int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Collecting IGMP Rx stats */
|
||||
igmp->rx_stats.leave_v2++;
|
||||
|
||||
memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr));
|
||||
|
||||
if (PIM_DEBUG_IGMP_PACKETS) {
|
||||
|
@ -1900,6 +1900,9 @@ int igmp_v3_recv_report(struct igmp_sock *igmp, struct in_addr from,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Collecting IGMP Rx stats */
|
||||
igmp->rx_stats.report_v3++;
|
||||
|
||||
num_groups = ntohs(
|
||||
*(uint16_t *)(igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET));
|
||||
if (num_groups < 1) {
|
||||
|
@ -20,6 +20,7 @@ pimd_libpim_a_SOURCES = \
|
||||
pimd/pim_ifchannel.c \
|
||||
pimd/pim_igmp.c \
|
||||
pimd/pim_igmp_mtrace.c \
|
||||
pimd/pim_igmp_stats.c \
|
||||
pimd/pim_igmpv2.c \
|
||||
pimd/pim_igmpv3.c \
|
||||
pimd/pim_instance.c \
|
||||
@ -69,6 +70,7 @@ noinst_HEADERS += \
|
||||
pimd/pim_igmp.h \
|
||||
pimd/pim_igmp_join.h \
|
||||
pimd/pim_igmp_mtrace.h \
|
||||
pimd/pim_igmp_stats.h \
|
||||
pimd/pim_igmpv2.h \
|
||||
pimd/pim_igmpv3.h \
|
||||
pimd/pim_instance.h \
|
||||
|
Loading…
Reference in New Issue
Block a user