From 8eea50f160124463bfc7bbc6638891638d683e6e Mon Sep 17 00:00:00 2001 From: Dan Kortschak <90160302+efd6@users.noreply.github.com> Date: Sun, 12 Nov 2023 08:01:30 +1030 Subject: [PATCH] packetbeat/protos/tcp: add metrics for TCP header flags (#36975) --- CHANGELOG.next.asciidoc | 1 + .../docs/protocol-metrics-packetbeat.asciidoc | 10 ++++ packetbeat/protos/tcp/tcp.go | 52 +++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 9863ff6db2da..c3af98fe9fac 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -231,6 +231,7 @@ Setting environmental variable ELASTIC_NETINFO:false in Elastic Agent pod will d *Packetbeat* +- Add metrics for TCP flags. {issue}36992[36992] {pull}36975[36975] *Packetbeat* diff --git a/packetbeat/docs/protocol-metrics-packetbeat.asciidoc b/packetbeat/docs/protocol-metrics-packetbeat.asciidoc index 4d9014f3a7a7..d36cce38e445 100644 --- a/packetbeat/docs/protocol-metrics-packetbeat.asciidoc +++ b/packetbeat/docs/protocol-metrics-packetbeat.asciidoc @@ -33,6 +33,16 @@ observe the activity of Packetbeat for the monitored protocol. | `tcp.dropped_because_of_gaps` | Number of packets dropped because of gaps. | `arrival_period` | Histogram of the elapsed time between packet arrivals. | `processing_time` | Histogram of the elapsed time between packet receipt and publication. +| `fin_flags_total` | Number of TCP FIN (finish) flags observed. +| `syn_flags_total` | Number of TCP SYN (synchronization) flags observed. +| `rst_flags_total` | Number of TCP RST (reset) flags observed. +| `psh_flags_total` | Number of TCP PSH (push) flags observed. +| `ack_flags_total` | Number of TCP ACK (acknowledgement) flags observed. +| `urg_flags_total` | Number of TCP URG (urgent) flags observed. +| `ece_flags_total` | Number of TCP ECE (ECN echo) flags observed. +| `cwr_flags_total` | Number of TCP CWR (congestion window reduced) flags observed. +| `ns_flags_total` | Number of TCP NS (nonce sum) flags observed. +| `received_headers_total` | Number of headers observed, including unprocessed packets. |======= diff --git a/packetbeat/protos/tcp/tcp.go b/packetbeat/protos/tcp/tcp.go index 57a3c64c4812..1275c2a88110 100644 --- a/packetbeat/protos/tcp/tcp.go +++ b/packetbeat/protos/tcp/tcp.go @@ -100,6 +100,8 @@ func (tcp *TCP) removalListener(_ common.Key, value common.Value) { func (tcp *TCP) Process(id *flows.FlowID, tcphdr *layers.TCP, pkt *protos.Packet) { tcp.expiredConns.notifyAll() + tcp.metrics.logFlags(tcphdr) + stream, created := tcp.getStream(pkt) if stream.conn == nil { return @@ -392,6 +394,11 @@ type inputMetrics struct { lastPacket time.Time + // TCP flag counts. + fin, syn, rst, psh, ack, urg, ece, cwr, ns *monitoring.Uint + // Total number of headers, including zero length packets. + headers *monitoring.Uint + device *monitoring.String // name of the device being monitored packets *monitoring.Uint // number of packets processed bytes *monitoring.Uint // number of bytes processed @@ -418,6 +425,16 @@ func newInputMetrics(id, device string, ports map[uint16]protos.Protocol) *input packets: monitoring.NewUint(reg, "received_events_total"), bytes: monitoring.NewUint(reg, "received_bytes_total"), overlapped: monitoring.NewUint(reg, "tcp_overlaps"), + fin: monitoring.NewUint(reg, "fin_flags_total"), + syn: monitoring.NewUint(reg, "syn_flags_total"), + rst: monitoring.NewUint(reg, "rst_flags_total"), + psh: monitoring.NewUint(reg, "psh_flags_total"), + ack: monitoring.NewUint(reg, "ack_flags_total"), + urg: monitoring.NewUint(reg, "urg_flags_total"), + ece: monitoring.NewUint(reg, "ece_flags_total"), + cwr: monitoring.NewUint(reg, "cwr_flags_total"), + ns: monitoring.NewUint(reg, "ns_flags_total"), + headers: monitoring.NewUint(reg, "received_headers_total"), dropped: monitoring.NewInt(reg, "tcp.dropped_because_of_gaps"), // Name and type retained for compatibility. arrivalPeriod: metrics.NewUniformSample(1024), processingTime: metrics.NewUniformSample(1024), @@ -450,6 +467,41 @@ func portList(m map[uint16]protos.Protocol) string { return strings.Join(s, "-") } +// logFlags logs flag metric for the given packet header. +func (m *inputMetrics) logFlags(hdr *layers.TCP) { + if m == nil { + return + } + m.headers.Add(1) + if hdr.FIN { + m.fin.Add(1) + } + if hdr.SYN { + m.syn.Add(1) + } + if hdr.RST { + m.rst.Add(1) + } + if hdr.PSH { + m.psh.Add(1) + } + if hdr.ACK { + m.ack.Add(1) + } + if hdr.URG { + m.urg.Add(1) + } + if hdr.ECE { + m.ece.Add(1) + } + if hdr.CWR { + m.cwr.Add(1) + } + if hdr.NS { + m.ns.Add(1) + } +} + // log logs metric for the given packet. func (m *inputMetrics) log(pkt *protos.Packet) { if m == nil {