diff options
author | Wataru Ishida <ishida.wataru@lab.ntt.co.jp> | 2016-10-09 07:18:13 -0700 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-10-09 07:18:13 -0700 |
commit | 614746ca1159fe421047df04c5af6f07c38b2e65 (patch) | |
tree | 77e93a40ec38318a96ab3a195fb1baa68372acd2 /server/fsm.go | |
parent | 6b6f6974fcea37dc006f90dbd2f8d65495048725 (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.go | 32 |
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", |