]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: Add IGMP join sent/failed statistics 10768/head
authorDonatas Abraitis <donatas@opensourcerouting.org>
Thu, 10 Mar 2022 16:10:43 +0000 (18:10 +0200)
committerDonatas Abraitis <donatas@opensourcerouting.org>
Sun, 13 Mar 2022 17:31:34 +0000 (19:31 +0200)
```
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>
13 files changed:
pimd/pim_cmd.c
pimd/pim_iface.c
pimd/pim_iface.h
pimd/pim_igmp.c
pimd/pim_igmp.h
pimd/pim_igmp_mtrace.c
pimd/pim_igmp_stats.c
pimd/pim_igmp_stats.h
pimd/pim_igmpv2.c
pimd/pim_igmpv3.c
pimd/pim_pim.c
pimd/pim_sock.c
pimd/pim_sock.h

index 8906caf00f93458191eaa5bba591604d007c17c2..bf803a48366b970ac0ac09a25dbe56f7ff940d8c 100644 (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;
index d1b4966ec9b9796b8965200b7fcc32ef384f02f0..98fa4c4882519a8cdac11ff3edcfd8bf435cedae 100644 (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];
index a1c946149d5b61091ecfe94c679cfff269d0b400..244e1aedd189f0d69d357f507cbcf4c6d7e160bd 100644 (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;
index 592cd7ec457cfd921e91491e391e62c9d3fa980e..fcb335a5b323d16e6e8cb76e868d74056a39c008 100644 (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;
index 4d7229dcce2ed9605cf339d4928e58af8901bbed..4160dcb118ddc1fce43b79353d001bb3dd1ec3d7 100644 (file)
@@ -100,7 +100,7 @@ struct gm_sock {
 
        bool mtrace_only;
 
-       struct igmp_stats rx_stats;
+       struct igmp_stats igmp_stats;
 };
 
 struct pim_interface;
index d8210168e2c7997008249e84191a7348466c7688..11bb2db7eba019e8328da90ebcc71da7f7fd3c81 100644 (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);
index 0cf1bb1ec130e79ad1a1315c36335fb03d5908f1..e1eb166b655722a83d9263aa8ac839299f6bb12e 100644 (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;
 }
index 47167efb3abca716d92fd912740338d2c4f499e5..42c0c9ee3171735c6c756661540985f2f331a9e2 100644 (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
index a7c7c99ebf8b5de29b67c61e525bc07cf1a0bdd6..09a82069a2f8695b5d3787a857e1fe42cc93050f 100644 (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
index 87554bc8ba65294e0b8154a4f5637be372522ca8..1ce5fdc4b07b88291c4c97cb9d3a9d63ae004a83 100644 (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));
index d3edc5d0fed1bff20d3a90f234d8d8f6b39942d2..3980e4828d647f656f2bcf1647ec9e2ffda9d3a2 100644 (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)
index 92e2d184517e64c9ab7211908d0d6eb325c386cb..8619cc3f83df67857b43c871f4ef5820a1db18b6 100644 (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;
        }
 
index 97cbda0c10c9120a30ff4cb0281e5ac0cd4d056e..2e9c043e845753009c2e234145aae3ead9b80553 100644 (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,