From a4cc1de1cca60bd5090ad46b386bc9746a9ab220 Mon Sep 17 00:00:00 2001 From: Konstantin Kuklin Date: Fri, 18 Oct 2024 00:34:20 +0300 Subject: [PATCH 1/2] add netfilter queue support Signed-off-by: Konstantin Kuklin --- nfnetlink_queue.go | 85 +++++++++++++++++++++++++++++++++++++++++ nfnetlink_queue_test.go | 75 ++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 nfnetlink_queue.go create mode 100644 nfnetlink_queue_test.go diff --git a/nfnetlink_queue.go b/nfnetlink_queue.go new file mode 100644 index 00000000..da23e6e8 --- /dev/null +++ b/nfnetlink_queue.go @@ -0,0 +1,85 @@ +// Copyright 2019 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "bytes" + "fmt" + + "github.com/prometheus/procfs/internal/util" +) + +const nfNetLinkQueueFormat = "%d %d %d %d %d %d %d %d %d" + +// NFNetLinkQueue contains general information about netfilter queues found in /proc/net/netfilter/nfnetlink_queue. +type NFNetLinkQueue struct { + // id of the queue + QueueID uint + // pid of process handling the queue + PeerPID uint + // number of packets waiting for a decision + QueueTotal uint + // indicate how userspace receive packets + CopyMode uint + // size of copy + CopyRange uint + // number of items dropped by the kernel because too many packets were waiting a decision. + // It queue_total is superior to queue_max_len (1024 per default) the packets are dropped. + QueueDropped uint + // number of packets dropped by userspace (due to kernel send failure on the netlink socket) + QueueUserDropped uint + // sequence number of packets queued. It gives a correct approximation of the number of queued packets. + SequenceID uint + // internal value (number of entity using the queue) + Use uint +} + +// NFNetLinkQueue returns information about current state of netfilter queues. +func (fs FS) NFNetLinkQueue() ([]NFNetLinkQueue, error) { + data, err := util.ReadFileNoStat(fs.proc.Path("net/netfilter/nfnetlink_queue")) + if err != nil { + return nil, err + } + + queue := []NFNetLinkQueue{} + if len(data) == 0 { + return queue, nil + } + + scanner := bufio.NewScanner(bytes.NewReader(data)) + for scanner.Scan() { + line := scanner.Text() + nFNetLinkQueue, err := parseNFNetLinkQueueLine(line) + if err != nil { + return nil, err + } + queue = append(queue, *nFNetLinkQueue) + } + return queue, nil +} + +// parseNFNetLinkQueueLine parses each line of the /proc/net/netfilter/nfnetlink_queue file. +func parseNFNetLinkQueueLine(line string) (*NFNetLinkQueue, error) { + nFNetLinkQueue := NFNetLinkQueue{} + _, err := fmt.Sscanf( + line, nfNetLinkQueueFormat, + &nFNetLinkQueue.QueueID, &nFNetLinkQueue.PeerPID, &nFNetLinkQueue.QueueTotal, &nFNetLinkQueue.CopyMode, + &nFNetLinkQueue.CopyRange, &nFNetLinkQueue.QueueDropped, &nFNetLinkQueue.QueueUserDropped, &nFNetLinkQueue.SequenceID, &nFNetLinkQueue.Use, + ) + if err != nil { + return nil, err + } + return &nFNetLinkQueue, nil +} diff --git a/nfnetlink_queue_test.go b/nfnetlink_queue_test.go new file mode 100644 index 00000000..c5ef81f4 --- /dev/null +++ b/nfnetlink_queue_test.go @@ -0,0 +1,75 @@ +// Copyright 2020 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "reflect" + "testing" +) + +func TestParseNFNetLinkQueueLine(t *testing.T) { + tests := []struct { + name string + s string + shouldErr bool + nfNetLinkQueue *NFNetLinkQueue + }{ + { + name: "nf_net_link_queue simple line", + s: " 230 44306 1 2 65531 3 4 5 6", + shouldErr: false, + nfNetLinkQueue: &NFNetLinkQueue{ + QueueID: 230, + PeerPID: 44306, + QueueTotal: 1, + CopyMode: 2, + CopyRange: 65531, + QueueDropped: 3, + QueueUserDropped: 4, + SequenceID: 5, + Use: 6, + }, + }, + { + name: "empty line", + s: "", + shouldErr: true, + nfNetLinkQueue: nil, + }, + { + name: "incorrect parameters count in line", + s: " 1 2 3 4 55555 ", + shouldErr: true, + nfNetLinkQueue: nil, + }, + } + + for i, test := range tests { + t.Logf("[%02d] test %q", i, test.name) + + nfNetLinkQueue, err := parseNFNetLinkQueueLine(test.s) + + if test.shouldErr && err == nil { + t.Errorf("%s: expected an error, but none occurred", test.name) + } + if !test.shouldErr && err != nil { + t.Errorf("%s: unexpected error: %v", test.name, err) + } + + if want, have := test.nfNetLinkQueue, nfNetLinkQueue; !reflect.DeepEqual(want, have) { + t.Errorf("nfNetLinkQueue:\nwant:\n%+v\nhave:\n%+v", want, have) + } + } + +} From 3dbfe37d0324e4a452dcfab055c6a3df2285206e Mon Sep 17 00:00:00 2001 From: Konstantin Kuklin Date: Thu, 19 Dec 2024 23:22:21 +0300 Subject: [PATCH 2/2] fixed copyright year Signed-off-by: Konstantin Kuklin --- nfnetlink_queue.go | 2 +- nfnetlink_queue_test.go | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/nfnetlink_queue.go b/nfnetlink_queue.go index da23e6e8..7adf17bf 100644 --- a/nfnetlink_queue.go +++ b/nfnetlink_queue.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright 2024 The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/nfnetlink_queue_test.go b/nfnetlink_queue_test.go index c5ef81f4..baf8a10e 100644 --- a/nfnetlink_queue_test.go +++ b/nfnetlink_queue_test.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright 2024 The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -71,5 +71,4 @@ func TestParseNFNetLinkQueueLine(t *testing.T) { t.Errorf("nfNetLinkQueue:\nwant:\n%+v\nhave:\n%+v", want, have) } } - }