Skip to content
This repository has been archived by the owner on Mar 27, 2024. It is now read-only.

Commit

Permalink
feat(ping): add 'interface' option (#1179)
Browse files Browse the repository at this point in the history
  • Loading branch information
ilyam8 authored May 15, 2023
1 parent 850260d commit 0532693
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 0 deletions.
6 changes: 6 additions & 0 deletions config/go.d/ping.conf
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@
# Syntax:
# interval: 100ms
#
# - interface
# Network interface name.
# If set, ping will attempt to use the interface's IP address as the source of ICMP packets.
# Syntax:
# interface: eth0
#
#
# [ JOB defaults ]:
# privileged: yes
Expand Down
1 change: 1 addition & 0 deletions modules/ping/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func (p *Ping) initProber() (prober, error) {
conf := pingProberConfig{
privileged: p.Privileged,
packets: p.SendPackets,
iface: p.Interface,
interval: p.Interval.Duration,
deadline: deadline,
}
Expand Down
1 change: 1 addition & 0 deletions modules/ping/ping.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type (
Privileged bool `yaml:"privileged"`
SendPackets int `yaml:"packets"`
Interval web.Duration `yaml:"interval"`
Interface string `yaml:"interface"`
}
)

Expand Down
43 changes: 43 additions & 0 deletions modules/ping/prober.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
package ping

import (
"errors"
"fmt"
"net"
"time"

"github.com/netdata/go.d.plugin/logger"
Expand All @@ -12,9 +14,20 @@ import (
)

func newPingProber(conf pingProberConfig, log *logger.Logger) prober {
var source string
if conf.iface != "" {
if addr, err := getInterfaceIPAddress(conf.iface); err != nil {
log.Warningf("error getting interface '%s' IP address: %v", conf.iface, err)
} else {
log.Infof("interface '%s' IP address '%s', will use it as the source", conf.iface, addr)
source = addr
}
}

return &pingProber{
privileged: conf.privileged,
packets: conf.packets,
source: source,
interval: conf.interval,
deadline: conf.deadline,
Logger: log,
Expand All @@ -24,13 +37,15 @@ func newPingProber(conf pingProberConfig, log *logger.Logger) prober {
type pingProberConfig struct {
privileged bool
packets int
iface string
interval time.Duration
deadline time.Duration
}

type pingProber struct {
privileged bool
packets int
source string
interval time.Duration
deadline time.Duration
*logger.Logger
Expand All @@ -43,6 +58,7 @@ func (p *pingProber) ping(host string) (*probing.Statistics, error) {
return nil, fmt.Errorf("DNS lookup '%s' : %v", host, err)
}

pr.Source = p.source
pr.RecordRtts = false
pr.Interval = p.interval
pr.Count = p.packets
Expand All @@ -60,3 +76,30 @@ func (p *pingProber) ping(host string) (*probing.Statistics, error) {

return stats, nil
}

func getInterfaceIPAddress(ifaceName string) (ipaddr string, err error) {
iface, err := net.InterfaceByName(ifaceName)
if err != nil {
return "", err
}

addresses, err := iface.Addrs()
if err != nil {
return "", err
}

// FIXME: add IPv6 support
var v4Addr string
for _, addr := range addresses {
if ipnet, ok := addr.(*net.IPNet); ok && ipnet.IP.To4() != nil {
v4Addr = ipnet.IP.To4().String()
break
}
}

if v4Addr == "" {
return "", errors.New("ipv4 addresses not found")
}

return v4Addr, nil
}

0 comments on commit 0532693

Please sign in to comment.