Codebase list golang-github-satta-ifplugo / 80486df
New upstream version 0.0~git20180801.7e2d884 Sascha Steinbiss 5 years ago
3 changed file(s) with 104 addition(s) and 30 deletion(s). Raw diff Collapse all Expand all
1414
1515 ```Go
1616 const (
17 // InterfaceUnknown represents an interface with no assigned state.
18 InterfaceUnknown InterfaceStatus = iota
19 // InterfaceUp represents an interface with a cable connected.
20 InterfaceUp
21 // InterfaceDown represents an interface with no cable connected.
22 InterfaceDown
23 // InterfaceErr represents an interface with errors querying its status.
24 InterfaceErr
17 // InterfaceUnknown represents an interface with no assigned state.
18 InterfaceUnknown InterfaceStatus = iota
19 // InterfaceUp represents an interface with a cable connected.
20 InterfaceUp
21 // InterfaceDown represents an interface with no cable connected.
22 InterfaceDown
23 // InterfaceErr represents an interface with errors querying its status.
24 InterfaceErr
2525 )
2626 ```
2727
4040 mon.Run()
4141 ```
4242
43 It is also possible to determine the status of an interface from whether any data is flowing or not. This can be useful if, for example, the interesting interface is only connected to one way of the physical connection (RX or TX) or for other reasons can not complete autonegotiation. Use `CheckIncomingDelta()` in this case, it allows to also mark an interface as 'up' and seeing traffic if a certain threshold of received bytes is exceeded during one polling period. Example:
44
45 ```Go
46 mon.CheckIncomingDelta(true, 1000)
47 ```
48
49 This would, for example, also mark an interface as up if more than 1000 bytes are received during the polling period, and mark the interface as down if there are ever less than 1000 bytes received in a polling period.
50
4351 ## Prerequisites
4452
4553 To build ifplugo, one needs [libdaemon](http://0pointer.de/lennart/projects/libdaemon/) in addition to Go and C compilers.
4957
5058 See the source code of the simple command line tools in `cmd/*` for more simple examples of how to use ifplugo.
5159
52 ```
60 ```Text
5361 $ ifplugo-watch eth0,eth1,eth2,eth3
5462 eth0: link
5563 eth1: link
6169
6270 ## Authors
6371
64 This source code includes parts of ifplugd, written by Lennart Poettering
65 <mzvscyhtq (at) 0pointer (dot) de>.
72 This source code includes parts of ifplugd, written by Lennart Poettering <mzvscyhtq (at) 0pointer (dot) de>.
6673
67 The Go component of the code was written by Sascha Steinbiss
68 <sascha (at) steinbiss (dot) name>.
74 The Go component of the code was written by Sascha Steinbiss <sascha (at) steinbiss (dot) name>.
6975
7076 ## License
7177
1616 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
1717
1818 import (
19 "flag"
1920 "fmt"
2021 "os"
2122 "strings"
2223 "time"
2324
2425 "github.com/satta/ifplugo"
26 log "github.com/sirupsen/logrus"
2527 )
2628
2729 func main() {
28 if len(os.Args) < 2 {
30 deltaValPtr := flag.Int("delta", 0, "number of bytes transferred per polling period to mark interface as seeing traffic")
31 pollingPtr := flag.Duration("poll", 2*time.Second, "polling period")
32 verbPtr := flag.Bool("verbose", false, "verbose logging")
33 flag.Parse()
34
35 if len(flag.Args()) < 1 {
2936 fmt.Println("Usage: ifplugo-status <iface1,iface2,...>")
3037 os.Exit(1)
3138 }
32 ifaces := strings.Split(os.Args[1], ",")
39 ifaces := strings.Split(flag.Args()[0], ",")
40
41 if *verbPtr {
42 log.SetLevel(log.DebugLevel)
43 }
3344
3445 outchan := make(chan ifplugo.LinkStatusSample)
35 mon := ifplugo.MakeLinkStatusMonitor(2*time.Second, ifaces, outchan)
46 mon := ifplugo.MakeLinkStatusMonitor(*pollingPtr, ifaces, outchan)
47 if *deltaValPtr > 0 {
48 mon.CheckIncomingDelta(true, uint64(*deltaValPtr))
49 }
3650 go func() {
3751 for v := range outchan {
3852 for k, v := range v.Ifaces {
2626 import (
2727 "syscall"
2828 "time"
29
30 "github.com/shirou/gopsutil/net"
31 log "github.com/sirupsen/logrus"
2932 )
3033
3134 // InterfaceStatus represents the link status of an interface.
9093 // periodically checks a list of given interfaces and returns their link status
9194 // via a specified channel.
9295 type LinkStatusMonitor struct {
93 PollPeriod time.Duration
94 LastStatus map[string]InterfaceStatus
95 OutChan chan LinkStatusSample
96 CloseChan chan bool
97 ClosedChan chan bool
98 Ifaces []string
96 PollPeriod time.Duration
97 LastStatus map[string]InterfaceStatus
98 LastStats map[string]net.IOCountersStat
99 checkIncomingDelta bool
100 checkIncomingThreshold uint64
101 OutChan chan LinkStatusSample
102 CloseChan chan bool
103 ClosedChan chan bool
104 Ifaces []string
99105 }
100106
101107 // LinkStatusSample is a single description of the link status at a given time.
118124 ClosedChan: make(chan bool),
119125 Ifaces: ifaces,
120126 LastStatus: make(map[string]InterfaceStatus),
127 LastStats: make(map[string]net.IOCountersStat),
121128 }
122129 return a
130 }
131
132 // CheckIncomingDelta allows to enable the optional behaviour to also consider
133 // an interface as 'up' if traffic is received on it. This is, for example,
134 // necessary in passive monitoring setups where there is no physical link
135 // detected (e.g. using taps that only provide RX lines).
136 func (a *LinkStatusMonitor) CheckIncomingDelta(val bool, threshold uint64) {
137 a.checkIncomingDelta = val
138 a.checkIncomingThreshold = threshold
139 }
140
141 func myDiffAbs(new, old uint64) uint64 {
142 if new > old {
143 return new - old
144 }
145 return 0
123146 }
124147
125148 func (a *LinkStatusMonitor) flush() error {
141164 }
142165 }
143166
167 ifstats, err := net.IOCounters(true)
168 if err != nil {
169 return err
170 }
171
172 if a.checkIncomingDelta {
173 for _, stat := range ifstats {
174 for _, iface := range a.Ifaces {
175 if stat.Name == iface {
176 log.Debugf("%s, %d/%d -> %d", a.LastStatus[iface], stat.BytesRecv, a.LastStats[iface].BytesRecv, myDiffAbs(stat.BytesRecv, a.LastStats[iface].BytesRecv))
177 if a.LastStatus[iface] != InterfaceUp {
178 if myDiffAbs(stat.BytesRecv, a.LastStats[iface].BytesRecv) > a.checkIncomingThreshold {
179 out.Ifaces[iface] = InterfaceUp
180 log.Debugf("changed %s to up", iface)
181 } else {
182 out.Ifaces[iface] = a.LastStatus[iface]
183 }
184 } else {
185 if myDiffAbs(stat.BytesRecv, a.LastStats[iface].BytesRecv) <= a.checkIncomingThreshold {
186 out.Ifaces[iface] = InterfaceDown
187 log.Debugf("changed %s to down", iface)
188 } else {
189 out.Ifaces[iface] = a.LastStatus[iface]
190 }
191 }
192 if a.LastStatus[iface] != out.Ifaces[iface] {
193 log.Debugf("%s <-> %s", a.LastStatus[iface], out.Ifaces[iface])
194 changed = true
195 a.LastStatus[iface] = out.Ifaces[iface]
196 }
197 }
198 }
199 a.LastStats[stat.Name] = stat
200 }
201 }
202
144203 if changed {
145204 a.OutChan <- out
146205 }
150209 // Run starts watching interfaces in the background.
151210 func (a *LinkStatusMonitor) Run() {
152211 go func() {
153 i := 0 * time.Second
212 a.flush()
154213 for {
155214 select {
156215 case <-a.CloseChan:
157216 close(a.ClosedChan)
158217 return
159 default:
160 if i >= a.PollPeriod {
161 a.flush()
162 i = 0 * time.Second
163 }
164 time.Sleep(1 * time.Second)
165 i += 1 * time.Second
218 case <-time.After(a.PollPeriod):
219 a.flush()
166220 }
167221 }
168222 }()