-
Notifications
You must be signed in to change notification settings - Fork 0
/
router.go
129 lines (115 loc) · 2.65 KB
/
router.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* router.go: provides objects for managing router states
*
* Authors: J. Lowell Wofford <[email protected]> & Brett Holman <[email protected]>
*
* This software is open source software available under the BSD-3 license.
* Copyright (c) 2020, Triad National Security, LLC
* See LICENSE file for details.
*/
package main
import (
"net"
"sync"
"sync/atomic"
"time"
)
const (
metric = 0
)
var routers = map[string]*Router{}
// atomic counting of routers
// this allows us to create hooks based on how many are active
type routerCount int32
func (rc *routerCount) Up() {
c := atomic.AddInt32((*int32)(rc), 1)
l.INFO("there are %d/%d routers up", c, len(routers))
}
func (rc *routerCount) Down() {
c := atomic.AddInt32((*int32)(rc), -1)
l.INFO("there are %d/%d routers up", c, len(routers))
}
var routersUp routerCount = 0
// A Router represents a network router and is used to add/remove associated Routes when the state of a Router changes
type Router struct {
sync.Mutex
ip net.IP
routes map[string]*Route
dead time.Duration
timer *time.Timer
up bool
}
// NewRouter creates a new router. New routers always start in down state
func NewRouter(ip net.IP, rs map[string]*Route, dead time.Duration) (r *Router) {
r = &Router{
ip: ip,
routes: routes,
dead: dead,
timer: &time.Timer{},
up: false,
}
return
}
// Up sets router up, starts dead timer
func (r *Router) Up() {
r.Lock()
defer r.Unlock()
if r.up == true {
// already up
l.DEBUG("router.Up called, but this route is already up")
return
}
l.INFO("router %s is now up", r.ip.String())
r.up = true
r.timer = time.AfterFunc(r.dead, r.Dead)
// set route
if !conf.dry {
for _, route := range r.routes {
route.Add(r.ip)
}
} else {
l.DEBUG("dry run set, not adding route")
}
routersUp.Up()
}
// Down sets router down
func (r *Router) Down() {
r.Lock()
defer r.Unlock()
if r.up == false {
// already down
l.DEBUG("router.Down called, but this route is already down")
return
}
l.INFO("router %s is now down", r.ip.String())
r.timer.Stop()
r.up = false
// unset route
if !conf.dry {
for _, route := range r.routes {
route.Del(r.ip)
}
} else {
l.DEBUG("dry run set, not removing route")
}
routersUp.Down()
}
// Dead sets router dead. This also calls Down
func (r *Router) Dead() {
l.WARN("router %s hit dead state", r.ip.String())
r.Down()
}
// Hello reports a router hello
func (r *Router) Hello() {
l.DEBUG("received a HELLO for %s", r.ip.String())
r.Lock()
if r.up {
// just reset the timer
r.timer.Reset(r.dead)
r.Unlock()
} else {
// bring interface up
l.INFO("router returned to service %s", r.ip.String())
r.Unlock()
r.Up()
}
}