mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-28 21:20:48 +00:00
pimd: Add IGMP join sent/failed statistics
``` exit1-debian-11# sh ip igmp statistics IGMP statistics Interface : global V1 query : 0 V2 query : 0 V3 query : 0 V2 leave : 0 V1 report : 0 V2 report : 0 V3 report : 16 mtrace response : 0 mtrace request : 0 unsupported : 0 joins failed : 0 joins sent : 11 total groups : 4 total source groups : 0 exit1-debian-11# sh ip igmp statistics json { "global":{ "name":"global", "queryV1":0, "queryV2":0, "queryV3":0, "leaveV3":0, "reportV1":0, "reportV2":0, "reportV3":16, "mtraceResponse":0, "mtraceRequest":0, "unsupported":0, "totalGroups":4, "totalSourceGroups":0, "joinsFailed":0, "joinsSent":11 } } ``` Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
This commit is contained in:
parent
7547d5288e
commit
f2058cb425
@ -1284,9 +1284,9 @@ static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty,
|
||||
const char *ifname, bool uj)
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct igmp_stats rx_stats;
|
||||
struct igmp_stats igmp_stats;
|
||||
|
||||
igmp_stats_init(&rx_stats);
|
||||
igmp_stats_init(&igmp_stats);
|
||||
|
||||
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
||||
struct pim_interface *pim_ifp;
|
||||
@ -1303,7 +1303,9 @@ static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty,
|
||||
if (ifname && strcmp(ifname, ifp->name))
|
||||
continue;
|
||||
|
||||
rx_stats.total_groups +=
|
||||
igmp_stats.joins_failed += pim_ifp->igmp_ifstat_joins_failed;
|
||||
igmp_stats.joins_sent += pim_ifp->igmp_ifstat_joins_sent;
|
||||
igmp_stats.total_groups +=
|
||||
pim_ifp->gm_group_list
|
||||
? listcount(pim_ifp->gm_group_list)
|
||||
: 0;
|
||||
@ -1315,13 +1317,13 @@ static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty,
|
||||
if (pim_addr_is_any(src->source_addr))
|
||||
continue;
|
||||
|
||||
rx_stats.total_source_groups++;
|
||||
igmp_stats.total_source_groups++;
|
||||
}
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_socket_list, sock_node,
|
||||
igmp)) {
|
||||
igmp_stats_add(&rx_stats, &igmp->rx_stats);
|
||||
igmp_stats_add(&igmp_stats, &igmp->igmp_stats);
|
||||
}
|
||||
}
|
||||
if (uj) {
|
||||
@ -1333,45 +1335,58 @@ static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty,
|
||||
|
||||
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, "leaveV2", 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, "queryV1", igmp_stats.query_v1);
|
||||
json_object_int_add(json_row, "queryV2", igmp_stats.query_v2);
|
||||
json_object_int_add(json_row, "queryV3", igmp_stats.query_v3);
|
||||
json_object_int_add(json_row, "leaveV2", igmp_stats.leave_v2);
|
||||
json_object_int_add(json_row, "reportV1", igmp_stats.report_v1);
|
||||
json_object_int_add(json_row, "reportV2", igmp_stats.report_v2);
|
||||
json_object_int_add(json_row, "reportV3", igmp_stats.report_v3);
|
||||
json_object_int_add(json_row, "mtraceResponse",
|
||||
rx_stats.mtrace_rsp);
|
||||
igmp_stats.mtrace_rsp);
|
||||
json_object_int_add(json_row, "mtraceRequest",
|
||||
rx_stats.mtrace_req);
|
||||
igmp_stats.mtrace_req);
|
||||
json_object_int_add(json_row, "unsupported",
|
||||
rx_stats.unsupported);
|
||||
igmp_stats.unsupported);
|
||||
json_object_int_add(json_row, "totalGroups",
|
||||
rx_stats.total_groups);
|
||||
igmp_stats.total_groups);
|
||||
json_object_int_add(json_row, "totalSourceGroups",
|
||||
rx_stats.total_source_groups);
|
||||
igmp_stats.total_source_groups);
|
||||
json_object_int_add(json_row, "joinsFailed",
|
||||
igmp_stats.joins_failed);
|
||||
json_object_int_add(json_row, "joinsSent",
|
||||
igmp_stats.joins_sent);
|
||||
json_object_object_add(json, ifname ? ifname : "global",
|
||||
json_row);
|
||||
vty_json(vty, json);
|
||||
} else {
|
||||
vty_out(vty, "IGMP RX statistics\n");
|
||||
vty_out(vty, "Interface : %s\n",
|
||||
vty_out(vty, "IGMP 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, "V1 query : %u\n", igmp_stats.query_v1);
|
||||
vty_out(vty, "V2 query : %u\n", igmp_stats.query_v2);
|
||||
vty_out(vty, "V3 query : %u\n", igmp_stats.query_v3);
|
||||
vty_out(vty, "V2 leave : %u\n", igmp_stats.leave_v2);
|
||||
vty_out(vty, "V1 report : %u\n",
|
||||
igmp_stats.report_v1);
|
||||
vty_out(vty, "V2 report : %u\n",
|
||||
igmp_stats.report_v2);
|
||||
vty_out(vty, "V3 report : %u\n",
|
||||
igmp_stats.report_v3);
|
||||
vty_out(vty, "mtrace response : %u\n",
|
||||
igmp_stats.mtrace_rsp);
|
||||
vty_out(vty, "mtrace request : %u\n",
|
||||
igmp_stats.mtrace_req);
|
||||
vty_out(vty, "unsupported : %u\n",
|
||||
rx_stats.unsupported);
|
||||
igmp_stats.unsupported);
|
||||
vty_out(vty, "joins failed : %u\n",
|
||||
igmp_stats.joins_failed);
|
||||
vty_out(vty, "joins sent : %u\n",
|
||||
igmp_stats.joins_sent);
|
||||
vty_out(vty, "total groups : %u\n",
|
||||
rx_stats.total_groups);
|
||||
igmp_stats.total_groups);
|
||||
vty_out(vty, "total source groups : %u\n",
|
||||
rx_stats.total_source_groups);
|
||||
igmp_stats.total_source_groups);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3995,6 +4010,8 @@ DEFUN (clear_ip_pim_interface_traffic,
|
||||
pim_ifp->pim_ifstat_assert_send = 0;
|
||||
pim_ifp->pim_ifstat_bsm_rx = 0;
|
||||
pim_ifp->pim_ifstat_bsm_tx = 0;
|
||||
pim_ifp->igmp_ifstat_joins_sent = 0;
|
||||
pim_ifp->igmp_ifstat_joins_failed = 0;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
|
@ -53,8 +53,8 @@
|
||||
#if PIM_IPV == 4
|
||||
static void pim_if_igmp_join_del_all(struct interface *ifp);
|
||||
static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
|
||||
struct in_addr group_addr,
|
||||
struct in_addr source_addr);
|
||||
struct in_addr group_addr, struct in_addr source_addr,
|
||||
struct pim_interface *pim_ifp);
|
||||
#endif
|
||||
|
||||
void pim_if_init(struct pim_instance *pim)
|
||||
@ -576,7 +576,7 @@ void pim_if_addr_add(struct connected *ifc)
|
||||
close(ij->sock_fd);
|
||||
join_fd = igmp_join_sock(
|
||||
ifp->name, ifp->ifindex, ij->group_addr,
|
||||
ij->source_addr);
|
||||
ij->source_addr, pim_ifp);
|
||||
if (join_fd < 0) {
|
||||
char group_str[INET_ADDRSTRLEN];
|
||||
char source_str[INET_ADDRSTRLEN];
|
||||
@ -1248,12 +1248,16 @@ static struct gm_join *igmp_join_find(struct list *join_list,
|
||||
}
|
||||
|
||||
static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
|
||||
struct in_addr group_addr, struct in_addr source_addr)
|
||||
struct in_addr group_addr, struct in_addr source_addr,
|
||||
struct pim_interface *pim_ifp)
|
||||
{
|
||||
int join_fd;
|
||||
|
||||
pim_ifp->igmp_ifstat_joins_sent++;
|
||||
|
||||
join_fd = pim_socket_raw(IPPROTO_IGMP);
|
||||
if (join_fd < 0) {
|
||||
pim_ifp->igmp_ifstat_joins_failed++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1269,6 +1273,8 @@ static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
|
||||
__func__, join_fd, group_str, source_str, ifindex,
|
||||
ifname, errno, safe_strerror(errno));
|
||||
|
||||
pim_ifp->igmp_ifstat_joins_failed++;
|
||||
|
||||
close(join_fd);
|
||||
return -2;
|
||||
}
|
||||
@ -1288,7 +1294,7 @@ static struct gm_join *igmp_join_new(struct interface *ifp,
|
||||
assert(pim_ifp);
|
||||
|
||||
join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr,
|
||||
source_addr);
|
||||
source_addr, pim_ifp);
|
||||
if (join_fd < 0) {
|
||||
char group_str[INET_ADDRSTRLEN];
|
||||
char source_str[INET_ADDRSTRLEN];
|
||||
|
@ -189,6 +189,9 @@ struct pim_interface {
|
||||
bool bsm_enable; /* bsm processing enable */
|
||||
bool ucast_bsm_accept; /* ucast bsm processing */
|
||||
|
||||
uint32_t igmp_ifstat_joins_sent;
|
||||
uint32_t igmp_ifstat_joins_failed;
|
||||
|
||||
struct {
|
||||
bool enabled;
|
||||
uint32_t min_rx;
|
||||
|
@ -220,6 +220,7 @@ static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp,
|
||||
int fd;
|
||||
int join = 0;
|
||||
struct in_addr group;
|
||||
struct pim_interface *pim_ifp = ifp->info;
|
||||
|
||||
fd = pim_socket_mcast(IPPROTO_IGMP, ifaddr, ifp, 1);
|
||||
|
||||
@ -228,7 +229,8 @@ static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp,
|
||||
|
||||
if (PIM_IF_TEST_IGMP_LISTEN_ALLROUTERS(pim_options)) {
|
||||
if (inet_aton(PIM_ALL_ROUTERS, &group)) {
|
||||
if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex))
|
||||
if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex,
|
||||
pim_ifp))
|
||||
++join;
|
||||
} else {
|
||||
zlog_warn(
|
||||
@ -244,7 +246,7 @@ static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp,
|
||||
IGMP routers must receive general queries for querier election.
|
||||
*/
|
||||
if (inet_aton(PIM_ALL_SYSTEMS, &group)) {
|
||||
if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex))
|
||||
if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex, pim_ifp))
|
||||
++join;
|
||||
} else {
|
||||
zlog_warn(
|
||||
@ -254,7 +256,8 @@ static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp,
|
||||
}
|
||||
|
||||
if (inet_aton(PIM_ALL_IGMP_ROUTERS, &group)) {
|
||||
if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) {
|
||||
if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex,
|
||||
pim_ifp)) {
|
||||
++join;
|
||||
}
|
||||
} else {
|
||||
@ -489,16 +492,16 @@ static int igmp_recv_query(struct gm_sock *igmp, int query_version,
|
||||
/* Collecting IGMP Rx stats */
|
||||
switch (query_version) {
|
||||
case 1:
|
||||
igmp->rx_stats.query_v1++;
|
||||
igmp->igmp_stats.query_v1++;
|
||||
break;
|
||||
case 2:
|
||||
igmp->rx_stats.query_v2++;
|
||||
igmp->igmp_stats.query_v2++;
|
||||
break;
|
||||
case 3:
|
||||
igmp->rx_stats.query_v3++;
|
||||
igmp->igmp_stats.query_v3++;
|
||||
break;
|
||||
default:
|
||||
igmp->rx_stats.unsupported++;
|
||||
igmp->igmp_stats.unsupported++;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -630,7 +633,7 @@ static int igmp_v1_recv_report(struct gm_sock *igmp, struct in_addr from,
|
||||
}
|
||||
|
||||
/* Collecting IGMP Rx stats */
|
||||
igmp->rx_stats.report_v1++;
|
||||
igmp->igmp_stats.report_v1++;
|
||||
|
||||
if (PIM_DEBUG_IGMP_TRACE) {
|
||||
zlog_warn("%s %s: FIXME WRITEME", __FILE__, __func__);
|
||||
@ -782,7 +785,7 @@ int pim_igmp_packet(struct gm_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++;
|
||||
igmp->igmp_stats.unsupported++;
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -1159,7 +1162,7 @@ static struct gm_sock *igmp_sock_new(int fd, struct in_addr ifaddr,
|
||||
pim_ifp->gm_default_robustness_variable;
|
||||
igmp->sock_creation = pim_time_monotonic_sec();
|
||||
|
||||
igmp_stats_init(&igmp->rx_stats);
|
||||
igmp_stats_init(&igmp->igmp_stats);
|
||||
|
||||
if (mtrace_only) {
|
||||
igmp->mtrace_only = mtrace_only;
|
||||
|
@ -100,7 +100,7 @@ struct gm_sock {
|
||||
|
||||
bool mtrace_only;
|
||||
|
||||
struct igmp_stats rx_stats;
|
||||
struct igmp_stats igmp_stats;
|
||||
};
|
||||
|
||||
struct pim_interface;
|
||||
|
@ -626,7 +626,7 @@ int igmp_mtrace_recv_qry_req(struct gm_sock *igmp, struct ip *ip_hdr,
|
||||
}
|
||||
|
||||
/* Collecting IGMP Rx stats */
|
||||
igmp->rx_stats.mtrace_req++;
|
||||
igmp->igmp_stats.mtrace_req++;
|
||||
|
||||
if (PIM_DEBUG_MTRACE)
|
||||
mtrace_debug(pim_ifp, mtracep, igmp_msg_len);
|
||||
@ -843,7 +843,7 @@ int igmp_mtrace_recv_response(struct gm_sock *igmp, struct ip *ip_hdr,
|
||||
mtracep->checksum = checksum;
|
||||
|
||||
/* Collecting IGMP Rx stats */
|
||||
igmp->rx_stats.mtrace_rsp++;
|
||||
igmp->igmp_stats.mtrace_rsp++;
|
||||
|
||||
if (PIM_DEBUG_MTRACE)
|
||||
mtrace_debug(pim_ifp, mtracep, igmp_msg_len);
|
||||
|
@ -45,4 +45,6 @@ void igmp_stats_add(struct igmp_stats *a, struct igmp_stats *b)
|
||||
a->unsupported += b->unsupported;
|
||||
a->total_groups += b->total_groups;
|
||||
a->total_source_groups += b->total_source_groups;
|
||||
a->joins_sent += b->joins_sent;
|
||||
a->joins_failed += b->joins_failed;
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ struct igmp_stats {
|
||||
uint32_t unsupported;
|
||||
uint32_t total_groups;
|
||||
uint32_t total_source_groups;
|
||||
uint32_t joins_sent;
|
||||
uint32_t joins_failed;
|
||||
};
|
||||
|
||||
#if PIM_IPV == 4
|
||||
|
@ -130,7 +130,7 @@ int igmp_v2_recv_report(struct gm_sock *igmp, struct in_addr from,
|
||||
}
|
||||
|
||||
/* Collecting IGMP Rx stats */
|
||||
igmp->rx_stats.report_v2++;
|
||||
igmp->igmp_stats.report_v2++;
|
||||
|
||||
memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr));
|
||||
|
||||
@ -221,7 +221,7 @@ int igmp_v2_recv_leave(struct gm_sock *igmp, struct ip *ip_hdr,
|
||||
}
|
||||
|
||||
/* Collecting IGMP Rx stats */
|
||||
igmp->rx_stats.leave_v2++;
|
||||
igmp->igmp_stats.leave_v2++;
|
||||
|
||||
/*
|
||||
* RFC 3376
|
||||
|
@ -1854,7 +1854,7 @@ int igmp_v3_recv_report(struct gm_sock *igmp, struct in_addr from,
|
||||
}
|
||||
|
||||
/* Collecting IGMP Rx stats */
|
||||
igmp->rx_stats.report_v3++;
|
||||
igmp->igmp_stats.report_v3++;
|
||||
|
||||
num_groups = ntohs(
|
||||
*(uint16_t *)(igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET));
|
||||
|
@ -428,7 +428,7 @@ static int pim_sock_open(struct interface *ifp)
|
||||
return -1;
|
||||
|
||||
if (pim_socket_join(fd, qpim_all_pim_routers_addr,
|
||||
pim_ifp->primary_address, ifp->ifindex)) {
|
||||
pim_ifp->primary_address, ifp->ifindex, pim_ifp)) {
|
||||
close(fd);
|
||||
return -2;
|
||||
}
|
||||
@ -467,6 +467,8 @@ void pim_ifstat_reset(struct interface *ifp)
|
||||
pim_ifp->pim_ifstat_bsm_cfg_miss = 0;
|
||||
pim_ifp->pim_ifstat_ucast_bsm_cfg_miss = 0;
|
||||
pim_ifp->pim_ifstat_bsm_invalid_sz = 0;
|
||||
pim_ifp->igmp_ifstat_joins_sent = 0;
|
||||
pim_ifp->igmp_ifstat_joins_failed = 0;
|
||||
}
|
||||
|
||||
void pim_sock_reset(struct interface *ifp)
|
||||
|
@ -38,6 +38,7 @@
|
||||
|
||||
#include "pimd.h"
|
||||
#include "pim_mroute.h"
|
||||
#include "pim_iface.h"
|
||||
#include "pim_sock.h"
|
||||
#include "pim_str.h"
|
||||
|
||||
@ -233,7 +234,8 @@ int pim_socket_mcast(int protocol, pim_addr ifaddr, struct interface *ifp,
|
||||
return fd;
|
||||
}
|
||||
|
||||
int pim_socket_join(int fd, pim_addr group, pim_addr ifaddr, ifindex_t ifindex)
|
||||
int pim_socket_join(int fd, pim_addr group, pim_addr ifaddr, ifindex_t ifindex,
|
||||
struct pim_interface *pim_ifp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -248,11 +250,14 @@ int pim_socket_join(int fd, pim_addr group, pim_addr ifaddr, ifindex_t ifindex)
|
||||
ret = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &opt, sizeof(opt));
|
||||
#endif
|
||||
|
||||
pim_ifp->igmp_ifstat_joins_sent++;
|
||||
|
||||
if (ret) {
|
||||
flog_err(
|
||||
EC_LIB_SOCKET,
|
||||
"Failure socket joining fd=%d group %pPAs on interface address %pPAs: %m",
|
||||
fd, &group, &ifaddr);
|
||||
pim_ifp->igmp_ifstat_joins_failed++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -40,8 +40,8 @@ void pim_socket_ip_hdr(int fd);
|
||||
int pim_socket_raw(int protocol);
|
||||
int pim_socket_mcast(int protocol, pim_addr ifaddr, struct interface *ifp,
|
||||
uint8_t loop);
|
||||
int pim_socket_join(int fd, pim_addr group, pim_addr ifaddr, ifindex_t ifindex);
|
||||
|
||||
int pim_socket_join(int fd, pim_addr group, pim_addr ifaddr, ifindex_t ifindex,
|
||||
struct pim_interface *pim_ifp);
|
||||
int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len,
|
||||
struct sockaddr_storage *from, socklen_t *fromlen,
|
||||
struct sockaddr_storage *to, socklen_t *tolen,
|
||||
|
Loading…
Reference in New Issue
Block a user