diff --git a/build/rpm/pcp.spec.in b/build/rpm/pcp.spec.in index 62b07568681..e6529ae013e 100755 --- a/build/rpm/pcp.spec.in +++ b/build/rpm/pcp.spec.in @@ -1674,6 +1674,20 @@ This package contains the PCP Performance Metrics Domain Agent (PMDA) for collecting statistics for nVidia RDMA over Converged Ethernet (RoCE) devices. # end pcp-pmda-rocestat +# +# pcp-pmda-rds +# +%package pmda-rds +License: GPL-2.0-or-later +Summary: Performance Co-Pilot (PCP) metrics for Reliable Datagram Sockets (RDS) protocol +URL: https://pcp.io +Requires: pcp = @package_version@ pcp-libs = @package_version@ +Requires: python3-pcp +%description pmda-rds +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting statistics for RDS connections +# end pcp-pmda-rds + # # pcp-pmda-openvswitch # @@ -2376,6 +2390,7 @@ basic_manifest | keep '(etc/pcp|pmdas)/podman(/|$)' >pcp-pmda-podman-files basic_manifest | keep '(etc/pcp|pmdas)/postfix(/|$)' >pcp-pmda-postfix-files basic_manifest | keep '(etc/pcp|pmdas)/postgresql(/|$)' >pcp-pmda-postgresql-files basic_manifest | keep '(etc/pcp|pmdas)/rabbitmq(/|$)' >pcp-pmda-rabbitmq-files +basic_manifest | keep '(etc/pcp|pmdas)/rds(/|$)' >pcp-pmda-rds-files basic_manifest | keep '(etc/pcp|pmdas)/redis(/|$)' >pcp-pmda-redis-files basic_manifest | keep '(etc/pcp|pmdas)/resctrl(/|$)|sys-fs-resctrl' >pcp-pmda-resctrl-files basic_manifest | keep '(etc/pcp|pmdas)/rocestat(/|$)' >pcp-pmda-rocestat-files @@ -2415,7 +2430,7 @@ for pmda_package in \ nutcracker nvidia \ openmetrics opentelemetry openvswitch oracle \ pdns perfevent podman postfix postgresql \ - rabbitmq redis resctrl rocestat roomtemp rsyslog \ + rabbitmq rds redis resctrl rocestat roomtemp rsyslog \ samba sendmail shping slurm smart snmp \ sockets statsd summary systemd \ unbound uwsgi \ @@ -2856,6 +2871,9 @@ done %preun pmda-rocestat %{pmda_remove "$1" "rocestat"} +%preun pmda-rds +%{pmda_remove "$1" "rds"} + %preun pmda-uwsgi %{pmda_remove "$1" "uwsgi"} %endif @@ -3184,6 +3202,8 @@ fi %files pmda-rocestat -f pcp-pmda-rocestat-files.rpm +%files pmda-rds -f pcp-pmda-rds-files.rpm + %files pmda-uwsgi -f pcp-pmda-uwsgi-files.rpm %files export-pcp2graphite -f pcp-export-pcp2graphite-files.rpm diff --git a/build/rpm/redhat.spec b/build/rpm/redhat.spec index c53336d8dc8..0c2fc9d4875 100644 --- a/build/rpm/redhat.spec +++ b/build/rpm/redhat.spec @@ -1781,6 +1781,21 @@ collecting statistics for nVidia RDMA over Converged Ethernet (RoCE) devices. # end pcp-pmda-rocestat %endif +# +# pcp-pmda-rds +# +%package pmda-rds +License: GPL-2.0-or-later +Summary: Performance Co-Pilot (PCP) metrics for Reliable Datagram Sockets (RDS) protocol +URL: https://pcp.io +Requires: pcp = %{version}-%{release} pcp-libs = %{version}-%{release} +Requires: python3-pcp +%description pmda-rds +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting statistics for RDS connections. +# end pcp-pmda-rds +%endif + %if !%{disable_mongodb} # # pcp-pmda-mongodb @@ -2516,6 +2531,7 @@ basic_manifest | keep '(etc/pcp|pmdas)/podman(/|$)' >pcp-pmda-podman-files basic_manifest | keep '(etc/pcp|pmdas)/postfix(/|$)' >pcp-pmda-postfix-files basic_manifest | keep '(etc/pcp|pmdas)/postgresql(/|$)' >pcp-pmda-postgresql-files basic_manifest | keep '(etc/pcp|pmdas)/rabbitmq(/|$)' >pcp-pmda-rabbitmq-files +basic_manifest | keep '(etc/pcp|pmdas)/rds(/|$)' >pcp-pmda-rds-files basic_manifest | keep '(etc/pcp|pmdas)/redis(/|$)' >pcp-pmda-redis-files basic_manifest | keep '(etc/pcp|pmdas)/resctrl(/|$)|sys-fs-resctrl' >pcp-pmda-resctrl-files basic_manifest | keep '(etc/pcp|pmdas)/rocestat(/|$)' >pcp-pmda-rocestat-files @@ -2556,7 +2572,7 @@ for pmda_package in \ nutcracker nvidia \ openmetrics opentelemetry openvswitch oracle \ pdns perfevent podman postfix postgresql \ - rabbitmq redis resctrl rocestat roomtemp rpm rsyslog \ + rabbitmq rds redis resctrl rocestat roomtemp rpm rsyslog \ samba sendmail shping slurm smart snmp \ sockets statsd summary systemd \ unbound uwsgi \ @@ -2949,6 +2965,9 @@ exit 0 %preun pmda-rocestat %{pmda_remove "$1" "rocestat"} +%preun pmda-rds +%{pmda_remove "$1" "rds"} + %endif %preun pmda-apache @@ -3304,6 +3323,8 @@ fi %files pmda-rocestat -f pcp-pmda-rocestat-files.rpm +%files pmda-rds -f pcp-pmda-rds-files.rpm + %files pmda-uwsgi -f pcp-pmda-uwsgi-files.rpm %files export-pcp2graphite -f pcp-export-pcp2graphite-files.rpm diff --git a/qa/1998 b/qa/1998 new file mode 100644 index 00000000000..1a4f6461db3 --- /dev/null +++ b/qa/1998 @@ -0,0 +1,78 @@ +#!/bin/sh +# PCP QA Test No. 1998 +# Testing PCP RDS PMDA - install, remove and values. +# +# Copyright (c) 2025 Oracle and/or its affiliates. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# 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. +# + +seq=`basename $0` +echo "QA output created by $seq" + +. ./common.python + +pmda_path="$PCP_PMDAS_DIR/rds" +pmda_script="$pmda_path/pmdards.python" +test_script="rds/rds_test.python" + +[ -d $pmda_path ] || _notrun "RDS PMDA is not installed" + +$python -c "from pcp import pmda" >/dev/null 2>&1 +[ $? -eq 0 ] || _notrun "python pcp pmda module not installed" + +status=1 # failure is the default! +trap "_cleanup_pmda rds; exit \$status" 0 1 2 3 15 + +pmdards_filter() +{ + sed \ + -e "s/Ran [0-9]* tests in [0-9]*\.[0-9][0-9]*s/Ran X tests in YYYs/" \ + -e "s/FAILED (failures=[0-9]*)/FAILED (failures=X)/" \ + -e "/^$/d" +} + +pmdards_remove() +{ + cd $pmda_path + echo + echo "=== Removing RDS agent ===" + $sudo ./Remove >$tmp.out 2>&1 +} + +pmdards_install() +{ + cd $pmda_path + $sudo ./Remove >/dev/null 2>&1 + + echo + echo "=== Installing RDS agent ===" + $sudo ./Install $tmp.out 2>&1 + cd $here +} + +# Real QA test starts here +_prepare_pmda rds + +pmdards_install + +echo "=== Report metric values ===" + +metrics=`pminfo rds | LC_COLLATE=POSIX sort` + +pminfo -dfmtT $metrics 2>&1 + +pmdards_remove + +# Success, all done +status=0 +exit \ No newline at end of file diff --git a/qa/1998.out b/qa/1998.out new file mode 100644 index 00000000000..b2ed7dd679e --- /dev/null +++ b/qa/1998.out @@ -0,0 +1,638 @@ +QA output created by 1998 + +=== Installing RDS agent === +=== Report metric values === + +rds.lat.arp_cache PMID: 255.9.2 [] + Data Type: string InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: none + value "10.211.8.2 dev eth0 lladdr 58:ac:78:e3:66:7f used 451734/451794/451734 probes 0 STALE +10.211.8.3 dev eth0 lladdr 58:ac:78:e3:59:ff used 451741/451801/451741 probes 0 STALE +10.211.8.1 dev eth0 lladdr 00:00:0c:9f:f0:1f ref 1 used 12/0/12 probes 1 REACHABLE +10.211.8.40 dev eth0 lladdr 56:6f:f5:fe:00:a9 used 12395/12390/12358 probes 1 STALE +10.211.8.19 dev eth0 lladdr a4:4c:11:6c:c8:3f used 436243/436303/436243 probes 0 STALE +fe80::5:73ff:fea0:2 dev eth0 lladdr 00:05:73:a0:00:02 router used 823/823/795 probes 1 STALE +fe80::5aac:78ff:fee3:667f dev eth0 lladdr 58:ac:78:e3:66:7f router used 818/818/791 probes 1 STALE +2606:b400:400:3451::2 dev eth0 lladdr 58:ac:78:e3:66:7f router used 15293/15293/15258 probes 1 STALE +" + +rds.lat.rds_ping PMID: 255.9.1 [] + Data Type: string InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: none + value "{}" + +rds.lat.ping PMID: 255.9.0 [] + Data Type: string InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: none + value "" + +rds.info.retrans_queue PMID: 255.8.6 [] + Data Type: string InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: none +No value(s) available! + +rds.info.send_queue PMID: 255.8.5 [] + Data Type: string InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: none +No value(s) available! + +rds.info.recv_queue PMID: 255.8.4 [] + Data Type: string InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: none +No value(s) available! + +rds.info.rds_conns PMID: 255.8.3 [] + Data Type: string InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: none +No value(s) available! + +rds.info.sockets PMID: 255.8.2 [] + Data Type: string InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: none + value "0.0.0.0 0 0.0.0.0 0 106496 106496 365993 0 31541 python3 +0.0.0.0 0 0.0.0.0 0 106496 106496 366074 0 31541 python3 +0.0.0.0 0 0.0.0.0 0 106496 106496 366122 0 31541 python3 +0.0.0.0 0 0.0.0.0 0 106496 106496 366135 0 31541 python3 +0.0.0.0 0 0.0.0.0 0 106496 106496 366148 0 31541 python3 +0.0.0.0 0 0.0.0.0 0 106496 106496 366316 0 31541 python3 +0.0.0.0 0 0.0.0.0 0 106496 106496 366332 0 31541 python3 +0.0.0.0 0 0.0.0.0 0 106496 106496 366397 0 31541 python3 +0.0.0.0 0 0.0.0.0 0 106496 106496 366398 0 31541 python3 +" + +rds.info.tcp_conns PMID: 255.8.1 [] + Data Type: string InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: none +No value(s) available! + +rds.info.ib_conns PMID: 255.8.0 [] + Data Type: string InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: none +No value(s) available! + +rds.sock.bytes_freed_from_sock PMID: 255.7.1 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: byte + value 0 + +rds.sock.bytes_added_to_sock PMID: 255.7.0 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: byte + value 0 + +rds.ib.listen_closed_stale PMID: 255.6.62 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.tasklet_call PMID: 255.6.60 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.evt_handler_call PMID: 255.6.59 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.connect_raced PMID: 255.6.58 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.srq.empty_refills PMID: 255.6.57 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.srq.refills PMID: 255.6.56 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.srq.lows PMID: 255.6.55 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rdma_mr.1m_pool_depleted PMID: 255.6.54 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rdma_mr.1m_pool_wait PMID: 255.6.53 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rdma_mr.1m_pool_flush PMID: 255.6.52 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rdma_mr.1m_used PMID: 255.6.51 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rdma_mr.1m_free PMID: 255.6.50 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rdma_mr.1m_alloc PMID: 255.6.49 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rdma_mr.8k_pool_depleted PMID: 255.6.48 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rdma_mr.8k_pool_wait PMID: 255.6.47 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rdma_mr.8k_pool_flush PMID: 255.6.46 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rdma_mr.8k_used PMID: 255.6.45 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rdma_mr.8k_free PMID: 255.6.44 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rdma_mr.8k_alloc PMID: 255.6.43 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.cm.watchdog_triggered PMID: 255.6.42 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.atomic.fadd PMID: 255.6.41 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.atomic.cswp PMID: 255.6.40 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.yield.success PMID: 255.6.39 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.yield.accepting PMID: 255.6.38 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.yield.expired PMID: 255.6.37 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.yield.stale PMID: 255.6.36 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.yield.right_of_way PMID: 255.6.35 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.yield.yielding PMID: 255.6.34 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.cache.nmb_cache_removed PMID: 255.6.33 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.cache.nmb_cache_added PMID: 255.6.32 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.cache.cache_removed PMID: 255.6.31 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.cache.cache_added PMID: 255.6.30 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.cache.get_miss PMID: 255.6.29 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.cache.get_ready PMID: 255.6.28 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.cache.put_percpu PMID: 255.6.27 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.cache.get_percpu PMID: 255.6.26 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.cache.free PMID: 255.6.25 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.cache.alloc PMID: 255.6.24 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.cache.put_free PMID: 255.6.23 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.cache.put_alloc PMID: 255.6.22 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.cache.put PMID: 255.6.21 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.cache.get PMID: 255.6.20 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.credit_updates PMID: 255.6.19 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.total_incs PMID: 255.6.18 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.total_frags PMID: 255.6.17 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.alloc_limit PMID: 255.6.16 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.refill_lock_taken PMID: 255.6.15 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.refill_from_thread PMID: 255.6.14 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.refill_from_cq PMID: 255.6.13 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.refill_from_cm PMID: 255.6.12 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.ring_empty PMID: 255.6.11 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.rx.cq_event PMID: 255.6.10 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.tx.cq_event PMID: 255.6.61 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.tx.credit_updates PMID: 255.6.9 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.tx.stalled PMID: 255.6.8 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.tx.sg_mapping_failure PMID: 255.6.7 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.tx.throttle PMID: 255.6.6 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.tx.ring_full PMID: 255.6.5 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.ack.received PMID: 255.6.4 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.ack.send_piggybacked PMID: 255.6.3 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.ack.send_delayed PMID: 255.6.2 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.ack.send_failure PMID: 255.6.1 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.ib.ack.sent PMID: 255.6.0 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.mem.copy_from_user PMID: 255.5.6 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.mem.copy_to_user PMID: 255.5.5 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.mem.page_rem_miss PMID: 255.5.4 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.mem.page_rem_hit PMID: 255.5.3 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.mem.page_frees PMID: 255.5.2 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.mem.page_gets PMID: 255.5.1 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.mem.page_allocs PMID: 255.5.0 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.sendq.send_lock_contention PMID: 255.4.3 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.sendq.q_full PMID: 255.4.2 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.sendq.q_empty PMID: 255.4.1 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.sendq.send_lock_q_raced PMID: 255.4.0 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.rx.drop.dead_sock PMID: 255.3.30 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.rx.drop.no_sock PMID: 255.3.29 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.rx.drop.old_seq PMID: 255.3.28 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.rx.drop.bad_csum PMID: 255.3.27 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.rx.recv_delivered PMID: 255.3.26 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.rx.recv_deliver_raced PMID: 255.3.25 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.rx.ack_reqd PMID: 255.3.24 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.rx.delayed_retry PMID: 255.3.23 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.rx.recv_imm_retry PMID: 255.3.22 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.rx.recv_mprds_pong PMID: 255.3.21 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.rx.recv_mprds_ping PMID: 255.3.20 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.rx.recv_hb_pong PMID: 255.3.19 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.rx.recv_hb_ping PMID: 255.3.18 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.rx.recv_pong PMID: 255.3.17 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.rx.recv_ping PMID: 255.3.16 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.rx.recv_rdma_bytes PMID: 255.3.15 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: byte + value 0 + +rds.packet.rx.recv_queued PMID: 255.3.14 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.tx.send_stuck_rm PMID: 255.3.13 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.tx.send_drop_acked PMID: 255.3.12 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.tx.send_ack_reqd PMID: 255.3.11 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.tx.send_delayed_retry PMID: 255.3.10 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.tx.send_imm_retry PMID: 255.3.9 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.tx.send_mprds_pong PMID: 255.3.8 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.tx.send_mprds_ping PMID: 255.3.7 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.tx.send_hb_pong PMID: 255.3.6 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.tx.send_hb_ping PMID: 255.3.5 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.tx.send_pong PMID: 255.3.4 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.tx.send_ping PMID: 255.3.3 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.tx.send_rdma_bytes PMID: 255.3.2 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: byte + value 0 + +rds.packet.tx.send_rdma PMID: 255.3.1 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.packet.tx.send_queued PMID: 255.3.0 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.cong.cong_update_received PMID: 255.2.3 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.cong.cong_send_error PMID: 255.2.2 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.cong.cong_update_queued PMID: 255.2.1 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.cong.cong_send_blocked PMID: 255.2.0 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.conn.qos_threshold_exceeded PMID: 255.1.1 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +rds.conn.conn_reset PMID: 255.1.0 [] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: count + value 0 + +=== Removing RDS agent === diff --git a/qa/group b/qa/group index 40c71e24d74..0eebb1f4ec2 100644 --- a/qa/group +++ b/qa/group @@ -2310,5 +2310,6 @@ telnet-probe 1995 pmda.linux local 1996 pmda.infiniband local 1997 pcp nfsiostat python local +1998 pmda.rds local python 4751 libpcp threads valgrind local pcp helgrind 9000 other local diff --git a/src/pmdas/GNUmakefile b/src/pmdas/GNUmakefile index 6d96bcfe3c3..a47f0a3db4d 100644 --- a/src/pmdas/GNUmakefile +++ b/src/pmdas/GNUmakefile @@ -41,7 +41,7 @@ PYPMDAS = bcc gluster zswap unbound mic haproxy \ libvirt lio openmetrics opentelemetry \ elasticsearch bpftrace mssql netcheck \ rabbitmq openvswitch nfsclient mongodb \ - uwsgi rocestat hdb + uwsgi rocestat hdb rds SUBDIRS = $(CPMDAS) $(PLPMDAS) $(PYPMDAS) LDIRT = pmcd.conf diff --git a/src/pmdas/rds/GNUmakefile b/src/pmdas/rds/GNUmakefile new file mode 100644 index 00000000000..1eaa4aa1042 --- /dev/null +++ b/src/pmdas/rds/GNUmakefile @@ -0,0 +1,63 @@ +# +# Copyright (c) 2025 Oracle and/or its affiliates. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# 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. +# + +TOPDIR = ../../.. +include $(TOPDIR)/src/include/builddefs + +IAM = rds +PYSCRIPT = pmda$(IAM).python +LDIRT = domain.h root pmns $(IAM).log +DOMAIN = RDS +SUBDIRS = modules + +PMDAADMDIR = $(PCP_PMDASADM_DIR)/$(IAM) +PMDATMPDIR = $(PCP_PMDAS_DIR)/$(IAM) + +MAN_SECTION = 1 +MAN_PAGES = pmda$(IAM).$(MAN_SECTION) +MAN_DEST = $(PCP_MAN_DIR)/man$(MAN_SECTION) + +default_pcp default :: build-me + +include $(BUILDRULES) + +ifeq "$(HAVE_PYTHON)" "true" +build-me: check_domain + +install_pcp install :: default + $(INSTALL) -m 755 -d $(PMDAADMDIR) + $(INSTALL) -m 755 -d $(PMDATMPDIR) + $(INSTALL) -m 755 -t $(PMDATMPDIR) Install Remove $(PYSCRIPT) $(PMDAADMDIR) + @$(INSTALL_MAN) + +default_pcp default :: $(SUBDIRS) + $(SUBDIRS_MAKERULE) + +install_pcp install :: $(SUBDIRS) + $(SUBDIRS_MAKERULE) +else +build-me: +install_pcp install: + @$(INSTALL_MAN) +endif + +check_domain: ../../pmns/stdpmid + $(DOMAIN_PYTHONRULE) + +check:: $(PYSCRIPT) + $(PYLINT) $^ + +check:: $(MAN_PAGES) + $(MANLINT) $^ diff --git a/src/pmdas/rds/Install b/src/pmdas/rds/Install new file mode 100755 index 00000000000..05992cd24d6 --- /dev/null +++ b/src/pmdas/rds/Install @@ -0,0 +1,32 @@ +# +# Copyright (c) 2025 Oracle and/or its affiliates. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# 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. +# + +. $PCP_DIR/etc/pcp.env +. $PCP_SHARE_DIR/lib/pmdaproc.sh + +iam=rds +python_opt=true +daemon_opt=false + +# +# See pmcd(1) man page. PMDA starts up in the "not ready" state. +# When it has finished starting up, it sends a PM_ERR_PMDAREADY +# error PDU to PMCD to indicate it's ready to start processing +# requests. + +ipc_prot="binary notready" +pmdaSetup +pmdaInstall +exit diff --git a/src/pmdas/rds/Remove b/src/pmdas/rds/Remove new file mode 100755 index 00000000000..a77324f9610 --- /dev/null +++ b/src/pmdas/rds/Remove @@ -0,0 +1,35 @@ +# +# Copyright (c) 2025 Oracle and/or its affiliates. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# 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. +# +# Remove the rds PMDA +# + +# source the PCP configuration environment variables +. $PCP_DIR/etc/pcp.env + +# Get the common procedures and variable assignments +# +. $PCP_SHARE_DIR/lib/pmdaproc.sh + +# The name of the PMDA +# +iam=rds + +# Do it +# +pmdaSetup +pmdaRemove + + +exit diff --git a/src/pmdas/rds/domain.h b/src/pmdas/rds/domain.h new file mode 100644 index 00000000000..c57ad897123 --- /dev/null +++ b/src/pmdas/rds/domain.h @@ -0,0 +1 @@ +#define RDS 255 diff --git a/src/pmdas/rds/modules/GNUmakefile b/src/pmdas/rds/modules/GNUmakefile new file mode 100644 index 00000000000..10bcb14a85b --- /dev/null +++ b/src/pmdas/rds/modules/GNUmakefile @@ -0,0 +1,35 @@ +# +# Copyright (c) 2025 Oracle and/or its affiliates +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER +# +# 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. +# + +TOPDIR = ../../../.. +include $(TOPDIR)/src/include/builddefs + +IAM = rds +PYSCRIPTS = $(shell echo *.python) + +PMDAADMDIR = $(PCP_PMDASADM_DIR)/$(IAM)/modules +PMDATMPDIR = $(PCP_PMDAS_DIR)/$(IAM)/modules + +include $(BUILDRULES) + +default_pcp default: $(SCRIPTS) + +install_pcp install: default + $(INSTALL) -m 755 -d $(PMDAADMDIR) + $(INSTALL) -m 755 -d $(PMDATMPDIR) + $(INSTALL) -m 644 -t $(PMDATMPDIR) $(PYSCRIPTS) $(PMDAADMDIR) + +check:: $(PYSCRIPTS) + $(PYLINT) $^ diff --git a/src/pmdas/rds/modules/__init__.python b/src/pmdas/rds/modules/__init__.python new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/pmdas/rds/modules/ping.python b/src/pmdas/rds/modules/ping.python new file mode 100644 index 00000000000..8d7baa709d8 --- /dev/null +++ b/src/pmdas/rds/modules/ping.python @@ -0,0 +1,321 @@ +# Copyright (c) 2025 Oracle and/or its affiliates. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# 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. +# +""" +Python implementation of ping +""" + +# pylint: disable=too-many-arguments,too-many-positional-arguments +# pylint: disable=global-statement,no-member + +from collections import defaultdict +import json +import socket +import sys +import os +import time +import select +from datetime import datetime +import argparse +import struct +import ipaddress +import threading +import signal +import re +import concurrent.futures +from modules.rds_info import RdsInfo + +ICMP_ECHO = 8 +ICMP_MAX_RECV = 2048 +RDS_INFO_LEN = 176 +SOL_RDS = 276 +RDS_INFO_IB_CONNECTIONS = 10008 + +pings_sent = 0 +pending = 0 +OWN_ID = os.getpid() & 0xFFFF +pings_json = {} + + +def signal_handler(sig, frame): + sys.exit(0) + + +def create_socket(): + try: + sock_fd = socket.socket( + socket.AF_INET, socket.SOCK_RAW, 1) # 1 for ICMP + return sock_fd + except socket.error as err: + print("socket creation failed with error %s" % (err), file=sys.stderr) + return None + + +def bind_socket(sock_fd, src_ip): + src_port = 0 + try: + sock_fd.bind((src_ip, src_port)) + except socket.error as err: + print("socket bind failed with error %s" % (err), file=sys.stderr) + + +def calculate_checksum(source_string): + countTo = (int(len(source_string) / 2)) * 2 + total = 0 + count = 0 + + # Handle bytes in pairs (decoding as short ints) + loByte = 0 + hiByte = 0 + while count < countTo: + if sys.byteorder == "little": + loByte = source_string[count] + hiByte = source_string[count + 1] + else: + loByte = source_string[count + 1] + hiByte = source_string[count] + total = total + ((hiByte) * 256 + (loByte)) + count += 2 + + # Handle last byte if applicable (odd-number of bytes) + # Endianness should be irrelevant in this case + if countTo < len(source_string): # Check for odd length + loByte = source_string[len(source_string) - 1] + total += loByte + + total &= 0xffffffff # Truncate total to 32 bits (a variance from ping.c, which + # uses signed ints, but overflow is unlikely in ping) + + total = (total >> 16) + (total & 0xffff) # Add high 16 bits to low 16 bits + total += (total >> 16) # Add carry from above (if any) + answer = ~total & 0xffff # Invert and truncate to 16 bits + answer = socket.htons(answer) + + return answer + + +def create_rds_socket(): + try: + sock_fd = socket.socket(socket.PF_RDS, socket.SOCK_SEQPACKET, 0) + return sock_fd + except socket.error as err: + print("socket creation failed with error %s" % (err), file=sys.stderr) + return None + + +def htosi(data, signed): + hex_string = data.hex() + return int.from_bytes(bytes.fromhex(hex_string), byteorder='little', signed=signed) + + +def send_ping(sock_fd, src_ip, dst_ip_list, send_timestamps): + seq_number = 0 + global pings_sent + + for dst_ip in dst_ip_list: + checksum = 0 + header = struct.pack("!BBHHH", ICMP_ECHO, 0, + checksum, OWN_ID, seq_number) + checksum = calculate_checksum(header) + header = struct.pack("!BBHHH", ICMP_ECHO, 0, + checksum, OWN_ID, seq_number) + packet = header + try: + sock_fd.sendto(packet, (dst_ip, 1)) + send_timestamps[dst_ip] = datetime.now() + except socket.error as err: + print("socket send failed with error %s" % (err), file=sys.stderr) + # remove the added entry from the list + del send_timestamps[dst_ip] + pings_sent = pings_sent + 1 + + +def recv_pong(sock_fd, src_ip, num_dest, timeout, send_timestamps, print_all): + + inputs = [sock_fd] + outputs = [] + latencies_info = "" + pongs_rcvd = 0 + sock_fd.settimeout(timeout) + + select_timeout = timeout + + select_timeout_msec = select_timeout * 1000 + while True: + select_start_time = int(round(time.time() * 1000)) + readable, writable, exceptional = select.select( + inputs, outputs, inputs, select_timeout) + + for _ in readable: + try: + packet_data, (ipaddr, _) = sock_fd.recvfrom(ICMP_MAX_RECV) + icmp_header = struct.unpack("!BBHHH", packet_data[20:28]) + + if icmp_header[3] == OWN_ID: + latency = datetime.now() - send_timestamps[ipaddr] + lat_data = ("%s %s - %.3f |" % + (src_ip, ipaddr, latency.microseconds)) + latencies_info = latencies_info + lat_data + pongs_rcvd = pongs_rcvd + 1 + conn = "%s-%s" % (src_ip, ipaddr) + pings_json[conn] = latency.microseconds + del send_timestamps[ipaddr] + except KeyError: + continue + + curr_time = int(round(time.time() * 1000)) + time_elapsed = curr_time - select_start_time + select_timeout_msec = select_timeout_msec - time_elapsed + if select_timeout_msec < 0: + for keys, _ in send_timestamps.items(): + lat_data = "%s %s - timeout |" % (src_ip, keys) + latencies_info = latencies_info + lat_data + conn = "%s-%s" % (src_ip, keys) + pings_json[conn] = -1 + break + + select_timeout = select_timeout_msec/1000 + + if num_dest - pongs_rcvd == 0: + break + + if not (readable or writable or exceptional): + for keys, _ in send_timestamps.items(): + lat_data = "%s %s - timeout |" % (src_ip, keys) + latencies_info = latencies_info + lat_data + conn = "%s-%s" % (src_ip, keys) + pings_json[conn] = -1 + + break + + if not print_all: + print(latencies_info) + + +def get_each_entry_len(data): + try: + rds_info_len = data[-4:].decode() + except ValueError: + rds_info_len = data[-4:-2].decode() + + if '\x00' in rds_info_len: + rds_info_len = ' '.join(rds_info_len.split('\x00')) + data = data[:-4] + + rds_info_len = re.findall(r'\d+', rds_info_len) + rds_info_len = int(rds_info_len[-1]) + + return data, rds_info_len + +def ping_destinations(src_ip, dest_ip_list, timeout): + sock_fd = create_socket() + bind_socket(sock_fd, src_ip) + send_timestamps = {} + num_dest = len(dest_ip_list) + send_ping(sock_fd, src_ip, dest_ip_list, send_timestamps) + recv_pong(sock_fd, src_ip, num_dest, timeout, send_timestamps, True) + sock_fd.close() + + +def ping_all_avlbl_dest(timeout): + rds_info = RdsInfo() + rds_connections = rds_info.main('-I').split("\n") + + conns_dict = defaultdict(list) + + for conn in rds_connections: + saddr, daddr = conn.split()[0:2] + if(validate_ip(saddr) == 0 and validate_ip(daddr) == 0): + conns_dict[saddr].append(daddr) + + with concurrent.futures.ThreadPoolExecutor() as executor: + for saddr, dest_ip_list in conns_dict.items(): + executor.submit(ping_destinations, saddr, dest_ip_list, timeout) + + res = json.dumps(pings_json) + return res + + +def validate_ip(ip_addr_str): + try: + ipaddress.ip_address(ip_addr_str) + return 0 + except ValueError: + print("Invalid IP %s" % ip_addr_str, file=sys.stderr) + return 1 + + +def ping(args): + dest_ip_list = [str(item) for item in args.list.split(' ')] + for ip_addr in dest_ip_list: + if validate_ip(ip_addr): + print("Invalid IP being passed %s. Please rectify." % (ip_addr), file=sys.stderr) + sys.exit(1) + + sock_fd = create_socket() + bind_socket(sock_fd, args.source_ip) + + num_destinations = len(dest_ip_list) + send_timestamps = {} + + thread2 = threading.Thread(target=recv_pong, args=( + sock_fd, args.source_ip, num_destinations, args.timeout, send_timestamps, False)) + thread2.start() + + thread1 = threading.Thread(target=send_ping, args=( + sock_fd, args.source_ip, dest_ip_list, send_timestamps)) + thread1.start() + + thread2.join() + thread1.join() + + sock_fd.close() + + +def main(argv): + parser = argparse.ArgumentParser() + parser.add_argument(dest='destination_ip', + help="destination ip is mandatory") + parser = argparse.ArgumentParser(description='python version of ping utility.', + epilog="sample usage: ping.python -d \"dst_ip_1 dst_ip_2\" -I src_ip") + parser.add_argument('-d', '--list', type=str) + parser.add_argument('-I', '--source_ip', type=str) + parser.add_argument('-t', '--timeout', type=float, default=3) + parser.add_argument('-a', '--auto', action='store_true') + parser.add_argument('-c', '--count', type=int, default=-1) + + args = parser.parse_args() + + if args.auto: + ping_all_avlbl_dest(args.timeout) + print(pings_json) + sys.exit(1) + + else: + if args.count == -1: + while True: + ping(args) + time.sleep(1) + else: + iterations = args.count + while iterations > 0: + ping(args) + iterations = iterations - 1 + if iterations: + time.sleep(1) + + +signal.signal(signal.SIGINT, signal_handler) + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/src/pmdas/rds/modules/rds_info.python b/src/pmdas/rds/modules/rds_info.python new file mode 100644 index 00000000000..389ed5793f3 --- /dev/null +++ b/src/pmdas/rds/modules/rds_info.python @@ -0,0 +1,423 @@ +# Copyright (c) 2025 Oracle and/or its affiliates. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# 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. +# +import sys +import struct +import psutil +import socket +import ctypes +import binascii +from datetime import datetime + +# Constants for socket operations +PF_RDS = 21 +SOCK_SEQPACKET = 5 +SOL_RDS = 276 + +RDS_INFO_COUNTERS = 10000 +RDS_INFO_CONNECTIONS = 10001 +RDS_INFO_SEND_MESSAGES = 10003 +RDS_INFO_RETRANS_MESSAGES = 10004 +RDS_INFO_RECV_MESSAGES = 10005 +RDS_INFO_SOCKETS = 10006 +RDS_INFO_TCP_SOCKETS = 10007 +RDS_INFO_IB_CONNECTIONS = 10008 +RDS_INFO_CONN_PATHS = 10020 + +# Connection drop reasons +CONN_DROP_REASONS = [ + "--", "user reset", "invalid connection state", "failure to move to DOWN state", + "connection destroy", "conn_connect failure", "hb timeout", "reconnect timeout", + "cancel operation on socket", "race between ESTABLISHED event and drop", + "conn is not in CONNECTING state", "qp event", "incoming REQ in CONN_UP state", + "incoming REQ in CONNECTING state", "passive setup_qp failure", + "rdma_accept failure", "active setup_qp failure", "rdma_connect failure", + "resolve_route failure", "detected rdma_cm_id mismatch", "ROUTE_ERROR event", + "ADDR_ERROR event", "CONNECT_ERROR or UNREACHABLE or DEVICE_REMOVE event", + "CONSUMER_DEFINED reject", "REJECTED event", "ADDR_CHANGE event", + "DISCONNECTED event", "TIMEWAIT_EXIT event", "post_recv failure", + "send_ack failure", "no header in incoming msg", "corrupted header in incoming msg", + "fragment header mismatch", "recv completion error", "send completion error", + "post_send failure", "rds_rdma module unload", "active bonding failover", + "corresponding loopback conn drop", "active bonding failback", "sk_state to TCP_CLOSE", + "tcp_send failure" +] + + +class RdsInfo: + """Class to implement standard RDS info operations.""" + + USAGE_MSG = ( + "Usage: python rds_info.python