From ad2b39d4b95e32e1eb5110b42c6cc9c72f6fd4ee Mon Sep 17 00:00:00 2001 From: Knut Ahlers Date: Sat, 6 Mar 2021 17:42:38 +0100 Subject: [PATCH] Add source interface selection Signed-off-by: Knut Ahlers --- main.go | 3 ++- spark.go | 35 +++++++++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/main.go b/main.go index 692eeb0..cca0edd 100644 --- a/main.go +++ b/main.go @@ -18,6 +18,7 @@ var ( InfluxHost string `flag:"influx-host" default:"http://localhost:8086" description:"Host with protocol of the InfluxDB"` InfluxPass string `flag:"influx-pass" default:"" description:"Password for the InfluxDB user"` InfluxUser string `flag:"influx-user" default:"" description:"Username for the InfluxDB connection"` + Interface string `flag:"interface" default:"" description:"Bind to interface for testing a specific interface throughput"` Interval time.Duration `flag:"interval" default:"15m" description:"Interval to execute test in"` LogLevel string `flag:"log-level" default:"info" description:"Set log level (debug, info, warning, error)"` OneShot bool `flag:"oneshot,1" default:"false" description:"Execute one measurement and exit (for cron execution)"` @@ -183,7 +184,7 @@ func writeTSV(t *testResult) error { func execTest() (*testResult, error) { t := newTestResult() - sc := newSparkClient(cfg.Server, cfg.Port) + sc := newSparkClient(cfg.Server, cfg.Port, cfg.Interface) if err := sc.ExecutePingTest(t); err != nil { return nil, errors.Wrap(err, "Ping-test failed") } diff --git a/spark.go b/spark.go index 5192853..e63b7bd 100644 --- a/spark.go +++ b/spark.go @@ -61,19 +61,42 @@ func (t testResult) String() string { } type sparkClient struct { - remote string - conn net.Conn - reader *bufio.Reader + bindInterfaceName string + remote string + conn net.Conn + reader *bufio.Reader } -func newSparkClient(hostname string, port int) *sparkClient { +func newSparkClient(hostname string, port int, bindInterfaceName string) *sparkClient { return &sparkClient{ - remote: fmt.Sprintf("%s:%d", hostname, port), + bindInterfaceName: bindInterfaceName, + remote: fmt.Sprintf("%s:%d", hostname, port), } } func (s *sparkClient) dial() error { - c, err := net.Dial("tcp", s.remote) + d := net.Dialer{} + + if s.bindInterfaceName != "" { + iface, err := net.InterfaceByName(s.bindInterfaceName) + if err != nil { + return errors.Wrap(err, "select interface") + } + + addrs, err := iface.Addrs() + if err != nil { + return errors.Wrap(err, "get interface IPs") + } + + if len(addrs) == 0 { + return errors.New("no addresses found on interface") + } + + d.LocalAddr = &net.TCPAddr{IP: addrs[0].(*net.IPNet).IP} + log.WithField("ip", d.LocalAddr).Warn("Set local address") + } + + c, err := d.Dial("tcp", s.remote) if err != nil { return errors.Wrap(err, "Unable to dial") }