diff options
author | Wataru Ishida <ishida.wataru@lab.ntt.co.jp> | 2016-10-09 07:15:08 -0700 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-10-09 07:15:08 -0700 |
commit | 6b6f6974fcea37dc006f90dbd2f8d65495048725 (patch) | |
tree | 5dc899df38c1ab7e410ce13440a43a35b98a0810 | |
parent | c3d8784efc24816e30c3ba68cad8f9a8d9d00b28 (diff) |
*: Notification support for BGP GR
implement draft-ietf-idr-bgp-gr-notification-07
Signed-off-by: Wataru Ishida <ishida.wataru@lab.ntt.co.jp>
-rw-r--r-- | config/bgp_configs.go | 12 | ||||
-rw-r--r-- | packet/bgp/bgp.go | 6 | ||||
-rw-r--r-- | packet/bgp/helper.go | 2 | ||||
-rw-r--r-- | server/fsm.go | 18 | ||||
-rw-r--r-- | server/fsm_test.go | 2 | ||||
-rw-r--r-- | tools/pyang_plugins/gobgp.yang | 6 |
6 files changed, 38 insertions, 8 deletions
diff --git a/config/bgp_configs.go b/config/bgp_configs.go index 17ae937d..f56a3750 100644 --- a/config/bgp_configs.go +++ b/config/bgp_configs.go @@ -3549,6 +3549,9 @@ type GracefulRestartState struct { Mode Mode `mapstructure:"mode"` // original -> gobgp:deferral-time DeferralTime uint16 `mapstructure:"deferral-time"` + // original -> gobgp:notification-enabled + //gobgp:notification-enabled's original type is boolean + NotificationEnabled bool `mapstructure:"notification-enabled"` } func (lhs *GracefulRestartState) Equal(rhs *GracefulRestartState) bool { @@ -3582,6 +3585,9 @@ func (lhs *GracefulRestartState) Equal(rhs *GracefulRestartState) bool { if lhs.DeferralTime != rhs.DeferralTime { return false } + if lhs.NotificationEnabled != rhs.NotificationEnabled { + return false + } return true } @@ -3600,6 +3606,9 @@ type GracefulRestartConfig struct { HelperOnly bool `mapstructure:"helper-only"` // original -> gobgp:deferral-time DeferralTime uint16 `mapstructure:"deferral-time"` + // original -> gobgp:notification-enabled + //gobgp:notification-enabled's original type is boolean + NotificationEnabled bool `mapstructure:"notification-enabled"` } func (lhs *GracefulRestartConfig) Equal(rhs *GracefulRestartConfig) bool { @@ -3621,6 +3630,9 @@ func (lhs *GracefulRestartConfig) Equal(rhs *GracefulRestartConfig) bool { if lhs.DeferralTime != rhs.DeferralTime { return false } + if lhs.NotificationEnabled != rhs.NotificationEnabled { + return false + } return true } diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go index 916a5f69..b14eb8a5 100644 --- a/packet/bgp/bgp.go +++ b/packet/bgp/bgp.go @@ -426,11 +426,14 @@ func (c *CapGracefulRestart) MarshalJSON() ([]byte, error) { }) } -func NewCapGracefulRestart(restarting bool, time uint16, tuples []*CapGracefulRestartTuple) *CapGracefulRestart { +func NewCapGracefulRestart(restarting, notification bool, time uint16, tuples []*CapGracefulRestartTuple) *CapGracefulRestart { flags := 0 if restarting { flags = 0x08 } + if notification { + flags |= 0x04 + } return &CapGracefulRestart{ DefaultParameterCapability: DefaultParameterCapability{ CapCode: BGP_CAP_GRACEFUL_RESTART, @@ -3914,6 +3917,7 @@ const ( BGP_ERROR_SUB_OTHER_CONFIGURATION_CHANGE BGP_ERROR_SUB_CONNECTION_COLLISION_RESOLUTION BGP_ERROR_SUB_OUT_OF_RESOURCES + BGP_ERROR_SUB_HARD_RESET //draft-ietf-idr-bgp-gr-notification-07 ) // NOTIFICATION Error Subcode for BGP_ERROR_ROUTE_REFRESH diff --git a/packet/bgp/helper.go b/packet/bgp/helper.go index 423361b1..1a06db1e 100644 --- a/packet/bgp/helper.go +++ b/packet/bgp/helper.go @@ -26,7 +26,7 @@ func NewTestBGPOpenMessage() *BGPMessage { []ParameterCapabilityInterface{NewCapMultiProtocol(RF_IPv4_UC)}) g := &CapGracefulRestartTuple{4, 2, 3} p3 := NewOptionParameterCapability( - []ParameterCapabilityInterface{NewCapGracefulRestart(false, 100, + []ParameterCapabilityInterface{NewCapGracefulRestart(false, true, 100, []*CapGracefulRestartTuple{g})}) p4 := NewOptionParameterCapability( []ParameterCapabilityInterface{NewCapFourOctetASNumber(100000)}) diff --git a/server/fsm.go b/server/fsm.go index 5ac3e6a2..d86a5ff1 100644 --- a/server/fsm.go +++ b/server/fsm.go @@ -47,6 +47,7 @@ const ( FSM_NEW_CONNECTION = "new-connection" FSM_OPEN_MSG_RECEIVED = "open-msg-received" FSM_OPEN_MSG_NEGOTIATED = "open-msg-negotiated" + FSM_HARD_RESET = "hard-reset" ) type FsmMsgType int @@ -544,7 +545,8 @@ func capabilitiesFromConfig(pConf *config.Neighbor) []bgp.ParameterCapabilityInt } } time := c.RestartTime - caps = append(caps, bgp.NewCapGracefulRestart(restarting, time, tuples)) + notification := c.NotificationEnabled + caps = append(caps, bgp.NewCapGracefulRestart(restarting, notification, time, tuples)) } return caps } @@ -693,8 +695,11 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) { "Subcode": body.ErrorSubcode, "Data": body.Data, }).Warn("received notification") - - sendToErrorCh(FsmStateReason(fmt.Sprintf("%s %s", FSM_NOTIFICATION_RECV, bgp.NewNotificationErrorCode(body.ErrorCode, body.ErrorSubcode).String()))) + if 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()))) + } return nil, nil } } @@ -847,7 +852,7 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) { // To re-establish the session with its peer, the Restarting Speaker // MUST set the "Restart State" bit in the Graceful Restart Capability // of the OPEN message. - if fsm.pConf.GracefulRestart.State.PeerRestarting && cap.Flags != 0x08 { + if fsm.pConf.GracefulRestart.State.PeerRestarting && cap.Flags&0x08 == 0 { log.WithFields(log.Fields{ "Topic": "Peer", "Key": fsm.pConf.Config.NeighborAddress, @@ -857,6 +862,9 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) { h.conn.Close() return bgp.BGP_FSM_IDLE, FSM_INVALID_MSG } + if fsm.pConf.GracefulRestart.Config.NotificationEnabled && cap.Flags&0x04 > 0 { + fsm.pConf.GracefulRestart.State.NotificationEnabled = true + } } msg := bgp.NewBGPKeepAliveMessage() @@ -1170,7 +1178,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 && (err == FSM_READ_FAILED || err == FSM_WRITE_FAILED) { + if s := fsm.pConf.GracefulRestart.State; s.Enabled && ((s.NotificationEnabled && err != FSM_HARD_RESET) || err == FSM_READ_FAILED || err == FSM_WRITE_FAILED) { err = FSM_GRACEFUL_RESTART log.WithFields(log.Fields{ "Topic": "Peer", diff --git a/server/fsm_test.go b/server/fsm_test.go index f973fb76..5e31c67a 100644 --- a/server/fsm_test.go +++ b/server/fsm_test.go @@ -311,7 +311,7 @@ func open() *bgp.BGPMessage { []bgp.ParameterCapabilityInterface{bgp.NewCapMultiProtocol(bgp.RF_IPv4_UC)}) g := &bgp.CapGracefulRestartTuple{4, 2, 3} p3 := bgp.NewOptionParameterCapability( - []bgp.ParameterCapabilityInterface{bgp.NewCapGracefulRestart(true, 100, + []bgp.ParameterCapabilityInterface{bgp.NewCapGracefulRestart(true, true, 100, []*bgp.CapGracefulRestartTuple{g})}) p4 := bgp.NewOptionParameterCapability( []bgp.ParameterCapabilityInterface{bgp.NewCapFourOctetASNumber(100000)}) diff --git a/tools/pyang_plugins/gobgp.yang b/tools/pyang_plugins/gobgp.yang index a4f8e335..72c766ab 100644 --- a/tools/pyang_plugins/gobgp.yang +++ b/tools/pyang_plugins/gobgp.yang @@ -705,6 +705,9 @@ module gobgp { leaf deferral-time { type uint16; } + leaf notification-enabled { + type boolean; + } } augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:graceful-restart/bgp:state" { @@ -712,6 +715,9 @@ module gobgp { leaf deferral-time { type uint16; } + leaf notification-enabled { + type boolean; + } } augment "/bgp:bgp/bgp:peer-groups/bgp:peer-group" { |