diff --git a/collector/netdev_common.go b/collector/netdev_common.go index 089f1e5870..4d35b1e15b 100644 --- a/collector/netdev_common.go +++ b/collector/netdev_common.go @@ -11,9 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build !nonetdev && (linux || freebsd || openbsd || dragonfly || darwin) +//go:build !nonetdev && (linux || freebsd || netbsd || openbsd || dragonfly || darwin) // +build !nonetdev -// +build linux freebsd openbsd dragonfly darwin +// +build linux freebsd netbsd openbsd dragonfly darwin package collector diff --git a/collector/netdev_netbsd.go b/collector/netdev_netbsd.go new file mode 100644 index 0000000000..983c1f8503 --- /dev/null +++ b/collector/netdev_netbsd.go @@ -0,0 +1,91 @@ +// 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 +// +// 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. + +//go:build !nonetdev && netbsd +// +build !nonetdev,netbsd + +package collector + +import ( + "errors" + + "fmt" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "unsafe" +) + +/* +#include +#include +#include +#include +#include +#include +#include +*/ +import "C" + +func getNetDevStats(filter *deviceFilter, logger log.Logger) (netDevStats, error) { + netDev := netDevStats{} + + var ifap, ifa *C.struct_ifaddrs + if C.getifaddrs(&ifap) == -1 { + return nil, errors.New("getifaddrs() failed") + } + defer C.freeifaddrs(ifap) + + for ifa = ifap; ifa != nil; ifa = ifa.ifa_next { + if ifa.ifa_addr.sa_family != C.AF_LINK { + continue + } + + dev := C.GoString(ifa.ifa_name) + if filter.ignored(dev) { + level.Debug(logger).Log("msg", "Ignoring device", "device", dev) + continue + } + + data := (*C.struct_if_data)(ifa.ifa_data) + + // https://github.com/NetBSD/src/blob/trunk/sys/net/if.h#L180-L202 + netDev[dev] = map[string]uint64{ + "receive_packets": uint64(data.ifi_ipackets), + "transmit_packets": uint64(data.ifi_opackets), + "receive_bytes": uint64(data.ifi_ibytes), + "transmit_bytes": uint64(data.ifi_obytes), + "receive_errors": uint64(data.ifi_ierrors), + "transmit_errors": uint64(data.ifi_oerrors), + "receive_dropped": uint64(data.ifi_iqdrops), + "receive_multicast": uint64(data.ifi_imcasts), + "transmit_multicast": uint64(data.ifi_omcasts), + "collisions": uint64(data.ifi_collisions), + "noproto": uint64(data.ifi_noproto), + } + + /* + * transmit_dropped (ifi_oqdrops) is not available in + * struct if_data for backwards compatibility reasons, + * but can be read via sysctl. + */ + var ifi_oqdrops uint64 + var len C.size_t = C.size_t(unsafe.Sizeof(ifi_oqdrops)) + name := C.CString(fmt.Sprintf("net.interfaces.%s.sndq.drops", dev)) + defer C.free(unsafe.Pointer(name)) + if C.sysctlbyname(name, unsafe.Pointer(&ifi_oqdrops), (*C.size_t)(unsafe.Pointer(&len)), unsafe.Pointer(nil), 0) == 0 { + netDev[dev]["transmit_dropped"] = uint64(ifi_oqdrops) + } + } + + return netDev, nil +}