diff options
Diffstat (limited to '')
-rw-r--r-- | src/go/plugin/go.d/modules/dnsmasq_dhcp/collect.go | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/src/go/plugin/go.d/modules/dnsmasq_dhcp/collect.go b/src/go/plugin/go.d/modules/dnsmasq_dhcp/collect.go new file mode 100644 index 000000000..6de2fa215 --- /dev/null +++ b/src/go/plugin/go.d/modules/dnsmasq_dhcp/collect.go @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package dnsmasq_dhcp + +import ( + "bufio" + "io" + "math" + "math/big" + "net" + "os" + "strings" + "time" + + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/iprange" +) + +func (d *DnsmasqDHCP) collect() (map[string]int64, error) { + now := time.Now() + var updated bool + + if now.Sub(d.parseConfigTime) > d.parseConfigEvery { + d.parseConfigTime = now + + dhcpRanges, dhcpHosts := d.parseDnsmasqDHCPConfiguration() + d.dhcpRanges, d.dhcpHosts = dhcpRanges, dhcpHosts + updated = d.updateCharts() + + d.collectV4V6Stats() + } + + f, err := os.Open(d.LeasesPath) + if err != nil { + return nil, err + } + defer func() { _ = f.Close() }() + + if !updated { + fi, err := f.Stat() + if err != nil { + return nil, err + } + + if d.leasesModTime.Equal(fi.ModTime()) { + d.Debug("lease database file modification time has not changed, old data is returned") + return d.mx, nil + } + + d.Debug("leases db file modification time has changed, reading it") + d.leasesModTime = fi.ModTime() + } + + leases := findLeases(f) + d.collectRangesStats(leases) + + return d.mx, nil +} + +func (d *DnsmasqDHCP) collectV4V6Stats() { + d.mx["ipv4_dhcp_ranges"], d.mx["ipv6_dhcp_ranges"] = 0, 0 + for _, r := range d.dhcpRanges { + if r.Family() == iprange.V6Family { + d.mx["ipv6_dhcp_ranges"]++ + } else { + d.mx["ipv4_dhcp_ranges"]++ + } + } + + d.mx["ipv4_dhcp_hosts"], d.mx["ipv6_dhcp_hosts"] = 0, 0 + for _, ip := range d.dhcpHosts { + if ip.To4() == nil { + d.mx["ipv6_dhcp_hosts"]++ + } else { + d.mx["ipv4_dhcp_hosts"]++ + } + } +} + +func (d *DnsmasqDHCP) collectRangesStats(leases []net.IP) { + for _, r := range d.dhcpRanges { + d.mx["dhcp_range_"+r.String()+"_allocated_leases"] = 0 + d.mx["dhcp_range_"+r.String()+"_utilization"] = 0 + } + + for _, ip := range leases { + for _, r := range d.dhcpRanges { + if r.Contains(ip) { + d.mx["dhcp_range_"+r.String()+"_allocated_leases"]++ + break + } + } + } + + for _, ip := range d.dhcpHosts { + for _, r := range d.dhcpRanges { + if r.Contains(ip) { + d.mx["dhcp_range_"+r.String()+"_allocated_leases"]++ + break + } + } + } + + for _, r := range d.dhcpRanges { + name := "dhcp_range_" + r.String() + "_allocated_leases" + numOfIps, ok := d.mx[name] + if !ok { + d.mx[name] = 0 + } + d.mx["dhcp_range_"+r.String()+"_utilization"] = int64(math.Round(calcPercent(numOfIps, r.Size()))) + } +} + +func (d *DnsmasqDHCP) updateCharts() bool { + var updated bool + seen := make(map[string]bool) + for _, r := range d.dhcpRanges { + seen[r.String()] = true + if !d.cacheDHCPRanges[r.String()] { + d.cacheDHCPRanges[r.String()] = true + d.addDHCPRangeCharts(r.String()) + updated = true + } + } + + for v := range d.cacheDHCPRanges { + if !seen[v] { + delete(d.cacheDHCPRanges, v) + d.removeDHCPRangeCharts(v) + updated = true + } + } + return updated +} + +func findLeases(r io.Reader) []net.IP { + /* + 1560300536 08:00:27:61:3c:ee 2.2.2.3 debian8 * + duid 00:01:00:01:24:90:cf:5b:08:00:27:61:2e:2c + 1560300414 660684014 1234::20b * 00:01:00:01:24:90:cf:a3:08:00:27:61:3c:ee + */ + var ips []net.IP + s := bufio.NewScanner(r) + + for s.Scan() { + parts := strings.Fields(s.Text()) + if len(parts) != 5 { + continue + } + + ip := net.ParseIP(parts[2]) + if ip == nil { + continue + } + ips = append(ips, ip) + } + + return ips +} + +func calcPercent(ips int64, hosts *big.Int) float64 { + h := hosts.Int64() + if ips == 0 || h == 0 || !hosts.IsInt64() { + return 0 + } + return float64(ips) * 100 / float64(h) +} |