summaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/fsm.go16
-rw-r--r--server/peer.go48
-rw-r--r--server/server.go7
3 files changed, 50 insertions, 21 deletions
diff --git a/server/fsm.go b/server/fsm.go
index 48f4e095..01587668 100644
--- a/server/fsm.go
+++ b/server/fsm.go
@@ -109,6 +109,7 @@ type AdminState int
const (
ADMIN_STATE_UP AdminState = iota
ADMIN_STATE_DOWN
+ ADMIN_STATE_PFX_CT
)
func (s AdminState) String() string {
@@ -117,6 +118,8 @@ func (s AdminState) String() string {
return "ADMIN_STATE_UP"
case ADMIN_STATE_DOWN:
return "ADMIN_STATE_DOWN"
+ case ADMIN_STATE_PFX_CT:
+ return "ADMIN_STATE_PFX_CT"
default:
return "Unknown"
}
@@ -1086,15 +1089,14 @@ func (h *FSMHandler) sendMessageloop() error {
}
}
if m.Notification != nil {
+ if m.StayIdle {
+ // current user is only prefix-limit
+ // fix me if this is not the case
+ h.changeAdminState(ADMIN_STATE_PFX_CT)
+ }
if err := send(m.Notification); err != nil {
return nil
}
- if m.StayIdle {
- select {
- case h.fsm.adminStateCh <- ADMIN_STATE_DOWN:
- default:
- }
- }
}
case <-ticker.C:
if err := send(bgp.NewBGPKeepAliveMessage()); err != nil {
@@ -1272,7 +1274,7 @@ func (h *FSMHandler) changeAdminState(s AdminState) error {
"State": fsm.state,
}).Info("Administrative start")
- case ADMIN_STATE_DOWN:
+ case ADMIN_STATE_DOWN, ADMIN_STATE_PFX_CT:
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": fsm.pConf.Config.NeighborAddress,
diff --git a/server/peer.go b/server/peer.go
index 950526dd..cc71063a 100644
--- a/server/peer.go
+++ b/server/peer.go
@@ -33,15 +33,16 @@ const (
)
type Peer struct {
- tableId string
- gConf config.Global
- conf config.Neighbor
- fsm *FSM
- adjRibIn *table.AdjRib
- adjRibOut *table.AdjRib
- outgoing chan *FsmOutgoingMsg
- policy *table.RoutingPolicy
- localRib *table.TableManager
+ tableId string
+ gConf config.Global
+ conf config.Neighbor
+ fsm *FSM
+ adjRibIn *table.AdjRib
+ adjRibOut *table.AdjRib
+ outgoing chan *FsmOutgoingMsg
+ policy *table.RoutingPolicy
+ localRib *table.TableManager
+ prefixLimitWarned bool
}
func NewPeer(g config.Global, conf config.Neighbor, loc *table.TableManager, policy *table.RoutingPolicy) *Peer {
@@ -227,7 +228,7 @@ func (peer *Peer) handleRouteRefresh(e *FsmMsg) []*table.Path {
return accepted
}
-func (peer *Peer) handleUpdate(e *FsmMsg) ([]*table.Path, []bgp.RouteFamily) {
+func (peer *Peer) handleUpdate(e *FsmMsg) ([]*table.Path, []bgp.RouteFamily, *bgp.BGPMessage) {
m := e.MsgData.(*bgp.BGPMessage)
log.WithFields(log.Fields{
"Topic": "Peer",
@@ -237,6 +238,29 @@ func (peer *Peer) handleUpdate(e *FsmMsg) ([]*table.Path, []bgp.RouteFamily) {
peer.conf.Timers.State.UpdateRecvTime = time.Now().Unix()
if len(e.PathList) > 0 {
peer.adjRibIn.Update(e.PathList)
+ for _, family := range peer.fsm.pConf.AfiSafis {
+ k, _ := bgp.GetRouteFamily(string(family.AfiSafiName))
+ count := peer.adjRibIn.Count([]bgp.RouteFamily{k})
+ if maxPrefixes := int(family.PrefixLimit.Config.MaxPrefixes); maxPrefixes > 0 {
+ pct := int(family.PrefixLimit.Config.ShutdownThresholdPct)
+ if pct > 0 && !peer.prefixLimitWarned && count > (maxPrefixes*pct/100) {
+ peer.prefixLimitWarned = true
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": peer.conf.Config.NeighborAddress,
+ "AddressFamily": family.AfiSafiName,
+ }).Warnf("prefix limit %d%% reached", pct)
+ }
+ if count > maxPrefixes {
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": peer.conf.Config.NeighborAddress,
+ "AddressFamily": family.AfiSafiName,
+ }).Warnf("prefix limit reached")
+ return nil, nil, bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_MAXIMUM_NUMBER_OF_PREFIXES_REACHED, nil)
+ }
+ }
+ }
paths := make([]*table.Path, 0, len(e.PathList))
eor := []bgp.RouteFamily{}
for _, path := range e.PathList {
@@ -254,9 +278,9 @@ func (peer *Peer) handleUpdate(e *FsmMsg) ([]*table.Path, []bgp.RouteFamily) {
paths = append(paths, path)
}
}
- return paths, eor
+ return paths, eor, nil
}
- return nil, nil
+ return nil, nil, nil
}
func (peer *Peer) startFSMHandler(incoming *channels.InfiniteChannel, stateCh chan *FsmMsg) {
diff --git a/server/server.go b/server/server.go
index af88f3ca..1b59402d 100644
--- a/server/server.go
+++ b/server/server.go
@@ -774,6 +774,7 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) []*SenderMsg {
} else {
drop = peer.configuredRFlist()
}
+ peer.prefixLimitWarned = false
peer.DropAll(drop)
msgs = server.dropPeerAllRoutes(peer, drop)
} else if peer.fsm.pConf.GracefulRestart.State.PeerRestarting && nextState == bgp.BGP_FSM_IDLE {
@@ -847,8 +848,10 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) []*SenderMsg {
case *bgp.MessageError:
return []*SenderMsg{newSenderMsg(peer, nil, bgp.NewBGPNotificationMessage(m.TypeCode, m.SubTypeCode, m.Data), false)}
case *bgp.BGPMessage:
- pathList, eor := peer.handleUpdate(e)
-
+ pathList, eor, notification := peer.handleUpdate(e)
+ if notification != nil {
+ return []*SenderMsg{newSenderMsg(peer, nil, notification, true)}
+ }
if m.Header.Type == bgp.BGP_MSG_UPDATE && server.watchers.watching(WATCHER_EVENT_UPDATE_MSG) {
_, y := peer.fsm.capMap[bgp.BGP_CAP_FOUR_OCTET_AS_NUMBER]
l, _ := peer.fsm.LocalHostPort()