diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2016-04-06 23:33:02 +0900 |
---|---|---|
committer | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2016-04-10 23:58:17 +0000 |
commit | 59420a4c4623492085348e07fb78eaae51182782 (patch) | |
tree | ea4ab75a0b39ca4ff049924edec59d7247ca0759 /server | |
parent | aa79a4de21772f556450cfe7e55e6f400c3f9dec (diff) |
server: support prefix-limit
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
Diffstat (limited to 'server')
-rw-r--r-- | server/fsm.go | 16 | ||||
-rw-r--r-- | server/peer.go | 48 | ||||
-rw-r--r-- | server/server.go | 7 |
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() |