summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorWataru Ishida <ishida.wataru@lab.ntt.co.jp>2016-10-09 07:15:08 -0700
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2016-10-09 07:15:08 -0700
commit6b6f6974fcea37dc006f90dbd2f8d65495048725 (patch)
tree5dc899df38c1ab7e410ce13440a43a35b98a0810
parentc3d8784efc24816e30c3ba68cad8f9a8d9d00b28 (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.go12
-rw-r--r--packet/bgp/bgp.go6
-rw-r--r--packet/bgp/helper.go2
-rw-r--r--server/fsm.go18
-rw-r--r--server/fsm_test.go2
-rw-r--r--tools/pyang_plugins/gobgp.yang6
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" {