summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packet/bgp/bgp.go25
-rw-r--r--server/fsm.go122
2 files changed, 136 insertions, 11 deletions
diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go
index 7e60b96e..fb9e2a1c 100644
--- a/packet/bgp/bgp.go
+++ b/packet/bgp/bgp.go
@@ -7982,6 +7982,31 @@ func (msg *BGPUpdate) IsEndOfRib() (bool, RouteFamily) {
return false, RouteFamily(0)
}
+func TreatAsWithdraw(msg *BGPUpdate) *BGPUpdate {
+ withdraw := &BGPUpdate{
+ WithdrawnRoutesLen: 0,
+ WithdrawnRoutes: []*IPAddrPrefix{},
+ TotalPathAttributeLen: 0,
+ PathAttributes: make([]PathAttributeInterface, 0, len(msg.PathAttributes)),
+ NLRI: []*IPAddrPrefix{},
+ }
+ withdraw.WithdrawnRoutes = append(msg.WithdrawnRoutes, msg.NLRI...)
+ var unreach []AddrPrefixInterface
+
+ for _, p := range msg.PathAttributes {
+ switch nlri := p.(type) {
+ case *PathAttributeMpReachNLRI:
+ unreach = append(unreach, nlri.Value...)
+ case *PathAttributeMpUnreachNLRI:
+ unreach = append(unreach, nlri.Value...)
+ }
+ }
+ if len(unreach) != 0 {
+ withdraw.PathAttributes = append(withdraw.PathAttributes, NewPathAttributeMpUnreachNLRI(unreach))
+ }
+ return withdraw
+}
+
func NewBGPUpdateMessage(withdrawnRoutes []*IPAddrPrefix, pathattrs []PathAttributeInterface, nlri []*IPAddrPrefix) *BGPMessage {
return &BGPMessage{
Header: BGPHeader{Type: BGP_MSG_UPDATE},
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 {