Coveralls logob
Coveralls logo
  • Home
  • Features
  • Pricing
  • Docs
  • Sign In

weaveworks / weave / #7201

20 Sep 2016 - 16:03 coverage decreased (-0.1%) to 73.98%
#7201

Pull #2501

circleci

7de8841b37903eead0e0bb4d567e9454?size=18&default=identiconbrb
Update weaveworks/mesh submodule
Pull Request #2501: Reject empty peers

6616 of 8943 relevant lines covered (73.98%)

121129.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.06
/router/overlay_switch.go
1
package router
2

3
import (
4
        "fmt"
5
        "strings"
6
        "sync"
7

8
        "github.com/weaveworks/mesh"
9
)
10

11
// OverlaySwitch selects which overlay to use, from a set of
12
// subsidiary overlays.  First, it passes a list of supported overlays
13
// in the connection features, and uses that to determine which
14
// overlays are in common.  Then it tries those common overlays, and
15
// uses the best one that seems to be working.
16

17
type OverlaySwitch struct {
18
        overlays      map[string]NetworkOverlay
19
        overlayNames  []string
20
        compatOverlay NetworkOverlay
21
}
22

23
func NewOverlaySwitch() *OverlaySwitch {
92×
24
        return &OverlaySwitch{overlays: make(map[string]NetworkOverlay)}
92×
25
}
92×
26

27
func (osw *OverlaySwitch) Add(name string, overlay NetworkOverlay) {
182×
28
        // check for repeated names
182×
29
        if _, present := osw.overlays[name]; present {
182×
30
                log.Fatal("OverlaySwitch: repeated overlay name")
!
31
        }
!
32

33
        osw.overlays[name] = overlay
182×
34
        osw.overlayNames = append(osw.overlayNames, name)
182×
35
}
36

37
func (osw *OverlaySwitch) SetCompatOverlay(overlay NetworkOverlay) {
92×
38
        osw.compatOverlay = overlay
92×
39
}
92×
40

41
func (osw *OverlaySwitch) AddFeaturesTo(features map[string]string) {
92×
42
        features["Overlays"] = strings.Join(osw.overlayNames, " ")
92×
43
}
92×
44

45
func (osw *OverlaySwitch) Diagnostics() interface{} {
168×
46
        diagnostics := make(map[string]interface{})
168×
47
        for name, overlay := range osw.overlays {
500×
48
                diagnostics[name] = overlay.Diagnostics()
332×
49
        }
332×
50
        return diagnostics
168×
51
}
52

53
func (osw *OverlaySwitch) InvalidateRoutes() {
413×
54
        for _, overlay := range osw.overlays {
1,230×
55
                overlay.InvalidateRoutes()
817×
56
        }
817×
57
}
58

59
func (osw *OverlaySwitch) InvalidateShortIDs() {
1×
60
        for _, overlay := range osw.overlays {
3×
61
                overlay.InvalidateShortIDs()
2×
62
        }
2×
63
}
64

65
func (osw *OverlaySwitch) StartConsumingPackets(localPeer *mesh.Peer, peers *mesh.Peers, consumer OverlayConsumer) error {
92×
66
        for _, overlay := range osw.overlays {
274×
67
                if err := overlay.StartConsumingPackets(localPeer, peers, consumer); err != nil {
182×
68
                        return err
!
69
                }
!
70
        }
71
        return nil
92×
72
}
73

74
type namedOverlay struct {
75
        NetworkOverlay
76
        name string
77
}
78

