Summary
The zmq output counts its heartbeat records as forwarded packets. zmq_send_heartbeat_packet appends the heartbeat to the batch (pkts_num++) and flushes. zmq_flush_packet then adds the batch's pkts_num to fwd_packets and its full size, batch header included, to fwd_bytes. Each heartbeat is also counted in heartbeat_packets, so it is counted twice, and fwd_packets no longer counts mirrored packets.
Heartbeats are sent exactly when the link is idle, so an output that has captured nothing reports a steadily growing fwd_packets. This is what cpctl shows and what cpdaemon uploads to CPM as fwdPackets (models.go:257). Heartbeats sent in a failed batch end up in error_drop_packets in the same way.
Two smaller points in the same area:
- ZMQ-WIRE-FORMAT.md §8 says a failed send is "counted in
error_drop_batches / error_drop_packets". No error_drop_batches counter exists in output_stats_t or in the stats RPC; the batch count only appears in the periodic error log (nb_drop_batches).
- The stats RPC does return
heartbeat_packets (task.c:705), but cpctl stats leaves it out of counters, so a cpctl user cannot subtract the heartbeats.
Reproduction (0.9.x d302572)
Run cpworker with a libpcap capturer on lo using "bpf": "udp port 1", which matches nothing, and a zmq output with "heartbeat_ms": 1000. No receiver is needed. After about 15 s:
$ cpctl stats -u w.sock -f jsonl -n 1
cap_packets {'packets': 0}
fwd_packets {'packets': 14}
fwd_bytes {'bytes': 784} # 14 × (24-byte batch header + 32-byte heartbeat record)
Expected
fwd_packets counts mirrored packets only, so that fwd_packets ≤ cap_packets holds and agrees with the GRE/VXLAN outputs. Heartbeats are counted only in heartbeat_packets, which cpctl shows. ZMQ-WIRE-FORMAT.md §8 names counters that actually exist (or the counter is added).
中文原文
zmq 输出把心跳记录计为已转发的包:zmq_send_heartbeat_packet 把心跳加入批次(pkts_num++)并立即发送,zmq_flush_packet 再把整批的 pkts_num 计入 fwd_packets、整批大小(含批头)计入 fwd_bytes。心跳同时计入 heartbeat_packets,因此被计了两次,fwd_packets 也不再只是镜像包的数量。心跳恰恰在链路空闲时发送,所以一个包都没抓到的输出,fwd_packets 也会持续增长;cpctl 显示的、cpdaemon 作为 fwdPackets 上报 CPM 的都是这个值(models.go:257)。发送失败时,心跳同样会计入 error_drop_packets。另外两点:ZMQ-WIRE-FORMAT.md §8 写失败计入 error_drop_batches,但统计结构和 RPC 中都没有该计数器,批次数只出现在周期性错误日志里;RPC 返回了 heartbeat_packets,但 cpctl stats 不显示,用户无法扣除。复现:lo 上 bpf "udp port 1"(不匹配任何包)、zmq heartbeat_ms 1000,约 15 秒后 cap_packets 0、fwd_packets 14、fwd_bytes 784(14 × 56)。期望 fwd_packets 只统计镜像包(满足 fwd_packets ≤ cap_packets,与 GRE/VXLAN 一致),心跳只计入 heartbeat_packets 并由 cpctl 显示,§8 使用实际存在的计数器名(或补上该计数器)。
Summary
The zmq output counts its heartbeat records as forwarded packets.
zmq_send_heartbeat_packetappends the heartbeat to the batch (pkts_num++) and flushes.zmq_flush_packetthen adds the batch'spkts_numtofwd_packetsand its full size, batch header included, tofwd_bytes. Each heartbeat is also counted inheartbeat_packets, so it is counted twice, andfwd_packetsno longer counts mirrored packets.Heartbeats are sent exactly when the link is idle, so an output that has captured nothing reports a steadily growing
fwd_packets. This is what cpctl shows and what cpdaemon uploads to CPM asfwdPackets(models.go:257). Heartbeats sent in a failed batch end up inerror_drop_packetsin the same way.Two smaller points in the same area:
error_drop_batches/error_drop_packets". Noerror_drop_batchescounter exists inoutput_stats_tor in the stats RPC; the batch count only appears in the periodic error log (nb_drop_batches).heartbeat_packets(task.c:705), butcpctl statsleaves it out ofcounters, so a cpctl user cannot subtract the heartbeats.Reproduction (0.9.x d302572)
Run cpworker with a libpcap capturer on
lousing"bpf": "udp port 1", which matches nothing, and a zmq output with"heartbeat_ms": 1000. No receiver is needed. After about 15 s:Expected
fwd_packetscounts mirrored packets only, so thatfwd_packets ≤ cap_packetsholds and agrees with the GRE/VXLAN outputs. Heartbeats are counted only inheartbeat_packets, which cpctl shows. ZMQ-WIRE-FORMAT.md §8 names counters that actually exist (or the counter is added).中文原文
zmq 输出把心跳记录计为已转发的包:zmq_send_heartbeat_packet 把心跳加入批次(pkts_num++)并立即发送,zmq_flush_packet 再把整批的 pkts_num 计入 fwd_packets、整批大小(含批头)计入 fwd_bytes。心跳同时计入 heartbeat_packets,因此被计了两次,fwd_packets 也不再只是镜像包的数量。心跳恰恰在链路空闲时发送,所以一个包都没抓到的输出,fwd_packets 也会持续增长;cpctl 显示的、cpdaemon 作为 fwdPackets 上报 CPM 的都是这个值(models.go:257)。发送失败时,心跳同样会计入 error_drop_packets。另外两点:ZMQ-WIRE-FORMAT.md §8 写失败计入 error_drop_batches,但统计结构和 RPC 中都没有该计数器,批次数只出现在周期性错误日志里;RPC 返回了 heartbeat_packets,但 cpctl stats 不显示,用户无法扣除。复现:lo 上 bpf "udp port 1"(不匹配任何包)、zmq heartbeat_ms 1000,约 15 秒后 cap_packets 0、fwd_packets 14、fwd_bytes 784(14 × 56)。期望 fwd_packets 只统计镜像包(满足 fwd_packets ≤ cap_packets,与 GRE/VXLAN 一致),心跳只计入 heartbeat_packets 并由 cpctl 显示,§8 使用实际存在的计数器名(或补上该计数器)。