github.com/osrg/gobgp@v2.0.0+incompatible/pkg/server/peer.go (about)

     1  // Copyright (C) 2014-2016 Nippon Telegraph and Telephone Corporation.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    12  // implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package server
    17  
    18  import (
    19  	"fmt"
    20  	"net"
    21  	"time"
    22  
    23  	"github.com/osrg/gobgp/internal/pkg/config"
    24  	"github.com/osrg/gobgp/internal/pkg/table"
    25  	"github.com/osrg/gobgp/pkg/packet/bgp"
    26  
    27  	"github.com/eapache/channels"
    28  	log "github.com/sirupsen/logrus"
    29  )
    30  
    31  const (
    32  	flopThreshold = time.Second * 30
    33  )
    34  
    35  var minConnectRetry = 10
    36  
    37  type peerGroup struct {
    38  	Conf             *config.PeerGroup
    39  	members          map[string]config.Neighbor
    40  	dynamicNeighbors map[string]*config.DynamicNeighbor
    41  }
    42  
    43  func newPeerGroup(c *config.PeerGroup) *peerGroup {
    44  	return &peerGroup{
    45  		Conf:             c,
    46  		members:          make(map[string]config.Neighbor),
    47  		dynamicNeighbors: make(map[string]*config.DynamicNeighbor),
    48  	}
    49  }
    50  
    51  func (pg *peerGroup) AddMember(c config.Neighbor) {
    52  	pg.members[c.State.NeighborAddress] = c
    53  }
    54  
    55  func (pg *peerGroup) DeleteMember(c config.Neighbor) {
    56  	delete(pg.members, c.State.NeighborAddress)
    57  }
    58  
    59  func (pg *peerGroup) AddDynamicNeighbor(c *config.DynamicNeighbor) {
    60  	pg.dynamicNeighbors[c.Config.Prefix] = c
    61  }
    62  
    63  func newDynamicPeer(g *config.Global, neighborAddress string, pg *config.PeerGroup, loc *table.TableManager, policy *table.RoutingPolicy) *peer {
    64  	conf := config.Neighbor{
    65  		Config: config.NeighborConfig{
    66  			PeerGroup: pg.Config.PeerGroupName,
    67  		},
    68  		State: config.NeighborState{
    69  			NeighborAddress: neighborAddress,
    70  		},
    71  		Transport: config.Transport{
    72  			Config: config.TransportConfig{
    73  				PassiveMode: true,
    74  			},
    75  		},
    76  	}
    77  	if err := config.OverwriteNeighborConfigWithPeerGroup(&conf, pg); err != nil {
    78  		log.WithFields(log.Fields{
    79  			"Topic": "Peer",
    80  			"Key":   neighborAddress,
    81  		}).Debugf("Can't overwrite neighbor config: %s", err)
    82  		return nil
    83  	}
    84  	if err := config.SetDefaultNeighborConfigValues(&conf, pg, g); err != nil {
    85  		log.WithFields(log.Fields{
    86  			"Topic": "Peer",
    87  			"Key":   neighborAddress,
    88  		}).Debugf("Can't set default config: %s", err)
    89  		return nil
    90  	}
    91  	peer := newPeer(g, &conf, loc, policy)
    92  	peer.fsm.lock.Lock()
    93  	peer.fsm.state = bgp.BGP_FSM_ACTIVE
    94  	peer.fsm.lock.Unlock()
    95  	return peer
    96  }
    97  
    98  type peer struct {
    99  	tableId           string
   100  	fsm               *fsm
   101  	adjRibIn          *table.AdjRib
   102  	outgoing          *channels.InfiniteChannel
   103  	policy            *table.RoutingPolicy
   104  	localRib          *table.TableManager
   105  	prefixLimitWarned map[bgp.RouteFamily]bool
   106  	llgrEndChs        []chan struct{}
   107  }
   108  
   109  func newPeer(g *config.Global, conf *config.Neighbor, loc *table.TableManager, policy *table.RoutingPolicy) *peer {
   110  	peer := &peer{
   111  		outgoing:          channels.NewInfiniteChannel(),
   112  		localRib:          loc,
   113  		policy:            policy,
   114  		fsm:               newFSM(g, conf, policy),
   115  		prefixLimitWarned: make(map[bgp.RouteFamily]bool),
   116  	}
   117  	if peer.isRouteServerClient() {
   118  		peer.tableId = conf.State.NeighborAddress
   119  	} else {
   120  		peer.tableId = table.GLOBAL_RIB_NAME
   121  	}
   122  	rfs, _ := config.AfiSafis(conf.AfiSafis).ToRfList()
   123  	peer.adjRibIn = table.NewAdjRib(rfs)
   124  	return peer
   125  }
   126  
   127  func (peer *peer) AS() uint32 {
   128  	peer.fsm.lock.RLock()
   129  	defer peer.fsm.lock.RUnlock()
   130  	return peer.fsm.pConf.State.PeerAs
   131  }
   132  
   133  func (peer *peer) ID() string {
   134  	peer.fsm.lock.RLock()
   135  	defer peer.fsm.lock.RUnlock()
   136  	return peer.fsm.pConf.State.NeighborAddress
   137  }
   138  
   139  func (peer *peer) TableID() string {
   140  	return peer.tableId
   141  }
   142  
   143  func (peer *peer) isIBGPPeer() bool {
   144  	peer.fsm.lock.RLock()
   145  	defer peer.fsm.lock.RUnlock()
   146  	return peer.fsm.pConf.State.PeerType == config.PEER_TYPE_INTERNAL
   147  }
   148  
   149  func (peer *peer) isRouteServerClient() bool {
   150  	peer.fsm.lock.RLock()
   151  	defer peer.fsm.lock.RUnlock()
   152  	return peer.fsm.pConf.RouteServer.Config.RouteServerClient
   153  }
   154  
   155  func (peer *peer) isRouteReflectorClient() bool {
   156  	peer.fsm.lock.RLock()
   157  	defer peer.fsm.lock.RUnlock()
   158  	return peer.fsm.pConf.RouteReflector.Config.RouteReflectorClient
   159  }
   160  
   161  func (peer *peer) isGracefulRestartEnabled() bool {
   162  	peer.fsm.lock.RLock()
   163  	defer peer.fsm.lock.RUnlock()
   164  	return peer.fsm.pConf.GracefulRestart.State.Enabled
   165  }
   166  
   167  func (peer *peer) getAddPathMode(family bgp.RouteFamily) bgp.BGPAddPathMode {
   168  	peer.fsm.lock.RLock()
   169  	defer peer.fsm.lock.RUnlock()
   170  	if mode, y := peer.fsm.rfMap[family]; y {
   171  		return mode
   172  	}
   173  	return bgp.BGP_ADD_PATH_NONE
   174  }
   175  
   176  func (peer *peer) isAddPathReceiveEnabled(family bgp.RouteFamily) bool {
   177  	return (peer.getAddPathMode(family) & bgp.BGP_ADD_PATH_RECEIVE) > 0
   178  }
   179  
   180  func (peer *peer) isAddPathSendEnabled(family bgp.RouteFamily) bool {
   181  	return (peer.getAddPathMode(family) & bgp.BGP_ADD_PATH_SEND) > 0
   182  }
   183  
   184  func (peer *peer) isDynamicNeighbor() bool {
   185  	peer.fsm.lock.RLock()
   186  	defer peer.fsm.lock.RUnlock()
   187  	return peer.fsm.pConf.Config.NeighborAddress == "" && peer.fsm.pConf.Config.NeighborInterface == ""
   188  }
   189  
   190  func (peer *peer) recvedAllEOR() bool {
   191  	peer.fsm.lock.RLock()
   192  	defer peer.fsm.lock.RUnlock()
   193  	for _, a := range peer.fsm.pConf.AfiSafis {
   194  		if s := a.MpGracefulRestart.State; s.Enabled && !s.EndOfRibReceived {
   195  			return false
   196  		}
   197  	}
   198  	return true
   199  }
   200  
   201  func (peer *peer) configuredRFlist() []bgp.RouteFamily {
   202  	peer.fsm.lock.RLock()
   203  	defer peer.fsm.lock.RUnlock()
   204  	rfs, _ := config.AfiSafis(peer.fsm.pConf.AfiSafis).ToRfList()
   205  	return rfs
   206  }
   207  
   208  func (peer *peer) negotiatedRFList() []bgp.RouteFamily {
   209  	peer.fsm.lock.RLock()
   210  	defer peer.fsm.lock.RUnlock()
   211  	l := make([]bgp.RouteFamily, 0, len(peer.fsm.rfMap))
   212  	for family := range peer.fsm.rfMap {
   213  		l = append(l, family)
   214  	}
   215  	return l
   216  }
   217  
   218  func (peer *peer) toGlobalFamilies(families []bgp.RouteFamily) []bgp.RouteFamily {
   219  	id := peer.ID()
   220  	peer.fsm.lock.RLock()
   221  	defer peer.fsm.lock.RUnlock()
   222  	if peer.fsm.pConf.Config.Vrf != "" {
   223  		fs := make([]bgp.RouteFamily, 0, len(families))
   224  		for _, f := range families {
   225  			switch f {
   226  			case bgp.RF_IPv4_UC:
   227  				fs = append(fs, bgp.RF_IPv4_VPN)
   228  			case bgp.RF_IPv6_UC:
   229  				fs = append(fs, bgp.RF_IPv6_VPN)
   230  			default:
   231  				log.WithFields(log.Fields{
   232  					"Topic":  "Peer",
   233  					"Key":    id,
   234  					"Family": f,
   235  					"VRF":    peer.fsm.pConf.Config.Vrf,
   236  				}).Warn("invalid family configured for neighbor with vrf")
   237  			}
   238  		}
   239  		families = fs
   240  	}
   241  	return families
   242  }
   243  
   244  func classifyFamilies(all, part []bgp.RouteFamily) ([]bgp.RouteFamily, []bgp.RouteFamily) {
   245  	a := []bgp.RouteFamily{}
   246  	b := []bgp.RouteFamily{}
   247  	for _, f := range all {
   248  		p := true
   249  		for _, g := range part {
   250  			if f == g {
   251  				p = false
   252  				a = append(a, f)
   253  				break
   254  			}
   255  		}
   256  		if p {
   257  			b = append(b, f)
   258  		}
   259  	}
   260  	return a, b
   261  }
   262  
   263  func (peer *peer) forwardingPreservedFamilies() ([]bgp.RouteFamily, []bgp.RouteFamily) {
   264  	peer.fsm.lock.RLock()
   265  	list := []bgp.RouteFamily{}
   266  	for _, a := range peer.fsm.pConf.AfiSafis {
   267  		if s := a.MpGracefulRestart.State; s.Enabled && s.Received {
   268  			list = append(list, a.State.Family)
   269  		}
   270  	}
   271  	peer.fsm.lock.RUnlock()
   272  	return classifyFamilies(peer.configuredRFlist(), list)
   273  }
   274  
   275  func (peer *peer) llgrFamilies() ([]bgp.RouteFamily, []bgp.RouteFamily) {
   276  	peer.fsm.lock.RLock()
   277  	list := []bgp.RouteFamily{}
   278  	for _, a := range peer.fsm.pConf.AfiSafis {
   279  		if a.LongLivedGracefulRestart.State.Enabled {
   280  			list = append(list, a.State.Family)
   281  		}
   282  	}
   283  	peer.fsm.lock.RUnlock()
   284  	return classifyFamilies(peer.configuredRFlist(), list)
   285  }
   286  
   287  func (peer *peer) isLLGREnabledFamily(family bgp.RouteFamily) bool {
   288  	peer.fsm.lock.RLock()
   289  	llgrEnabled := peer.fsm.pConf.GracefulRestart.Config.LongLivedEnabled
   290  	peer.fsm.lock.RUnlock()
   291  	if !llgrEnabled {
   292  		return false
   293  	}
   294  	fs, _ := peer.llgrFamilies()
   295  	for _, f := range fs {
   296  		if f == family {
   297  			return true
   298  		}
   299  	}
   300  	return false
   301  }
   302  
   303  func (peer *peer) llgrRestartTime(family bgp.RouteFamily) uint32 {
   304  	peer.fsm.lock.RLock()
   305  	defer peer.fsm.lock.RUnlock()
   306  	for _, a := range peer.fsm.pConf.AfiSafis {
   307  		if a.State.Family == family {
   308  			return a.LongLivedGracefulRestart.State.PeerRestartTime
   309  		}
   310  	}
   311  	return 0
   312  }
   313  
   314  func (peer *peer) llgrRestartTimerExpired(family bgp.RouteFamily) bool {
   315  	peer.fsm.lock.RLock()
   316  	defer peer.fsm.lock.RUnlock()
   317  	all := true
   318  	for _, a := range peer.fsm.pConf.AfiSafis {
   319  		if a.State.Family == family {
   320  			a.LongLivedGracefulRestart.State.PeerRestartTimerExpired = true
   321  		}
   322  		s := a.LongLivedGracefulRestart.State
   323  		if s.Received && !s.PeerRestartTimerExpired {
   324  			all = false
   325  		}
   326  	}
   327  	return all
   328  }
   329  
   330  func (peer *peer) markLLGRStale(fs []bgp.RouteFamily) []*table.Path {
   331  	paths := peer.adjRibIn.PathList(fs, true)
   332  	for i, p := range paths {
   333  		doStale := true
   334  		for _, c := range p.GetCommunities() {
   335  			if c == uint32(bgp.COMMUNITY_NO_LLGR) {
   336  				doStale = false
   337  				p = p.Clone(true)
   338  				break
   339  			}
   340  		}
   341  		if doStale {
   342  			p = p.Clone(false)
   343  			p.SetCommunities([]uint32{uint32(bgp.COMMUNITY_LLGR_STALE)}, false)
   344  		}
   345  		paths[i] = p
   346  	}
   347  	return paths
   348  }
   349  
   350  func (peer *peer) stopPeerRestarting() {
   351  	peer.fsm.lock.Lock()
   352  	defer peer.fsm.lock.Unlock()
   353  	peer.fsm.pConf.GracefulRestart.State.PeerRestarting = false
   354  	for _, ch := range peer.llgrEndChs {
   355  		close(ch)
   356  	}
   357  	peer.llgrEndChs = make([]chan struct{}, 0)
   358  
   359  }
   360  
   361  func (peer *peer) filterPathFromSourcePeer(path, old *table.Path) *table.Path {
   362  	if peer.ID() != path.GetSource().Address.String() {
   363  		return path
   364  	}
   365  
   366  	// Note: Multiple paths having the same prefix could exist the withdrawals
   367  	// list in the case of Route Server setup with import policies modifying
   368  	// paths. In such case, gobgp sends duplicated update messages; withdraw
   369  	// messages for the same prefix.
   370  	if !peer.isRouteServerClient() {
   371  		if peer.isRouteReflectorClient() && path.GetRouteFamily() == bgp.RF_RTC_UC {
   372  			// When the peer is a Route Reflector client and the given path
   373  			// contains the Route Tartget Membership NLRI, the path should not
   374  			// be withdrawn in order to signal the client to distribute routes
   375  			// with the specific RT to Route Reflector.
   376  			return path
   377  		} else if !path.IsWithdraw && old != nil && old.GetSource().Address.String() != peer.ID() {
   378  			// Say, peer A and B advertized same prefix P, and best path
   379  			// calculation chose a path from B as best. When B withdraws prefix
   380  			// P, best path calculation chooses the path from A as best. For
   381  			// peers other than A, this path should be advertised (as implicit
   382  			// withdrawal). However for A, we should advertise the withdrawal
   383  			// path. Thing is same when peer A and we advertized prefix P (as
   384  			// local route), then, we withdraws the prefix.
   385  			return old.Clone(true)
   386  		}
   387  	}
   388  	log.WithFields(log.Fields{
   389  		"Topic": "Peer",
   390  		"Key":   peer.ID(),
   391  		"Data":  path,
   392  	}).Debug("From me, ignore.")
   393  	return nil
   394  }
   395  
   396  func (peer *peer) doPrefixLimit(k bgp.RouteFamily, c *config.PrefixLimitConfig) *bgp.BGPMessage {
   397  	if maxPrefixes := int(c.MaxPrefixes); maxPrefixes > 0 {
   398  		count := peer.adjRibIn.Count([]bgp.RouteFamily{k})
   399  		pct := int(c.ShutdownThresholdPct)
   400  		if pct > 0 && !peer.prefixLimitWarned[k] && count > (maxPrefixes*pct/100) {
   401  			peer.prefixLimitWarned[k] = true
   402  			log.WithFields(log.Fields{
   403  				"Topic":         "Peer",
   404  				"Key":           peer.ID(),
   405  				"AddressFamily": k.String(),
   406  			}).Warnf("prefix limit %d%% reached", pct)
   407  		}
   408  		if count > maxPrefixes {
   409  			log.WithFields(log.Fields{
   410  				"Topic":         "Peer",
   411  				"Key":           peer.ID(),
   412  				"AddressFamily": k.String(),
   413  			}).Warnf("prefix limit reached")
   414  			return bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_MAXIMUM_NUMBER_OF_PREFIXES_REACHED, nil)
   415  		}
   416  	}
   417  	return nil
   418  
   419  }
   420  
   421  func (peer *peer) updatePrefixLimitConfig(c []config.AfiSafi) error {
   422  	peer.fsm.lock.RLock()
   423  	x := peer.fsm.pConf.AfiSafis
   424  	peer.fsm.lock.RUnlock()
   425  	y := c
   426  	if len(x) != len(y) {
   427  		return fmt.Errorf("changing supported afi-safi is not allowed")
   428  	}
   429  	m := make(map[bgp.RouteFamily]config.PrefixLimitConfig)
   430  	for _, e := range x {
   431  		m[e.State.Family] = e.PrefixLimit.Config
   432  	}
   433  	for _, e := range y {
   434  		if p, ok := m[e.State.Family]; !ok {
   435  			return fmt.Errorf("changing supported afi-safi is not allowed")
   436  		} else if !p.Equal(&e.PrefixLimit.Config) {
   437  			log.WithFields(log.Fields{
   438  				"Topic":                   "Peer",
   439  				"Key":                     peer.ID(),
   440  				"AddressFamily":           e.Config.AfiSafiName,
   441  				"OldMaxPrefixes":          p.MaxPrefixes,
   442  				"NewMaxPrefixes":          e.PrefixLimit.Config.MaxPrefixes,
   443  				"OldShutdownThresholdPct": p.ShutdownThresholdPct,
   444  				"NewShutdownThresholdPct": e.PrefixLimit.Config.ShutdownThresholdPct,
   445  			}).Warnf("update prefix limit configuration")
   446  			peer.prefixLimitWarned[e.State.Family] = false
   447  			if msg := peer.doPrefixLimit(e.State.Family, &e.PrefixLimit.Config); msg != nil {
   448  				sendfsmOutgoingMsg(peer, nil, msg, true)
   449  			}
   450  		}
   451  	}
   452  	peer.fsm.lock.Lock()
   453  	peer.fsm.pConf.AfiSafis = c
   454  	peer.fsm.lock.Unlock()
   455  	return nil
   456  }
   457  
   458  func (peer *peer) handleUpdate(e *fsmMsg) ([]*table.Path, []bgp.RouteFamily, *bgp.BGPMessage) {
   459  	m := e.MsgData.(*bgp.BGPMessage)
   460  	update := m.Body.(*bgp.BGPUpdate)
   461  	log.WithFields(log.Fields{
   462  		"Topic":       "Peer",
   463  		"Key":         peer.fsm.pConf.State.NeighborAddress,
   464  		"nlri":        update.NLRI,
   465  		"withdrawals": update.WithdrawnRoutes,
   466  		"attributes":  update.PathAttributes,
   467  	}).Debug("received update")
   468  	peer.fsm.lock.Lock()
   469  	peer.fsm.pConf.Timers.State.UpdateRecvTime = time.Now().Unix()
   470  	peer.fsm.lock.Unlock()
   471  	if len(e.PathList) > 0 {
   472  		paths := make([]*table.Path, 0, len(e.PathList))
   473  		eor := []bgp.RouteFamily{}
   474  		for _, path := range e.PathList {
   475  			if path.IsEOR() {
   476  				family := path.GetRouteFamily()
   477  				log.WithFields(log.Fields{
   478  					"Topic":         "Peer",
   479  					"Key":           peer.ID(),
   480  					"AddressFamily": family,
   481  				}).Debug("EOR received")
   482  				eor = append(eor, family)
   483  				continue
   484  			}
   485  			// RFC4271 9.1.2 Phase 2: Route Selection
   486  			//
   487  			// If the AS_PATH attribute of a BGP route contains an AS loop, the BGP
   488  			// route should be excluded from the Phase 2 decision function.
   489  			if aspath := path.GetAsPath(); aspath != nil {
   490  				peer.fsm.lock.RLock()
   491  				localAS := peer.fsm.peerInfo.LocalAS
   492  				allowOwnAS := int(peer.fsm.pConf.AsPathOptions.Config.AllowOwnAs)
   493  				peer.fsm.lock.RUnlock()
   494  				if hasOwnASLoop(localAS, allowOwnAS, aspath) {
   495  					path.SetAsLooped(true)
   496  					continue
   497  				}
   498  			}
   499  			// RFC4456 8. Avoiding Routing Information Loops
   500  			// A router that recognizes the ORIGINATOR_ID attribute SHOULD
   501  			// ignore a route received with its BGP Identifier as the ORIGINATOR_ID.
   502  			isIBGPPeer := peer.isIBGPPeer()
   503  			peer.fsm.lock.RLock()
   504  			routerId := peer.fsm.gConf.Config.RouterId
   505  			peer.fsm.lock.RUnlock()
   506  			if isIBGPPeer {
   507  				if id := path.GetOriginatorID(); routerId == id.String() {
   508  					log.WithFields(log.Fields{
   509  						"Topic":        "Peer",
   510  						"Key":          peer.ID(),
   511  						"OriginatorID": id,
   512  						"Data":         path,
   513  					}).Debug("Originator ID is mine, ignore")
   514  					continue
   515  				}
   516  			}
   517  			paths = append(paths, path)
   518  		}
   519  		peer.adjRibIn.Update(e.PathList)
   520  		peer.fsm.lock.RLock()
   521  		peerAfiSafis := peer.fsm.pConf.AfiSafis
   522  		peer.fsm.lock.RUnlock()
   523  		for _, af := range peerAfiSafis {
   524  			if msg := peer.doPrefixLimit(af.State.Family, &af.PrefixLimit.Config); msg != nil {
   525  				return nil, nil, msg
   526  			}
   527  		}
   528  		return paths, eor, nil
   529  	}
   530  	return nil, nil, nil
   531  }
   532  
   533  func (peer *peer) startFSMHandler(incoming *channels.InfiniteChannel, stateCh chan *fsmMsg) {
   534  	handler := newFSMHandler(peer.fsm, incoming, stateCh, peer.outgoing)
   535  	peer.fsm.lock.Lock()
   536  	peer.fsm.h = handler
   537  	peer.fsm.lock.Unlock()
   538  }
   539  
   540  func (peer *peer) StaleAll(rfList []bgp.RouteFamily) []*table.Path {
   541  	return peer.adjRibIn.StaleAll(rfList)
   542  }
   543  
   544  func (peer *peer) PassConn(conn *net.TCPConn) {
   545  	select {
   546  	case peer.fsm.connCh <- conn:
   547  	default:
   548  		conn.Close()
   549  		log.WithFields(log.Fields{
   550  			"Topic": "Peer",
   551  			"Key":   peer.ID(),
   552  		}).Warn("accepted conn is closed to avoid be blocked")
   553  	}
   554  }
   555  
   556  func (peer *peer) DropAll(rfList []bgp.RouteFamily) {
   557  	peer.adjRibIn.Drop(rfList)
   558  }
   559  
   560  func (peer *peer) stopFSM() error {
   561  	failed := false
   562  	peer.fsm.lock.RLock()
   563  	addr := peer.fsm.pConf.State.NeighborAddress
   564  	state := peer.fsm.state
   565  	peer.fsm.lock.RUnlock()
   566  	t1 := time.AfterFunc(time.Minute*5, func() {
   567  		log.WithFields(log.Fields{
   568  			"Topic": "Peer",
   569  		}).Warnf("Failed to free the fsm.h.t for %s", addr)
   570  		failed = true
   571  	})
   572  	peer.fsm.h.ctxCancel()
   573  	peer.fsm.h.wg.Wait()
   574  	t1.Stop()
   575  	if !failed {
   576  		log.WithFields(log.Fields{
   577  			"Topic": "Peer",
   578  			"Key":   addr,
   579  			"State": state,
   580  		}).Debug("freed fsm.h.t")
   581  		cleanInfiniteChannel(peer.outgoing)
   582  	}
   583  	return fmt.Errorf("Failed to free FSM for %s", addr)
   584  }