From 1d6add5af37db0062caca7b4efb195ab26e80219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=8F=81?= <1185280650@qq.com> Date: Thu, 15 Jun 2023 20:28:24 +0800 Subject: [PATCH] =?UTF-8?q?Add=20net/route=20parse,=20also=20add=20util=20?= =?UTF-8?q?lib=20Pars=E2=80=A6=20(#508)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * @Wentao[add-net-route]: added net/route parse, also add util lib ParseIpv4FromHexString function - sansna --------- Signed-off-by: sansna <1185280650@qq.com> Signed-off-by: 三叁 <1185280650@qq.com> Co-authored-by: Ben Kochie --- net_route.go | 143 ++++++++++++++++++++++++++++++++++++++++++++++ net_route_test.go | 60 +++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 net_route.go create mode 100644 net_route_test.go diff --git a/net_route.go b/net_route.go new file mode 100644 index 00000000..deb7029f --- /dev/null +++ b/net_route.go @@ -0,0 +1,143 @@ +// Copyright 2023 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" + "io" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +const ( + blackholeRepresentation string = "*" + blackholeIfaceName string = "blackhole" + routeLineColumns int = 11 +) + +// A NetRouteLine represents one line from net/route. +type NetRouteLine struct { + Iface string + Destination uint32 + Gateway uint32 + Flags uint32 + RefCnt uint32 + Use uint32 + Metric uint32 + Mask uint32 + MTU uint32 + Window uint32 + IRTT uint32 +} + +func (fs FS) NetRoute() ([]NetRouteLine, error) { + return readNetRoute(fs.proc.Path("net", "route")) +} + +func readNetRoute(path string) ([]NetRouteLine, error) { + b, err := util.ReadFileNoStat(path) + if err != nil { + return nil, err + } + + routelines, err := parseNetRoute(bytes.NewReader(b)) + if err != nil { + return nil, fmt.Errorf("failed to read net route from %s: %w", path, err) + } + return routelines, nil +} + +func parseNetRoute(r io.Reader) ([]NetRouteLine, error) { + var routelines []NetRouteLine + + scanner := bufio.NewScanner(r) + scanner.Scan() + for scanner.Scan() { + fields := strings.Fields(scanner.Text()) + routeline, err := parseNetRouteLine(fields) + if err != nil { + return nil, err + } + routelines = append(routelines, *routeline) + } + return routelines, nil +} + +func parseNetRouteLine(fields []string) (*NetRouteLine, error) { + if len(fields) != routeLineColumns { + return nil, fmt.Errorf("invalid routeline, num of digits: %d", len(fields)) + } + iface := fields[0] + if iface == blackholeRepresentation { + iface = blackholeIfaceName + } + destination, err := strconv.ParseUint(fields[1], 16, 32) + if err != nil { + return nil, err + } + gateway, err := strconv.ParseUint(fields[2], 16, 32) + if err != nil { + return nil, err + } + flags, err := strconv.ParseUint(fields[3], 10, 32) + if err != nil { + return nil, err + } + refcnt, err := strconv.ParseUint(fields[4], 10, 32) + if err != nil { + return nil, err + } + use, err := strconv.ParseUint(fields[5], 10, 32) + if err != nil { + return nil, err + } + metric, err := strconv.ParseUint(fields[6], 10, 32) + if err != nil { + return nil, err + } + mask, err := strconv.ParseUint(fields[7], 16, 32) + if err != nil { + return nil, err + } + mtu, err := strconv.ParseUint(fields[8], 10, 32) + if err != nil { + return nil, err + } + window, err := strconv.ParseUint(fields[9], 10, 32) + if err != nil { + return nil, err + } + irtt, err := strconv.ParseUint(fields[10], 10, 32) + if err != nil { + return nil, err + } + routeline := &NetRouteLine{ + Iface: iface, + Destination: uint32(destination), + Gateway: uint32(gateway), + Flags: uint32(flags), + RefCnt: uint32(refcnt), + Use: uint32(use), + Metric: uint32(metric), + Mask: uint32(mask), + MTU: uint32(mtu), + Window: uint32(window), + IRTT: uint32(irtt), + } + return routeline, nil +} diff --git a/net_route_test.go b/net_route_test.go new file mode 100644 index 00000000..0464036c --- /dev/null +++ b/net_route_test.go @@ -0,0 +1,60 @@ +// Copyright 2023 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 ( + "bytes" + "reflect" + "testing" +) + +func TestParseNetRoute(t *testing.T) { + var netRoute = []byte(`Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT +eno16780032 00000000 9503A8C0 0003 0 0 100 00000000 0 0 0 +eno16780032 0000A8C0 00000000 0001 0 0 100 0000FFFF 0 0 0`) + + r := bytes.NewReader(netRoute) + parsed, _ := parseNetRoute(r) + want := []NetRouteLine{ + { + Iface: "eno16780032", + Destination: 0, + Gateway: 2500044992, + Flags: 3, + RefCnt: 0, + Use: 0, + Metric: 100, + Mask: 0, + MTU: 0, + Window: 0, + IRTT: 0, + }, + { + Iface: "eno16780032", + Destination: 43200, + Gateway: 0, + Flags: 1, + RefCnt: 0, + Use: 0, + Metric: 100, + Mask: 65535, + MTU: 0, + Window: 0, + IRTT: 0, + }, + } + if !reflect.DeepEqual(want, parsed) { + t.Errorf("want %v, parsed %v", want, parsed) + } +}