Newer
Older
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package server
import (
"fmt"
"net"
"time"
"github.com/bio-routing/bio-rd/protocols/bgp/packet"
"github.com/bio-routing/bio-rd/routingtable"
"github.com/bio-routing/bio-rd/routingtable/adjRIBIn"
"github.com/bio-routing/bio-rd/routingtable/locRIB"
)
type state interface {
run() (state, string)
}
// FSM2 implements the BGP finite state machine (RFC4271)
type FSM2 struct {
server *BGPServer
peer *Peer
eventCh chan int
con net.Conn
conCh chan net.Conn
delayOpen bool
delayOpenTime time.Duration
delayOpenTimer *time.Timer
connectRetryTime time.Duration
connectRetryTimer *time.Timer
connectRetryCounter int
holdTimeConfigured time.Duration
holdTime time.Duration
holdTimer *time.Timer
keepaliveTime time.Duration
keepaliveTimer *time.Timer
msgRecvCh chan msgRecvMsg
msgRecvFailCh chan msgRecvErr
stopMsgRecvCh chan struct{}
capAddPathSend bool
capAddPathRecv bool
local net.IP
remote net.IP
ribsInitialized bool
adjRIBIn *adjRIBIn.AdjRIBIn
adjRIBOut routingtable.RouteTableClient
rib *locRIB.LocRIB
updateSender routingtable.RouteTableClient
neighborID uint32
state state
reason string
active bool
}
// NewPassiveFSM2 initiates a new passive FSM
func NewPassiveFSM2(peer *Peer, con *net.TCPConn) *FSM2 {
fsm := &FSM2{
peer: peer,
eventCh: make(chan int),
con: con,
conCh: make(chan net.Conn),
msgRecvCh: make(chan msgRecvMsg),
msgRecvFailCh: make(chan msgRecvErr),
stopMsgRecvCh: make(chan struct{}),
}
return fsm
}
// NewActiveFSM2 initiates a new passive FSM
func NewActiveFSM2(peer *Peer) *FSM2 {
return &FSM2{
peer: peer,
eventCh: make(chan int),
active: true,
conCh: make(chan net.Conn),
}
}
func (fsm *FSM2) Cease() {
}
func (fsm *FSM2) startConnectRetryTimer() {
fsm.connectRetryTimer = time.NewTimer(time.Second * fsm.connectRetryTime)
}
func (fsm *FSM2) resetConnectRetryTimer() {
if !fsm.connectRetryTimer.Reset(time.Second * fsm.connectRetryTime) {
<-fsm.connectRetryTimer.C
}
}
func (fsm *FSM2) resetConnectRetryCounter() {
fsm.connectRetryCounter = 0
}
func (fsm *FSM2) tcpConnect() {
}
func (fsm *FSM2) sendOpen() error {
msg := packet.SerializeOpenMsg(&packet.BGPOpen{
Version: BGPVersion,
AS: uint16(fsm.peer.asn),
HoldTime: uint16(fsm.holdTimeConfigured),
BGPIdentifier: fsm.server.routerID,
OptParams: fsm.peer.optOpenParams,
})
_, err := fsm.con.Write(msg)
if err != nil {
return fmt.Errorf("Unable to send OPEN message: %v", err)
}
return nil
}
func (fsm *FSM2) sendNotification(errorCode uint8, errorSubCode uint8) error {
msg := packet.SerializeNotificationMsg(&packet.BGPNotification{})
_, err := fsm.con.Write(msg)
if err != nil {
return fmt.Errorf("Unable to send NOTIFICATION message: %v", err)
}
return nil
}
func (fsm *FSM2) sendKeepalive() error {
msg := packet.SerializeKeepaliveMsg()
_, err := fsm.con.Write(msg)
if err != nil {
return fmt.Errorf("Unable to send KEEPALIVE message: %v", err)
}
return nil
}
func stopTimer(t *time.Timer) {
if !t.Stop() {
select {
case <-t.C:
default:
}
}
}