fix behaviour of data-flow-based switching
Sascha Steinbiss
5 years ago
98 | 98 | LastStats map[string]net.IOCountersStat |
99 | 99 | checkIncomingDelta bool |
100 | 100 | checkIncomingThreshold uint64 |
101 | configuredByLink map[string]bool | |
101 | 102 | OutChan chan LinkStatusSample |
102 | 103 | CloseChan chan bool |
103 | 104 | ClosedChan chan bool |
118 | 119 | func MakeLinkStatusMonitor(pollPeriod time.Duration, ifaces []string, |
119 | 120 | outChan chan LinkStatusSample) *LinkStatusMonitor { |
120 | 121 | a := &LinkStatusMonitor{ |
121 | PollPeriod: pollPeriod, | |
122 | OutChan: outChan, | |
123 | CloseChan: make(chan bool), | |
124 | ClosedChan: make(chan bool), | |
125 | Ifaces: ifaces, | |
126 | LastStatus: make(map[string]InterfaceStatus), | |
127 | LastStats: make(map[string]net.IOCountersStat), | |
122 | PollPeriod: pollPeriod, | |
123 | OutChan: outChan, | |
124 | CloseChan: make(chan bool), | |
125 | ClosedChan: make(chan bool), | |
126 | Ifaces: ifaces, | |
127 | LastStatus: make(map[string]InterfaceStatus), | |
128 | LastStats: make(map[string]net.IOCountersStat), | |
129 | configuredByLink: make(map[string]bool), | |
128 | 130 | } |
129 | 131 | return a |
130 | 132 | } |
150 | 152 | Ifaces: make(map[string]InterfaceStatus), |
151 | 153 | } |
152 | 154 | |
153 | changed := false | |
155 | // try to get status via link | |
154 | 156 | for _, iface := range a.Ifaces { |
155 | 157 | v, err := GetLinkStatus(iface) |
156 | 158 | if err != nil { |
157 | 159 | out.Ifaces[iface] = InterfaceUnknown |
158 | 160 | } |
159 | 161 | out.Ifaces[iface] = v |
160 | ||
161 | if a.LastStatus[iface] != out.Ifaces[iface] { | |
162 | changed = true | |
163 | a.LastStatus[iface] = out.Ifaces[iface] | |
164 | } | |
165 | } | |
166 | ||
167 | ifstats, err := net.IOCounters(true) | |
168 | if err != nil { | |
169 | return err | |
170 | } | |
171 | ||
162 | if v == InterfaceUp { | |
163 | // this interface has been seen up once via actual link status | |
164 | // let's record this fact so we won't override this from data | |
165 | // flow info | |
166 | if _, ok := a.configuredByLink[iface]; !ok { | |
167 | a.configuredByLink[iface] = true | |
168 | } | |
169 | } | |
170 | log.Debug("link status: ", iface, v) | |
171 | } | |
172 | ||
173 | // also try to determine status from data flow | |
172 | 174 | if a.checkIncomingDelta { |
175 | ifstats, err := net.IOCounters(true) | |
176 | if err != nil { | |
177 | return err | |
178 | } | |
173 | 179 | for _, stat := range ifstats { |
174 | 180 | for _, iface := range a.Ifaces { |
175 | 181 | 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)) | |
182 | if _, ok := a.configuredByLink[iface]; ok { | |
183 | if a.configuredByLink[iface] { | |
184 | continue | |
185 | } | |
186 | } | |
187 | log.Debugf("%s, %s, %d/%d -> %d", iface, a.LastStatus[iface], stat.BytesRecv, a.LastStats[iface].BytesRecv, myDiffAbs(stat.BytesRecv, a.LastStats[iface].BytesRecv)) | |
177 | 188 | if a.LastStatus[iface] != InterfaceUp { |
178 | 189 | if myDiffAbs(stat.BytesRecv, a.LastStats[iface].BytesRecv) > a.checkIncomingThreshold { |
179 | 190 | out.Ifaces[iface] = InterfaceUp |
189 | 200 | out.Ifaces[iface] = a.LastStatus[iface] |
190 | 201 | } |
191 | 202 | } |
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 | } | |
203 | a.LastStats[iface] = stat | |
197 | 204 | } |
198 | 205 | } |
199 | a.LastStats[stat.Name] = stat | |
206 | } | |
207 | } | |
208 | ||
209 | changed := false | |
210 | for iface := range out.Ifaces { | |
211 | if a.LastStatus[iface] != out.Ifaces[iface] { | |
212 | changed = true | |
213 | log.Debugf("status changed %s <-> %s", a.LastStatus[iface], out.Ifaces[iface]) | |
214 | a.LastStatus[iface] = out.Ifaces[iface] | |
200 | 215 | } |
201 | 216 | } |
202 | 217 |