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:
Donatas Abraitis 2022-03-10 18:10:43 +02:00
parent 7547d5288e
commit f2058cb425
13 changed files with 96 additions and 56 deletions

View File

@ -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;

View File

@ -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];

View File

@ -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;

View File

@ -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;

View File

@ -100,7 +100,7 @@ struct gm_sock {
bool mtrace_only;
struct igmp_stats rx_stats;
struct igmp_stats igmp_stats;
};
struct pim_interface;

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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)

View File

@ -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;
}

View File

@ -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,