diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2018-05-10 09:00:50 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2018-05-10 23:13:21 +0900 |
commit | 691d80e5d160b82c8b4dd1d83c959ecdffad318f (patch) | |
tree | 52d9a238bde9dd525c63bf15b8ede84ab85d56fe /server/peer.go | |
parent | 5fc0ac2731ebbe0e812d493e837007068989faa7 (diff) |
make Path objects in rib read-only
Now you can read Path objects in rib safely. Nobody modifies
them. GetRib() API doesn't need to clone the objects. With full
routes, this avoid allocating temporary huge memory.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Diffstat (limited to 'server/peer.go')
-rw-r--r-- | server/peer.go | 231 |
1 files changed, 0 insertions, 231 deletions
diff --git a/server/peer.go b/server/peer.go index 3bdd9965..80fc6a1b 100644 --- a/server/peer.go +++ b/server/peer.go @@ -313,105 +313,6 @@ func (peer *Peer) getAccepted(rfList []bgp.RouteFamily) []*table.Path { return peer.adjRibIn.PathList(rfList, true) } -func (peer *Peer) filterpath(path, old *table.Path) *table.Path { - // Special handling for RTM NLRI. - if path != nil && path.GetRouteFamily() == bgp.RF_RTC_UC && !path.IsWithdraw { - // If the given "path" is locally generated and the same with "old", we - // assumes "path" was already sent before. This assumption avoids the - // infinite UPDATE loop between Route Reflector and its clients. - if path.IsLocal() && path == old { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": peer.fsm.pConf.State.NeighborAddress, - "Path": path, - }).Debug("given rtm nlri is already sent, skipping to advertise") - return nil - } - - if old != nil && old.IsLocal() { - // We assumes VRF with the specific RT is deleted. - path = old.Clone(true) - } else if peer.isRouteReflectorClient() { - // We need to send the path even if the peer is originator of the - // path in order to signal that the client should distribute route - // with the given RT. - } else { - // We send a path even if it is not the best path. See comments in - // (*Destination) GetChanges(). - dst := peer.localRib.GetDestination(path) - path = nil - for _, p := range dst.GetKnownPathList(peer.TableID(), peer.AS()) { - // Just take care not to send back. - if peer.ID() != p.GetSource().Address.String() { - path = p - break - } - } - } - } - - // only allow vpnv4 and vpnv6 paths to be advertised to VRFed neighbors. - // also check we can import this path using table.CanImportToVrf() - // if we can, make it local path by calling (*Path).ToLocal() - if path != nil && peer.fsm.pConf.Config.Vrf != "" { - if f := path.GetRouteFamily(); f != bgp.RF_IPv4_VPN && f != bgp.RF_IPv6_VPN { - return nil - } - vrf := peer.localRib.Vrfs[peer.fsm.pConf.Config.Vrf] - if table.CanImportToVrf(vrf, path) { - path = path.ToLocal() - } else { - return nil - } - } - - // replace-peer-as handling - if path != nil && !path.IsWithdraw && peer.fsm.pConf.AsPathOptions.State.ReplacePeerAs { - path = path.ReplaceAS(peer.fsm.pConf.Config.LocalAs, peer.fsm.pConf.Config.PeerAs) - } - - if path = filterpath(peer, path, old); path == nil { - return nil - } - - path = table.UpdatePathAttrs(peer.fsm.gConf, peer.fsm.pConf, peer.fsm.peerInfo, path) - - options := &table.PolicyOptions{ - Info: peer.fsm.peerInfo, - } - path = peer.policy.ApplyPolicy(peer.TableID(), table.POLICY_DIRECTION_EXPORT, path, options) - // When 'path' is filtered (path == nil), check 'old' has been sent to this peer. - // If it has, send withdrawal to the peer. - if path == nil && old != nil { - o := peer.policy.ApplyPolicy(peer.TableID(), table.POLICY_DIRECTION_EXPORT, old, options) - if o != nil { - path = old.Clone(true) - } - } - - // draft-uttaro-idr-bgp-persistence-02 - // 4.3. Processing LLGR_STALE Routes - // - // The route SHOULD NOT be advertised to any neighbor from which the - // Long-lived Graceful Restart Capability has not been received. The - // exception is described in the Optional Partial Deployment - // Procedure section (Section 4.7). Note that this requirement - // implies that such routes should be withdrawn from any such neighbor. - if path != nil && !path.IsWithdraw && !peer.isLLGREnabledFamily(path.GetRouteFamily()) && path.IsLLGRStale() { - // we send unnecessary withdrawn even if we didn't - // sent the route. - path = path.Clone(true) - } - - // remove local-pref attribute - // we should do this after applying export policy since policy may - // set local-preference - if path != nil && !peer.isIBGPPeer() && !peer.isRouteServerClient() { - path.RemoveLocalPref() - } - return path -} - func (peer *Peer) filterPathFromSourcePeer(path, old *table.Path) *table.Path { if peer.ID() != path.GetSource().Address.String() { return path @@ -447,86 +348,6 @@ func (peer *Peer) filterPathFromSourcePeer(path, old *table.Path) *table.Path { return nil } -func (peer *Peer) getBestFromLocal(rfList []bgp.RouteFamily) ([]*table.Path, []*table.Path) { - pathList := []*table.Path{} - filtered := []*table.Path{} - for _, family := range peer.toGlobalFamilies(rfList) { - pl := func() []*table.Path { - if peer.isAddPathSendEnabled(family) { - return peer.localRib.GetPathList(peer.TableID(), peer.AS(), []bgp.RouteFamily{family}) - } - return peer.localRib.GetBestPathList(peer.TableID(), peer.AS(), []bgp.RouteFamily{family}) - }() - for _, path := range pl { - if p := peer.filterpath(path, nil); p != nil { - pathList = append(pathList, p) - } else { - filtered = append(filtered, path) - } - } - } - if peer.isGracefulRestartEnabled() { - for _, family := range rfList { - pathList = append(pathList, table.NewEOR(family)) - } - } - return pathList, filtered -} - -func (peer *Peer) processOutgoingPaths(paths, olds []*table.Path) []*table.Path { - if peer.fsm.state != bgp.BGP_FSM_ESTABLISHED { - return nil - } - if peer.fsm.pConf.GracefulRestart.State.LocalRestarting { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": peer.fsm.pConf.State.NeighborAddress, - }).Debug("now syncing, suppress sending updates") - return nil - } - - outgoing := make([]*table.Path, 0, len(paths)) - - for idx, path := range paths { - var old *table.Path - if olds != nil { - old = olds[idx] - } - if p := peer.filterpath(path, old); p != nil { - outgoing = append(outgoing, p) - } - } - return outgoing -} - -func (peer *Peer) handleRouteRefresh(e *FsmMsg) []*table.Path { - m := e.MsgData.(*bgp.BGPMessage) - rr := m.Body.(*bgp.BGPRouteRefresh) - rf := bgp.AfiSafiToRouteFamily(rr.AFI, rr.SAFI) - if _, ok := peer.fsm.rfMap[rf]; !ok { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": peer.ID(), - "Data": rf, - }).Warn("Route family isn't supported") - return nil - } - if _, ok := peer.fsm.capMap[bgp.BGP_CAP_ROUTE_REFRESH]; !ok { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": peer.ID(), - }).Warn("ROUTE_REFRESH received but the capability wasn't advertised") - return nil - } - rfList := []bgp.RouteFamily{rf} - accepted, filtered := peer.getBestFromLocal(rfList) - for _, path := range filtered { - path.IsWithdraw = true - accepted = append(accepted, path) - } - return accepted -} - func (peer *Peer) doPrefixLimit(k bgp.RouteFamily, c *config.PrefixLimitConfig) *bgp.BGPMessage { if maxPrefixes := int(c.MaxPrefixes); maxPrefixes > 0 { count := peer.adjRibIn.Count([]bgp.RouteFamily{k}) @@ -652,58 +473,6 @@ func (peer *Peer) PassConn(conn *net.TCPConn) { } } -func (peer *Peer) ToConfig(getAdvertised bool) *config.Neighbor { - // create copy which can be access to without mutex - conf := *peer.fsm.pConf - - conf.AfiSafis = make([]config.AfiSafi, len(peer.fsm.pConf.AfiSafis)) - for i, af := range peer.fsm.pConf.AfiSafis { - conf.AfiSafis[i] = af - conf.AfiSafis[i].AddPaths.State.Receive = peer.isAddPathReceiveEnabled(af.State.Family) - if peer.isAddPathSendEnabled(af.State.Family) { - conf.AfiSafis[i].AddPaths.State.SendMax = af.AddPaths.State.SendMax - } else { - conf.AfiSafis[i].AddPaths.State.SendMax = 0 - } - } - - remoteCap := make([]bgp.ParameterCapabilityInterface, 0, len(peer.fsm.capMap)) - for _, caps := range peer.fsm.capMap { - for _, m := range caps { - // need to copy all values here - buf, _ := m.Serialize() - c, _ := bgp.DecodeCapability(buf) - remoteCap = append(remoteCap, c) - } - } - conf.State.RemoteCapabilityList = remoteCap - conf.State.LocalCapabilityList = capabilitiesFromConfig(peer.fsm.pConf) - - conf.State.SessionState = config.IntToSessionStateMap[int(peer.fsm.state)] - conf.State.AdminState = config.IntToAdminStateMap[int(peer.fsm.adminState)] - - if peer.fsm.state == bgp.BGP_FSM_ESTABLISHED { - rfList := peer.configuredRFlist() - if getAdvertised { - pathList, filtered := peer.getBestFromLocal(rfList) - conf.State.AdjTable.Advertised = uint32(len(pathList)) - conf.State.AdjTable.Filtered = uint32(len(filtered)) - } else { - conf.State.AdjTable.Advertised = 0 - } - conf.State.AdjTable.Received = uint32(peer.adjRibIn.Count(rfList)) - conf.State.AdjTable.Accepted = uint32(peer.adjRibIn.Accepted(rfList)) - - conf.Transport.State.LocalAddress, conf.Transport.State.LocalPort = peer.fsm.LocalHostPort() - _, conf.Transport.State.RemotePort = peer.fsm.RemoteHostPort() - buf, _ := peer.fsm.recvOpen.Serialize() - // need to copy all values here - conf.State.ReceivedOpenMessage, _ = bgp.ParseBGPMessage(buf) - conf.State.RemoteRouterId = peer.fsm.peerInfo.ID.To4().String() - } - return &conf -} - func (peer *Peer) DropAll(rfList []bgp.RouteFamily) { peer.adjRibIn.Drop(rfList) } |