summaryrefslogtreecommitdiffhomepage
path: root/server/fsm.go
diff options
context:
space:
mode:
Diffstat (limited to 'server/fsm.go')
-rw-r--r--server/fsm.go122
1 files changed, 111 insertions, 11 deletions
diff --git a/server/fsm.go b/server/fsm.go
index df31b30b..0d208eb4 100644
--- a/server/fsm.go
+++ b/server/fsm.go
@@ -681,6 +681,92 @@ func hasOwnASLoop(ownAS uint32, limit int, aspath *bgp.PathAttributeAsPath) bool
return false
}
+func extractRouteFamily(p *bgp.PathAttributeInterface) *bgp.RouteFamily {
+ attr := *p
+
+ var afi uint16
+ var safi uint8
+
+ switch a := attr.(type) {
+ case *bgp.PathAttributeMpReachNLRI:
+ afi = a.AFI
+ safi = a.SAFI
+ case *bgp.PathAttributeMpUnreachNLRI:
+ afi = a.AFI
+ safi = a.SAFI
+ default:
+ return nil
+ }
+
+ rf := bgp.AfiSafiToRouteFamily(afi, safi)
+ return &rf
+}
+
+func (h *FSMHandler) afiSafiDisable(rf bgp.RouteFamily) string {
+ n := bgp.AddressFamilyNameMap[rf]
+
+ for i, a := range h.fsm.pConf.AfiSafis {
+ if string(a.Config.AfiSafiName) == n {
+ h.fsm.pConf.AfiSafis[i].State.Enabled = false
+ break
+ }
+ }
+ newList := make([]bgp.ParameterCapabilityInterface, 0)
+ for _, c := range h.fsm.capMap[bgp.BGP_CAP_MULTIPROTOCOL] {
+ if c.(*bgp.CapMultiProtocol).CapValue == rf {
+ continue
+ }
+ newList = append(newList, c)
+ }
+ h.fsm.capMap[bgp.BGP_CAP_MULTIPROTOCOL] = newList
+ return n
+}
+
+func (h *FSMHandler) handlingError(m *bgp.BGPMessage, e error, useRevisedError bool) bgp.ErrorHandling {
+ handling := bgp.ERROR_HANDLING_NONE
+ if m.Header.Type == bgp.BGP_MSG_UPDATE && useRevisedError {
+ factor := e.(*bgp.MessageError)
+ handling = factor.ErrorHandling
+ switch handling {
+ case bgp.ERROR_HANDLING_ATTRIBUTE_DISCARD:
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": h.fsm.pConf.State.NeighborAddress,
+ "State": h.fsm.state.String(),
+ "error": e,
+ }).Warn("Some attributes were discarded")
+ case bgp.ERROR_HANDLING_TREAT_AS_WITHDRAW:
+ m.Body = bgp.TreatAsWithdraw(m.Body.(*bgp.BGPUpdate))
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": h.fsm.pConf.State.NeighborAddress,
+ "State": h.fsm.state.String(),
+ "error": e,
+ }).Warn("the received Update message was treated as withdraw")
+ case bgp.ERROR_HANDLING_AFISAFI_DISABLE:
+ rf := extractRouteFamily(factor.ErrorAttribute)
+ if rf == nil {
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": h.fsm.pConf.State.NeighborAddress,
+ "State": h.fsm.state.String(),
+ }).Warn("Error occured during AFI/SAFI disabling")
+ } else {
+ n := h.afiSafiDisable(*rf)
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": h.fsm.pConf.State.NeighborAddress,
+ "State": h.fsm.state.String(),
+ "error": e,
+ }).Warnf("Capability %s was disabled", n)
+ }
+ }
+ } else {
+ handling = bgp.ERROR_HANDLING_SESSION_RESET
+ }
+ return handling
+}
+
func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) {
sendToErrorCh := func(reason FsmStateReason) {
// probably doesn't happen but be cautious
@@ -705,7 +791,7 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) {
"Key": h.fsm.pConf.State.NeighborAddress,
"State": h.fsm.state.String(),
"error": err,
- }).Warn("malformed BGP Header")
+ }).Warn("Session will be reset due to malformed BGP Header")
fmsg := &FsmMsg{
MsgType: FSM_MSG_BGP_MESSAGE,
MsgSrc: h.fsm.pConf.State.NeighborAddress,
@@ -722,12 +808,16 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) {
}
now := time.Now()
+ useRevisedError := h.fsm.pConf.ErrorHandling.Config.TreatAsWithdraw
+ handling := bgp.ERROR_HANDLING_NONE
+
m, err := bgp.ParseBGPBody(hd, bodyBuf, h.fsm.marshallingOptions)
- if err == nil {
+ if err != nil {
+ handling = h.handlingError(m, err, useRevisedError)
+ h.fsm.bgpMessageStateUpdate(0, true)
+ } else {
h.fsm.bgpMessageStateUpdate(m.Header.Type, true)
err = bgp.ValidateBGPMessage(m)
- } else {
- h.fsm.bgpMessageStateUpdate(0, true)
}
fmsg := &FsmMsg{
MsgType: FSM_MSG_BGP_MESSAGE,
@@ -735,15 +825,21 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) {
timestamp: now,
Version: h.fsm.version,
}
- if err != nil {
+
+ switch handling {
+ case bgp.ERROR_HANDLING_AFISAFI_DISABLE:
+ fmsg.MsgData = m
+ return fmsg, nil
+ case bgp.ERROR_HANDLING_SESSION_RESET:
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": h.fsm.pConf.State.NeighborAddress,
"State": h.fsm.state.String(),
"error": err,
- }).Warn("malformed BGP message")
+ }).Warn("Session will be reset due to malformed BGP message")
fmsg.MsgData = err
- } else {
+ return fmsg, err
+ default:
fmsg.MsgData = m
if h.fsm.state == bgp.BGP_FSM_ESTABLISHED {
switch m.Header.Type {
@@ -757,14 +853,18 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) {
copy(fmsg.payload, headerBuf)
copy(fmsg.payload[len(headerBuf):], bodyBuf)
- _, err = bgp.ValidateUpdateMsg(body, h.fsm.rfMap, confedCheck)
- if err != nil {
+ ok, err := bgp.ValidateUpdateMsg(body, h.fsm.rfMap, confedCheck)
+ if !ok {
+ handling = h.handlingError(m, err, useRevisedError)
+ }
+
+ if handling == bgp.ERROR_HANDLING_SESSION_RESET {
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": h.fsm.pConf.State.NeighborAddress,
"State": h.fsm.state.String(),
"error": err,
- }).Warn("malformed BGP update message")
+ }).Warn("Session will be reset due to malformed BGP update message")
fmsg.MsgData = err
return fmsg, err
}
@@ -848,7 +948,7 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) {
}
}
}
- return fmsg, err
+ return fmsg, nil
}
func (h *FSMHandler) recvMessage() error {