79
// Find the common set of overlays supported by both sides, with the
80
// ordering being the same on both sides too.
81
func (osw *OverlaySwitch) commonOverlays(params mesh.OverlayConnectionParams) ([]namedOverlay, error) {
84×
82
        var peerOverlays []string
84×
83
        if overlaysFeature, present := params.Features["Overlays"]; present {
168×
84
                peerOverlays = strings.Split(overlaysFeature, " ")
84×
85
        }
84×
86

87
        common := make(map[string]NetworkOverlay)
84×
88
        for _, name := range peerOverlays {
250×
89
                if overlay := osw.overlays[name]; overlay != nil {
332×
90
                        common[name] = overlay
166×
91
                }
166×
92
        }
93

94
        if len(common) == 0 {
84×
95
                return nil, fmt.Errorf("no overlays in common with peer")
!
96
        }
!
97

98
        // we order them according to the connecting node
99
        ordering := osw.overlayNames
84×
100
        if params.RemoteAddr == nil {
84×
101
                // we are the connectee
!
102
                ordering = peerOverlays
!
103
        }
!
104

105
        res := make([]namedOverlay, 0, len(common))
84×
106
        for _, name := range ordering {
250×
107
                overlay := common[name]
166×
108
                if overlay != nil {
332×
109
                        res = append(res, namedOverlay{overlay, name})
166×
110
                }
166×
111
        }
112

113
        // we use bytes to represent forwarder indices in control
114
        // messages, so just in case:
115
        if len(res) > 256 {
84×
116
                res = res[:256]
!
117
        }
!
118

119
        return res, nil
84×
120
}
121

122
type overlaySwitchForwarder struct {
123
        remotePeer *mesh.Peer
124

125
        lock sync.Mutex
126

127
        // the index of the forwarder to send on
128
        best int
129

130
        // the subsidiary forwarders
131
        forwarders []subForwarder
132

133
        // closed to tell the main goroutine to stop
134
        stopChan chan<- struct{}
135

136
        alreadyEstablished bool
137
        establishedChan    chan struct{}
138
        errorChan          chan error
139
}
140

141
// A subsidiary forwarder
142
type subForwarder struct {
143
        fwd         OverlayForwarder
144
        overlayName string
145

146
        // Has the forwarder signalled that it is established?
147
        established bool
148

149
        // closed to tell the forwarder monitor goroutine to stop
150
        stopChan chan<- struct{}
151
}
152

153
// An event from a subsidiary forwarder
154
type subForwarderEvent struct {
155
        // the index of the forwarder
156
        index int
157

158
        // is this an "established" event?
159
        established bool
160

161
        // is this an error event?
162
        err error
163
}
164

165
func (osw *OverlaySwitch) PrepareConnection(params mesh.OverlayConnectionParams) (mesh.OverlayConnection, error) {
84×
166
        if _, present := params.Features["Overlays"]; !present && osw.compatOverlay != nil {
84×
167
                return osw.compatOverlay.PrepareConnection(params)
!
168
        }
!
169

170
        overlays, err := osw.commonOverlays(params)
84×
171
        if err != nil {
84×
172
                return nil, err
!
173
        }
!
174

175
        // channel to carry events from the subforwarder monitors to
176
        // the main goroutine
177
        eventsChan := make(chan subForwarderEvent)
84×
178

84×
179
        // channel to stop the main goroutine
84×
180
        stopChan := make(chan struct{})
84×
181

84×
182
        fwd := &overlaySwitchForwarder{
84×
183
                remotePeer: params.RemotePeer,
84×
184

84×
185
                best:       -1,
84×
186
                forwarders: make([]subForwarder, len(overlays)),
84×
187
                stopChan:   stopChan,
84×
188

84×
189
                establishedChan: make(chan struct{}),
84×
190
                errorChan:       make(chan error, 1),
84×
191
        }
84×
192

84×
193
        origSendControlMessage := params.SendControlMessage
84×
194
        for i, overlay := range overlays {
250×
195
                // Prefix control messages to indicate the relevant forwarder
166×
196
                index := i
166×
197
                params.SendControlMessage = func(tag byte, msg []byte) error {
463×
198
                        xmsg := make([]byte, len(msg)+2)
297×
199
                        xmsg[0] = byte(index)
297×
200
                        xmsg[1] = tag
297×
201
                        copy(xmsg[2:], msg)
297×
202
                        return origSendControlMessage(mesh.ProtocolOverlayControlMsg, xmsg)
297×
203
                }
297×
204

205
                subConn, err := overlay.PrepareConnection(params)
166×
206
                if err != nil {
168×
207
                        log.Infof("Unable to use %s for connection to %s(%s): %s",
2×
208
                                overlay.name,
2×
209
                                params.RemotePeer.Name,
2×
210
                                params.RemotePeer.NickName,
2×
211
                                err)
2×
212
                        // failed to start subforwarder - record overlay name and continue
2×
213
                        fwd.forwarders[i] = subForwarder{
2×
214
                                overlayName: overlay.name,
2×
215
                        }
2×
216
                        continue
2×
217
                }
218
                subFwd := subConn.(OverlayForwarder)
164×
219

164×
220
                subStopChan := make(chan struct{})
164×
221
                go monitorForwarder(i, eventsChan, subStopChan, subFwd)
164×
222
                fwd.forwarders[i] = subForwarder{
164×
223
                        fwd:         subFwd,
164×
224
                        overlayName: overlay.name,
164×
225
                        stopChan:    subStopChan,
164×
226
                }
164×
227
        }
228

229
        fwd.chooseBest()
84×
230
        go fwd.run(eventsChan, stopChan)
84×
231
        return fwd, nil
84×
232
}
233

