@@ -18,7 +18,6 @@ import (
18
18
"context"
19
19
"strings"
20
20
"sync"
21
- "time"
22
21
23
22
"github.com/golang/protobuf/proto"
24
23
prototypes "github.com/golang/protobuf/ptypes/empty"
@@ -35,11 +34,6 @@ const (
35
34
// InterfaceWatcherName is the name of the descriptor watching Linux interfaces
36
35
// in the default namespace.
37
36
InterfaceWatcherName = "linux-interface-watcher"
38
-
39
- // notificationDelay specifies how long to delay notification when interface changes.
40
- // Typically interface is created in multiple stages and we do not want to notify
41
- // scheduler about intermediate states.
42
- notificationDelay = 500 * time .Millisecond
43
37
)
44
38
45
39
// InterfaceWatcher watches default namespace for newly added/removed Linux interfaces.
@@ -58,9 +52,6 @@ type InterfaceWatcher struct {
58
52
ifacesMu sync.Mutex
59
53
ifaces map [string ]struct {}
60
54
61
- // interface changes delayed to give Linux time to "finalize" them
62
- pendingIntfs map [string ]bool // interface name -> exists?
63
-
64
55
// conditional variable to check if the list of interfaces is in-sync with
65
56
// Linux network stack
66
57
intfsInSync bool
@@ -74,13 +65,12 @@ type InterfaceWatcher struct {
74
65
// NewInterfaceWatcher creates a new instance of the Interface Watcher.
75
66
func NewInterfaceWatcher (kvscheduler kvs.KVScheduler , ifHandler linuxcalls.NetlinkAPI , log logging.PluginLogger ) * InterfaceWatcher {
76
67
descriptor := & InterfaceWatcher {
77
- log : log .NewLogger ("if-watcher" ),
78
- kvscheduler : kvscheduler ,
79
- ifHandler : ifHandler ,
80
- ifaces : make (map [string ]struct {}),
81
- pendingIntfs : make (map [string ]bool ),
82
- notifCh : make (chan netlink.LinkUpdate ),
83
- doneCh : make (chan struct {}),
68
+ log : log .NewLogger ("if-watcher" ),
69
+ kvscheduler : kvscheduler ,
70
+ ifHandler : ifHandler ,
71
+ ifaces : make (map [string ]struct {}),
72
+ notifCh : make (chan netlink.LinkUpdate ),
73
+ doneCh : make (chan struct {}),
84
74
}
85
75
descriptor .intfsInSyncCond = sync .NewCond (& descriptor .ifacesMu )
86
76
descriptor .ctx , descriptor .cancel = context .WithCancel (context .Background ())
@@ -185,59 +175,14 @@ func (w *InterfaceWatcher) processLinkNotification(linkUpdate netlink.LinkUpdate
185
175
defer w .ifacesMu .Unlock ()
186
176
187
177
ifName := linkUpdate .Attrs ().Name
188
- isEnabled := linkUpdate .Attrs ().OperState != netlink .OperDown &&
189
- linkUpdate .Attrs ().OperState != netlink .OperNotPresent
190
-
191
- _ , isPendingNotif := w .pendingIntfs [ifName ]
192
- if isPendingNotif {
193
- // notification for this interface is already scheduled, just update the state
194
- w .pendingIntfs [ifName ] = isEnabled
195
- return
196
- }
178
+ isUp := isLinkUp (linkUpdate )
197
179
198
- if ! w .needsUpdate (ifName , isEnabled ) {
180
+ if ! w .needsUpdate (ifName , isUp ) {
199
181
// ignore notification if the interface admin status remained the same
200
182
return
201
183
}
202
184
203
- if isEnabled {
204
- // do not notify until interface is truly finished
205
- w .pendingIntfs [ifName ] = true
206
- w .wg .Add (1 )
207
- go w .delayNotification (ifName )
208
- return
209
- }
210
-
211
- // notification about removed interface is propagated immediately
212
- w .notifyScheduler (ifName , false )
213
- }
214
-
215
- // delayNotification delays notification about enabled interface - typically
216
- // interface is created in multiple stages and we do not want to notify scheduler
217
- // about intermediate states.
218
- func (w * InterfaceWatcher ) delayNotification (ifName string ) {
219
- defer w .wg .Done ()
220
-
221
- select {
222
- case <- w .ctx .Done ():
223
- return
224
- case <- time .After (notificationDelay ):
225
- w .applyDelayedNotification (ifName )
226
- }
227
- }
228
-
229
- // applyDelayedNotification applies delayed interface notification.
230
- func (w * InterfaceWatcher ) applyDelayedNotification (ifName string ) {
231
- w .ifacesMu .Lock ()
232
- defer w .ifacesMu .Unlock ()
233
-
234
- // in the meantime the status may have changed and may not require update anymore
235
- isEnabled := w .pendingIntfs [ifName ]
236
- if w .needsUpdate (ifName , isEnabled ) {
237
- w .notifyScheduler (ifName , isEnabled )
238
- }
239
-
240
- delete (w .pendingIntfs , ifName )
185
+ w .notifyScheduler (ifName , isUp )
241
186
}
242
187
243
188
// notifyScheduler notifies scheduler about interface change.
@@ -251,14 +196,21 @@ func (w *InterfaceWatcher) notifyScheduler(ifName string, enabled bool) {
251
196
delete (w .ifaces , ifName )
252
197
}
253
198
254
- w .kvscheduler .PushSBNotification (kvs.KVWithMetadata {
199
+ if err := w .kvscheduler .PushSBNotification (kvs.KVWithMetadata {
255
200
Key : ifmodel .InterfaceHostNameKey (ifName ),
256
201
Value : value ,
257
202
Metadata : nil ,
258
- })
203
+ }); err != nil {
204
+ w .log .Warnf ("pushing SB notification failed: %v" , err )
205
+ }
259
206
}
260
207
261
208
func (w * InterfaceWatcher ) needsUpdate (ifName string , isEnabled bool ) bool {
262
209
_ , wasEnabled := w .ifaces [ifName ]
263
210
return isEnabled != wasEnabled
264
211
}
212
+
213
+ func isLinkUp (update netlink.LinkUpdate ) bool {
214
+ return update .Attrs ().OperState != netlink .OperDown &&
215
+ update .Attrs ().OperState != netlink .OperNotPresent
216
+ }
0 commit comments