summaryrefslogtreecommitdiffhomepage
path: root/server/fsm.go
diff options
context:
space:
mode:
authorWataru Ishida <ishida.wataru@lab.ntt.co.jp>2016-10-09 07:18:13 -0700
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2016-10-09 07:18:13 -0700
commit614746ca1159fe421047df04c5af6f07c38b2e65 (patch)
tree77e93a40ec38318a96ab3a195fb1baa68372acd2 /server/fsm.go
parent6b6f6974fcea37dc006f90dbd2f8d65495048725 (diff)
*: support long lived graceful restart
Signed-off-by: Wataru Ishida <ishida.wataru@lab.ntt.co.jp>
Diffstat (limited to 'server/fsm.go')
-rw-r--r--server/fsm.go32
1 files changed, 28 insertions, 4 deletions
diff --git a/server/fsm.go b/server/fsm.go
index d86a5ff1..c8ae658b 100644
--- a/server/fsm.go
+++ b/server/fsm.go
@@ -27,6 +27,7 @@ import (
"math/rand"
"net"
"strconv"
+ "strings"
"time"
)
@@ -521,6 +522,7 @@ func capabilitiesFromConfig(pConf *config.Neighbor) []bgp.ParameterCapabilityInt
if c := pConf.GracefulRestart.Config; c.Enabled {
tuples := []*bgp.CapGracefulRestartTuple{}
+ ltuples := []*bgp.CapLongLivedGracefulRestartTuple{}
// RFC 4724 4.1
// To re-establish the session with its peer, the Restarting Speaker
@@ -530,8 +532,8 @@ func capabilitiesFromConfig(pConf *config.Neighbor) []bgp.ParameterCapabilityInt
if !c.HelperOnly {
for i, rf := range pConf.AfiSafis {
- if rf.MpGracefulRestart.Config.Enabled {
- k, _ := bgp.GetRouteFamily(string(rf.Config.AfiSafiName))
+ k, _ := bgp.GetRouteFamily(string(rf.Config.AfiSafiName))
+ if m := rf.MpGracefulRestart.Config; m.Enabled {
// When restarting, always flag forwaring bit.
// This can be a lie, depending on how gobgpd is used.
// For a route-server use-case, since a route-server
@@ -542,11 +544,17 @@ func capabilitiesFromConfig(pConf *config.Neighbor) []bgp.ParameterCapabilityInt
tuples = append(tuples, bgp.NewCapGracefulRestartTuple(k, restarting))
pConf.AfiSafis[i].MpGracefulRestart.State.Advertised = true
}
+ if m := rf.LongLivedGracefulRestart.Config; m.Enabled {
+ ltuples = append(ltuples, bgp.NewCapLongLivedGracefulRestartTuple(k, restarting, m.RestartTime))
+ }
}
}
time := c.RestartTime
notification := c.NotificationEnabled
caps = append(caps, bgp.NewCapGracefulRestart(restarting, notification, time, tuples))
+ if c.LongLivedEnabled {
+ caps = append(caps, bgp.NewCapLongLivedGracefulRestart(ltuples))
+ }
}
return caps
}
@@ -695,7 +703,7 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) {
"Subcode": body.ErrorSubcode,
"Data": body.Data,
}).Warn("received notification")
- if body.ErrorCode == bgp.BGP_ERROR_CEASE && body.ErrorSubcode == bgp.BGP_ERROR_SUB_HARD_RESET {
+ if s := h.fsm.pConf.GracefulRestart.State; s.Enabled && s.NotificationEnabled && body.ErrorCode == bgp.BGP_ERROR_CEASE && body.ErrorSubcode == bgp.BGP_ERROR_SUB_HARD_RESET {
sendToErrorCh(FSM_HARD_RESET)
} else {
sendToErrorCh(FsmStateReason(fmt.Sprintf("%s %s", FSM_NOTIFICATION_RECV, bgp.NewNotificationErrorCode(body.ErrorCode, body.ErrorSubcode).String())))
@@ -866,6 +874,22 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) {
fsm.pConf.GracefulRestart.State.NotificationEnabled = true
}
}
+ llgr, ok2 := fsm.capMap[bgp.BGP_CAP_LONG_LIVED_GRACEFUL_RESTART]
+ if fsm.pConf.GracefulRestart.Config.LongLivedEnabled && ok && ok2 {
+ fsm.pConf.GracefulRestart.State.LongLivedEnabled = true
+ cap := llgr[len(llgr)-1].(*bgp.CapLongLivedGracefulRestart)
+ for _, t := range cap.Tuples {
+ n := bgp.AddressFamilyNameMap[bgp.AfiSafiToRouteFamily(t.AFI, t.SAFI)]
+ for i, a := range fsm.pConf.AfiSafis {
+ if string(a.Config.AfiSafiName) == n {
+ fsm.pConf.AfiSafis[i].LongLivedGracefulRestart.State.Enabled = true
+ fsm.pConf.AfiSafis[i].LongLivedGracefulRestart.State.Received = true
+ fsm.pConf.AfiSafis[i].LongLivedGracefulRestart.State.PeerRestartTime = t.RestartTime
+ break
+ }
+ }
+ }
+ }
msg := bgp.NewBGPKeepAliveMessage()
b, _ := msg.Serialize()
@@ -1178,7 +1202,7 @@ func (h *FSMHandler) established() (bgp.FSMState, FsmStateReason) {
case err := <-h.errorCh:
h.conn.Close()
h.t.Kill(nil)
- if s := fsm.pConf.GracefulRestart.State; s.Enabled && ((s.NotificationEnabled && err != FSM_HARD_RESET) || err == FSM_READ_FAILED || err == FSM_WRITE_FAILED) {
+ if s := fsm.pConf.GracefulRestart.State; s.Enabled && ((s.NotificationEnabled && strings.HasPrefix(string(err), FSM_NOTIFICATION_RECV)) || err == FSM_READ_FAILED || err == FSM_WRITE_FAILED) {
err = FSM_GRACEFUL_RESTART
log.WithFields(log.Fields{
"Topic": "Peer",