forked from cloudfoundry/bosh-agent
-
Notifications
You must be signed in to change notification settings - Fork 0
/
arping.go
93 lines (76 loc) · 2.33 KB
/
arping.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package arp
import (
"path"
"sync"
"time"
boship "github.com/cloudfoundry/bosh-agent/platform/net/ip"
boshlog "github.com/cloudfoundry/bosh-utils/logger"
boshsys "github.com/cloudfoundry/bosh-utils/system"
)
const arpingLogTag = "arping"
type arping struct {
cmdRunner boshsys.CmdRunner
fs boshsys.FileSystem
logger boshlog.Logger
iterations int
iterationDelay time.Duration
interfaceCheckDelay time.Duration
}
func NewArping(
cmdRunner boshsys.CmdRunner,
fs boshsys.FileSystem,
logger boshlog.Logger,
iterations int,
iterationDelay time.Duration,
interfaceCheckDelay time.Duration,
) AddressBroadcaster {
return arping{
cmdRunner: cmdRunner,
fs: fs,
logger: logger,
iterations: iterations,
iterationDelay: iterationDelay,
interfaceCheckDelay: interfaceCheckDelay,
}
}
// BroadcastMACAddresses broadcasts multiple IP/MAC pairs, multiple times
func (a arping) BroadcastMACAddresses(addresses []boship.InterfaceAddress) {
a.logger.Debug(arpingLogTag, "Broadcasting MAC addresses")
var wg sync.WaitGroup
for _, addr := range addresses {
wg.Add(1) // Outside of goroutine
go func(address boship.InterfaceAddress) {
a.blockUntilInterfaceExists(address.GetInterfaceName())
for i := 0; i < a.iterations; i++ {
a.broadcastMACAddress(address)
if i < a.iterations-1 {
// Sleep between iterations
time.Sleep(a.iterationDelay)
}
}
wg.Done()
}(addr)
}
wg.Wait()
}
// blockUntilInterfaceExists block until the specified network interface exists
// at /sys/class/net/<interfaceName>
func (a arping) blockUntilInterfaceExists(interfaceName string) {
// TODO: Timeout waiting for net interface to exist?
for !a.fs.FileExists(path.Join("/sys/class/net", interfaceName)) {
time.Sleep(a.interfaceCheckDelay)
}
}
// broadcastMACAddress broadcasts an IP/MAC pair to the specified network and logs any failure
func (a arping) broadcastMACAddress(address boship.InterfaceAddress) {
ip, err := address.GetIP()
if err != nil {
a.logger.Info(arpingLogTag, "Ignoring GetIP failure: %s", err.Error())
return
}
ifaceName := address.GetInterfaceName()
_, _, _, err = a.cmdRunner.RunCommand("arping", "-c", "1", "-U", "-I", ifaceName, ip)
if err != nil {
a.logger.Info(arpingLogTag, "Ignoring arping failure: %s", err.Error())
}
}