234
func monitorForwarder(index int, eventsChan chan<- subForwarderEvent, stopChan <-chan struct{}, fwd OverlayForwarder) {
164×
235
        establishedChan := fwd.EstablishedChannel()
164×
236
loop:
164×
237
        for {
472×
238
                e := subForwarderEvent{index: index}
308×
239

308×
240
                select {
308×
241
                case <-establishedChan:
144×
242
                        e.established = true
144×
243
                        establishedChan = nil
144×
244

UNCOV
245
                case err := <-fwd.ErrorChannel():
!
UNCOV
246
                        e.err = err
!
247

248
                case <-stopChan:
98×
249
                        break loop
98×
250
                }
251

252
                select {
144×
253
                case eventsChan <- e:
144×
254
                case <-stopChan:
!
255
                        break loop
!
256
                }
257

258
                if e.err != nil {
144×
UNCOV
259
                        break loop
!
260
                }
261
        }
262

263
        fwd.Stop()
98×
264
}
265

266
func (fwd *overlaySwitchForwarder) run(eventsChan <-chan subForwarderEvent, stopChan <-chan struct{}) {
84×
267
loop:
84×
268
        for {
312×
269
                select {
228×
270
                case <-stopChan:
!
271
                        break loop
!
272

273
                case e := <-eventsChan:
144×
274
                        switch {
144×
275
                        case e.established:
144×
276
                                fwd.established(e.index)
144×
UNCOV
277
                        case e.err != nil:
!
UNCOV
278
                                fwd.error(e.index, e.err)
!
279
                        }
280
                }
281
        }
282

283
        fwd.lock.Lock()
!
284
        defer fwd.lock.Unlock()
!
285
        fwd.stopFrom(0)
!
286
}
287

288
func (fwd *overlaySwitchForwarder) established(index int) {
144×
289
        fwd.lock.Lock()
144×
290
        defer fwd.lock.Unlock()
144×
291

144×
292
        fwd.forwarders[index].established = true
144×
293

144×
294
        if !fwd.alreadyEstablished {
218×
295
                fwd.alreadyEstablished = true
74×
296
                close(fwd.establishedChan)
74×
297
        }
74×
298

299
        fwd.chooseBest()
144×
300
}
301

302
func (fwd *overlaySwitchForwarder) logPrefix() string {
166×
303
        return fmt.Sprintf("overlay_switch ->[%s] ", fwd.remotePeer)
166×
304
}
166×
305

UNCOV
306
func (fwd *overlaySwitchForwarder) error(index int, err error) {
!
UNCOV
307
        fwd.lock.Lock()
!
UNCOV
308
        defer fwd.lock.Unlock()
!
UNCOV
309

!
UNCOV
310
        log.Info(fwd.logPrefix(), fwd.forwarders[index].overlayName, " ", err)
!
UNCOV
311
        fwd.forwarders[index].fwd = nil
!
UNCOV
312
        fwd.chooseBest()
!
UNCOV
313
}
!
314

315
func (fwd *overlaySwitchForwarder) stopFrom(index int) {
50×
316
        for index < len(fwd.forwarders) {
149×
317
                subFwd := &fwd.forwarders[index]
99×
318
                if subFwd.fwd != nil {
197×
319
                        subFwd.fwd = nil
98×
320
                        close(subFwd.stopChan)
98×
321
                }
98×
322
                index++
99×
323
        }
324
}
325

