mirror of
git://f0xx.org/android_cast
synced 2026-07-29 05:37:52 +03:00
Net topology: sirene (P2P), spider (MCU), spider net (SFU), pautina (net, mesh), hydra (hybrid), code names
287 lines
9.8 KiB
Bash
287 lines
9.8 KiB
Bash
# wan-deep-diag.sh — parseable deep diagnostics (sourced by wan-snapshot.sh).
|
|
# Not meant to be executed directly.
|
|
#
|
|
# Emits kind=deep lines to WAN_WATCH_LOG (key=value, one fact per line).
|
|
|
|
wan_deep_load_1m() {
|
|
awk '{print $1}' /proc/loadavg 2>/dev/null || echo "n/a"
|
|
}
|
|
|
|
wan_deep_cpu_busy_pct() {
|
|
awk '/^cpu / {
|
|
idle = $5 + $6; total = 0
|
|
for (i = 2; i <= NF; i++) total += $i
|
|
if (total > 0) printf "%.0f", 100 * (total - idle) / total
|
|
}' /proc/stat 2>/dev/null || echo "n/a"
|
|
}
|
|
|
|
wan_deep_mem_avail_kb() {
|
|
awk '/^MemAvailable:/ { print $2 }' /proc/meminfo 2>/dev/null || echo "n/a"
|
|
}
|
|
|
|
wan_deep_conntrack_fields() {
|
|
_cur="$(cat /proc/sys/net/netfilter/nf_conntrack_count 2>/dev/null)" || _cur=""
|
|
_max="$(cat /proc/sys/net/netfilter/nf_conntrack_max 2>/dev/null)" || _max=""
|
|
if [ -n "$_cur" ] && [ -n "$_max" ] && [ "$_max" -gt 0 ] 2>/dev/null; then
|
|
_pct=$((_cur * 100 / _max))
|
|
printf 'conntrack_cur=%s conntrack_max=%s conntrack_pct=%s' "$_cur" "$_max" "$_pct"
|
|
else
|
|
printf 'conntrack_cur=n/a conntrack_max=n/a conntrack_pct=n/a'
|
|
fi
|
|
}
|
|
|
|
wan_deep_emit() {
|
|
# wan_deep_emit KIND TS ROLE HOST [key=value ...]
|
|
_kind="$1"
|
|
_ts="$2"
|
|
_role="$3"
|
|
_host="$4"
|
|
shift 4
|
|
_line="kind=$_kind ts=$_ts role=$_role host=$_host $*"
|
|
_dir="$(dirname "$WAN_WATCH_LOG")"
|
|
[ -d "$_dir" ] || mkdir -p "$_dir" 2>/dev/null || true
|
|
printf '%s\n' "$_line" >> "$WAN_WATCH_LOG"
|
|
}
|
|
|
|
# Burst ping (fast) -> one kind=deep line.
|
|
wan_deep_burst_ping() {
|
|
_parent_ts="$1"
|
|
_role="$2"
|
|
_hostn="$3"
|
|
_label="$4"
|
|
_target="$5"
|
|
_count="${6:-5}"
|
|
_deadline="${7:-6}"
|
|
|
|
_out="$(ping -c "$_count" -w "$_deadline" "$_target" 2>/dev/null)" || _out=""
|
|
if [ -z "$_out" ]; then
|
|
wan_deep_emit deep "$_parent_ts" "$_role" "$_hostn" \
|
|
"parent_ts=$_parent_ts section=burst label=$_label target=$_target loss=-1 avg_ms=-1"
|
|
return 0
|
|
fi
|
|
|
|
_loss="$(printf '%s\n' "$_out" | awk '/packet loss/ {
|
|
for (i = 1; i <= NF; i++) if ($i ~ /%$/) { gsub(/%/, "", $i); print $i; exit }
|
|
}')"
|
|
_rtt="$(printf '%s\n' "$_out" | sed -n 's/.*= \([0-9.]*\)\/\([0-9.]*\)\/\([0-9.]*\)\/\([0-9.]*\) ms.*/\1 \2 \3 \4/p' | head -1)"
|
|
_min="-1" _avg="-1" _max="-1" _mdev="-1"
|
|
if [ -n "$_rtt" ]; then
|
|
_min="${_rtt%% *}"
|
|
_rest="${_rtt#* }"
|
|
_avg="${_rest%% *}"
|
|
_rest="${_rest#* }"
|
|
_max="${_rest%% *}"
|
|
_mdev="${_rest#* }"
|
|
fi
|
|
[ -n "$_loss" ] || _loss="-1"
|
|
|
|
wan_deep_emit deep "$_parent_ts" "$_role" "$_hostn" \
|
|
"parent_ts=$_parent_ts section=burst label=$_label target=$_target loss=${_loss}% min_ms=$_min avg_ms=$_avg max_ms=$_max mdev_ms=$_mdev"
|
|
}
|
|
|
|
wan_deep_host_health() {
|
|
_parent_ts="$1"
|
|
_role="$2"
|
|
_hostn="$3"
|
|
_ct="$(wan_deep_conntrack_fields)"
|
|
wan_deep_emit deep "$_parent_ts" "$_role" "$_hostn" \
|
|
"parent_ts=$_parent_ts section=host load1=$(wan_deep_load_1m) cpu_busy=$(wan_deep_cpu_busy_pct)% mem_avail_kb=$(wan_deep_mem_avail_kb) $_ct"
|
|
}
|
|
|
|
wan_deep_top_procs() {
|
|
_parent_ts="$1"
|
|
_role="$2"
|
|
_hostn="$3"
|
|
_n="${4:-5}"
|
|
ps -eo pcpu=,pmem=,comm= --sort=-pcpu 2>/dev/null | head -n "$_n" | awk -v ts="$_parent_ts" -v role="$_role" -v host="$_hostn" -v n="$_n" '
|
|
NF >= 3 {
|
|
rank = NR
|
|
printf "kind=deep ts=%s role=%s host=%s parent_ts=%s section=proc rank=%d cpu=%s mem=%s comm=%s\n",
|
|
ts, role, host, ts, rank, $1, $2, $3
|
|
}
|
|
' >> "$WAN_WATCH_LOG" 2>/dev/null || true
|
|
}
|
|
|
|
wan_deep_iface_stats() {
|
|
_parent_ts="$1"
|
|
_role="$2"
|
|
_hostn="$3"
|
|
_dev="$4"
|
|
[ -n "$_dev" ] || return 0
|
|
ip -s link show "$_dev" 2>/dev/null | awk -v ts="$_parent_ts" -v role="$_role" -v host="$_hostn" -v dev="$_dev" '
|
|
/^[0-9]+:/ { rx_b = tx_b = rx_p = tx_p = rx_drop = tx_drop = rx_err = tx_err = 0 }
|
|
/RX: bytes/ { rx_b = $3; rx_p = $2 }
|
|
/RX:.*packets/ { getline; rx_err = $3; rx_drop = $4 }
|
|
/TX: bytes/ { tx_b = $3; tx_p = $2 }
|
|
/TX:.*packets/ { getline; tx_err = $3; tx_drop = $4 }
|
|
END {
|
|
printf "kind=deep ts=%s role=%s host=%s parent_ts=%s section=iface dev=%s rx_bytes=%s tx_bytes=%s rx_drop=%s tx_drop=%s rx_err=%s tx_err=%s\n",
|
|
ts, role, host, ts, dev, rx_b, tx_b, rx_drop, tx_drop, rx_err, tx_err
|
|
}
|
|
' >> "$WAN_WATCH_LOG" 2>/dev/null || true
|
|
}
|
|
|
|
wan_deep_all_ifaces_nonzero() {
|
|
_parent_ts="$1"
|
|
_role="$2"
|
|
_hostn="$3"
|
|
ip -s link 2>/dev/null | awk -v ts="$_parent_ts" -v role="$_role" -v host="$_hostn" '
|
|
/^[0-9]+:/ {
|
|
if (iface != "" && iface !~ /^lo$/ && (rx_drop + tx_drop + rx_err + tx_err) > 0)
|
|
printf "kind=deep ts=%s role=%s host=%s parent_ts=%s section=iface dev=%s rx_drop=%s tx_drop=%s rx_err=%s tx_err=%s\n",
|
|
ts, role, host, ts, iface, rx_drop, tx_drop, rx_err, tx_err
|
|
iface = $2; gsub(":", "", iface)
|
|
rx_drop = tx_drop = rx_err = tx_err = 0
|
|
}
|
|
/RX:/ { getline; rx_err = $3; rx_drop = $4 }
|
|
/TX:/ { getline; tx_err = $3; tx_drop = $4 }
|
|
END {
|
|
if (iface != "" && iface !~ /^lo$/ && (rx_drop + tx_drop + rx_err + tx_err) > 0)
|
|
printf "kind=deep ts=%s role=%s host=%s parent_ts=%s section=iface dev=%s rx_drop=%s tx_drop=%s rx_err=%s tx_err=%s\n",
|
|
ts, role, host, ts, iface, rx_drop, tx_drop, rx_err, tx_err
|
|
}
|
|
' >> "$WAN_WATCH_LOG" 2>/dev/null || true
|
|
}
|
|
|
|
wan_deep_softnet() {
|
|
_parent_ts="$1"
|
|
_role="$2"
|
|
_hostn="$3"
|
|
[ -r /proc/net/softnet_stat ] || return 0
|
|
awk -v ts="$_parent_ts" -v role="$_role" -v host="$_hostn" '
|
|
$2 + 0 > 0 {
|
|
printf "kind=deep ts=%s role=%s host=%s parent_ts=%s section=softnet cpu=%d dropped=%s processed=%s\n",
|
|
ts, role, host, ts, NR - 1, $2, $1
|
|
}
|
|
' /proc/net/softnet_stat >> "$WAN_WATCH_LOG" 2>/dev/null || true
|
|
}
|
|
|
|
wan_deep_neigh() {
|
|
_parent_ts="$1"
|
|
_role="$2"
|
|
_hostn="$3"
|
|
_ip="$4"
|
|
[ -n "$_ip" ] || return 0
|
|
ip neigh show "$_ip" 2>/dev/null | awk -v ts="$_parent_ts" -v role="$_role" -v host="$_hostn" -v ip="$_ip" '
|
|
NF >= 5 {
|
|
printf "kind=deep ts=%s role=%s host=%s parent_ts=%s section=neigh ip=%s lladdr=%s dev=%s state=%s\n",
|
|
ts, role, host, ts, ip, $5, $3, $6
|
|
}
|
|
' >> "$WAN_WATCH_LOG" 2>/dev/null || true
|
|
}
|
|
|
|
wan_deep_route() {
|
|
_parent_ts="$1"
|
|
_role="$2"
|
|
_hostn="$3"
|
|
_label="$4"
|
|
_target="$5"
|
|
[ -n "$_target" ] || return 0
|
|
ip route get "$_target" 2>/dev/null | awk -v ts="$_parent_ts" -v role="$_role" -v host="$_hostn" -v label="$_label" -v target="$_target" '
|
|
{
|
|
dev = via = ""; src = ""
|
|
for (i = 1; i <= NF; i++) {
|
|
if ($i == "dev") dev = $(i + 1)
|
|
if ($i == "via") via = $(i + 1)
|
|
if ($i == "src") src = $(i + 1)
|
|
}
|
|
printf "kind=deep ts=%s role=%s host=%s parent_ts=%s section=route label=%s target=%s dev=%s via=%s src=%s\n",
|
|
ts, role, host, ts, label, target, dev, via, src
|
|
}
|
|
' >> "$WAN_WATCH_LOG" 2>/dev/null || true
|
|
}
|
|
|
|
wan_deep_iptables_hot() {
|
|
_parent_ts="$1"
|
|
_role="$2"
|
|
_hostn="$3"
|
|
command -v iptables >/dev/null 2>&1 || return 0
|
|
for _spec in "filter:FORWARD" "nat:PREROUTING" "nat:POSTROUTING"; do
|
|
_tbl="${_spec%%:*}"
|
|
_chain="${_spec#*:}"
|
|
iptables -t "$_tbl" -L "$_chain" -n -v --line-numbers 2>/dev/null \
|
|
| awk -v ts="$_parent_ts" -v role="$_role" -v host="$_hostn" -v tbl="$_tbl" -v chain="$_chain" '
|
|
/^[0-9]+/ && $2 + 0 > 0 {
|
|
ln = $1; pkts = $2; bytes = $3; target = $4
|
|
printf "kind=deep ts=%s role=%s host=%s parent_ts=%s section=iptables tbl=%s chain=%s line=%s pkts=%s bytes=%s target=%s\n",
|
|
ts, role, host, ts, tbl, chain, ln, pkts, bytes, target
|
|
}
|
|
' | head -n 8 >> "$WAN_WATCH_LOG" 2>/dev/null || true
|
|
done
|
|
}
|
|
|
|
wan_deep_qdisc() {
|
|
_parent_ts="$1"
|
|
_role="$2"
|
|
_hostn="$3"
|
|
_dev="$4"
|
|
[ -n "$_dev" ] || return 0
|
|
tc -s qdisc show dev "$_dev" 2>/dev/null | awk -v ts="$_parent_ts" -v role="$_role" -v host="$_hostn" -v dev="$_dev" '
|
|
/qdisc/ {
|
|
printf "kind=deep ts=%s role=%s host=%s parent_ts=%s section=qdisc dev=%s detail=%s\n",
|
|
ts, role, host, ts, dev, $0
|
|
}
|
|
/backlog/ {
|
|
printf "kind=deep ts=%s role=%s host=%s parent_ts=%s section=qdisc dev=%s backlog=%s\n",
|
|
ts, role, host, ts, dev, $0
|
|
}
|
|
' >> "$WAN_WATCH_LOG" 2>/dev/null || true
|
|
}
|
|
|
|
wan_deep_ss_summary() {
|
|
_parent_ts="$1"
|
|
_role="$2"
|
|
_hostn="$3"
|
|
ss -s 2>/dev/null | awk -v ts="$_parent_ts" -v role="$_role" -v host="$_hostn" '
|
|
/TCP:|UDP:/ {
|
|
gsub(/^[ \t]+/, "")
|
|
printf "kind=deep ts=%s role=%s host=%s parent_ts=%s section=ss %s\n", ts, role, host, ts, $0
|
|
}
|
|
' >> "$WAN_WATCH_LOG" 2>/dev/null || true
|
|
}
|
|
|
|
# Full deep capture for one anomaly event.
|
|
wan_deep_diag_run() {
|
|
_parent_ts="$1"
|
|
_role="$2"
|
|
_hostn="$3"
|
|
_triggers="$4"
|
|
_wan_target="$5"
|
|
_fe_target="$6"
|
|
_gw_target="$7"
|
|
_route_wan_dev="$8"
|
|
_route_fe_dev="$9"
|
|
|
|
wan_deep_emit alert "$_parent_ts" "$_role" "$_hostn" \
|
|
"parent_ts=$_parent_ts triggers=\"$_triggers\""
|
|
|
|
wan_deep_host_health "$_parent_ts" "$_role" "$_hostn"
|
|
wan_deep_burst_ping "$_parent_ts" "$_role" "$_hostn" "wan" "$_wan_target"
|
|
wan_deep_burst_ping "$_parent_ts" "$_role" "$_hostn" "fe" "$_fe_target"
|
|
if [ -n "$_gw_target" ] && [ "$_gw_target" != "none" ]; then
|
|
wan_deep_burst_ping "$_parent_ts" "$_role" "$_hostn" "gw" "$_gw_target"
|
|
fi
|
|
|
|
wan_deep_route "$_parent_ts" "$_role" "$_hostn" "wan" "$_wan_target"
|
|
wan_deep_route "$_parent_ts" "$_role" "$_hostn" "fe" "$_fe_target"
|
|
wan_deep_neigh "$_parent_ts" "$_role" "$_hostn" "$_fe_target"
|
|
wan_deep_top_procs "$_parent_ts" "$_role" "$_hostn" 5
|
|
wan_deep_softnet "$_parent_ts" "$_role" "$_hostn"
|
|
wan_deep_ss_summary "$_parent_ts" "$_role" "$_hostn"
|
|
|
|
wan_deep_iface_stats "$_parent_ts" "$_role" "$_hostn" "$_route_wan_dev"
|
|
wan_deep_iface_stats "$_parent_ts" "$_role" "$_hostn" "$_route_fe_dev"
|
|
wan_deep_all_ifaces_nonzero "$_parent_ts" "$_role" "$_hostn"
|
|
|
|
if [ "$_role" = "router" ]; then
|
|
wan_deep_iptables_hot "$_parent_ts" "$_role" "$_hostn"
|
|
wan_deep_qdisc "$_parent_ts" "$_role" "$_hostn" "$_route_wan_dev"
|
|
fi
|
|
|
|
if [ "$_role" = "pi" ]; then
|
|
wan_deep_qdisc "$_parent_ts" "$_role" "$_hostn" "$_route_fe_dev"
|
|
fi
|
|
}
|
|
|
|
# Loaded marker for wan-snapshot.sh
|
|
WAN_DEEP_DIAG_LOADED=1 |