326
func (fwd *overlaySwitchForwarder) chooseBest() {
228×
327
        // the most preferred established forwarder is the best
228×
328
        // otherwise, the most preferred working forwarder is the best
228×
329
        bestEstablished := -1
228×
330
        bestWorking := -1
228×
331

228×
332
        for i := range fwd.forwarders {
680×
333
                subFwd := &fwd.forwarders[i]
452×
334
                if subFwd.fwd == nil {
456×
335
                        continue
4×
336
                }
337

338
                if bestWorking < 0 {
676×
339
                        bestWorking = i
228×
340
                }
228×
341

342
                if bestEstablished < 0 && subFwd.established {
592×
343
                        bestEstablished = i
144×
344
                }
144×
345
        }
346

347
        best := bestEstablished
228×
348
        if best < 0 {
312×
349
                if bestWorking < 0 {
84×
350
                        select {
!
351
                        case fwd.errorChan <- fmt.Errorf("no working forwarders to %s", fwd.remotePeer):
!
352
                        default:
!
353
                        }
354

355
                        return
!
356
                }
357

358
                best = bestWorking
84×
359
        }
360

361
        if fwd.best != best {
394×
362
                fwd.best = best
166×
363
                log.Info(fwd.logPrefix(), "using ", fwd.forwarders[best].overlayName)
166×
364
        }
166×
365
}
366

367
func (fwd *overlaySwitchForwarder) Confirm() {
82×
368
        var forwarders []OverlayForwarder
82×
369

82×
370
        fwd.lock.Lock()
82×
371
        for _, subFwd := range fwd.forwarders {
244×
372
                if subFwd.fwd != nil {
322×
373
                        forwarders = append(forwarders, subFwd.fwd)
160×
374
                }
160×
375
        }
376
        fwd.lock.Unlock()
82×
377

82×
378
        for _, subFwd := range forwarders {
242×
379
                subFwd.Confirm()
160×
380
        }
160×
381
}
382

383
func (fwd *overlaySwitchForwarder) Forward(pk ForwardPacketKey) FlowOp {
515×
384
        fwd.lock.Lock()
515×
385

515×
386
        if fwd.best >= 0 {
1,030×
387
                for i := fwd.best; i < len(fwd.forwarders); i++ {
1,030×
388
                        best := fwd.forwarders[i].fwd
515×
389
                        if best != nil {
1,030×
390
                                fwd.lock.Unlock()
515×
391
                                if op := best.Forward(pk); op != nil {
1,030×
392
                                        return op
515×
393
                                }
515×
394
                                fwd.lock.Lock()
!
395
                        }
396
                }
397
        }
398

399
        fwd.lock.Unlock()
!
400

!
401
        return DiscardingFlowOp{}
!
402
}
403

404
func (fwd *overlaySwitchForwarder) EstablishedChannel() <-chan struct{} {
82×
405
        return fwd.establishedChan
82×
406
}
82×
407

408
func (fwd *overlaySwitchForwarder) ErrorChannel() <-chan error {
82×
409
        return fwd.errorChan
82×
410
}
82×
411

412
func (fwd *overlaySwitchForwarder) Stop() {
50×
413
        fwd.lock.Lock()
50×
414
        defer fwd.lock.Unlock()
50×
415
        fwd.stopFrom(0)
50×
416
}
50×
417

418
func (fwd *overlaySwitchForwarder) ControlMessage(tag byte, msg []byte) {
296×
419
        fwd.lock.Lock()
296×
420
        subFwd := fwd.forwarders[msg[0]].fwd
296×
421
        fwd.lock.Unlock()
296×
422
        if subFwd != nil {
592×
423
                subFwd.ControlMessage(msg[1], msg[2:])
296×
424
        }
296×
425
}
426

427
func (fwd *overlaySwitchForwarder) DisplayName() string {
64×
428
        var best OverlayForwarder
64×
429

64×
430
        fwd.lock.Lock()
64×
431
        if fwd.best >= 0 {
128×
432
                best = fwd.forwarders[fwd.best].fwd
64×
433
        }
64×
434
        fwd.lock.Unlock()
64×
435

64×
436
        if best != nil {
128×
437
                return best.DisplayName()
64×
438
        }
64×
439

440
        return "none"
!
441
}
Troubleshooting · Open an Issue · Sales · Support · ENTERPRISE · CAREERS · STATUS
BLOG · TWITTER · Legal & Privacy · Supported CI Services · What's a CI service? · Automated Testing

© 2022 Coveralls, Inc