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

     1  // Copyright (C) 2014 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  	"context"
    20  	"fmt"
    21  	"io"
    22  	"math/rand"
    23  	"net"
    24  	"strconv"
    25  	"sync"
    26  	"syscall"
    27  	"time"
    28  
    29  	"github.com/eapache/channels"
    30  	"github.com/osrg/gobgp/internal/pkg/config"
    31  	"github.com/osrg/gobgp/internal/pkg/table"
    32  	"github.com/osrg/gobgp/pkg/packet/bgp"
    33  	"github.com/osrg/gobgp/pkg/packet/bmp"
    34  
    35  	log "github.com/sirupsen/logrus"
    36  )
    37  
    38  type peerDownReason int
    39  
    40  const (
    41  	peerDownByLocal peerDownReason = iota
    42  	peerDownByLocalWithoutNotification
    43  	peerDownByRemote
    44  	peerDownByRemoteWithoutNotification
    45  )
    46  
    47  type fsmStateReasonType uint8
    48  
    49  const (
    50  	fsmDying fsmStateReasonType = iota
    51  	fsmAdminDown
    52  	fsmReadFailed
    53  	fsmWriteFailed
    54  	fsmNotificationSent
    55  	fsmNotificationRecv
    56  	fsmHoldTimerExpired
    57  	fsmIdleTimerExpired
    58  	fsmRestartTimerExpired
    59  	fsmGracefulRestart
    60  	fsmInvalidMsg
    61  	fsmNewConnection
    62  	fsmOpenMsgReceived
    63  	fsmOpenMsgNegotiated
    64  	fsmHardReset
    65  )
    66  
    67  type fsmStateReason struct {
    68  	Type            fsmStateReasonType
    69  	peerDownReason  peerDownReason
    70  	BGPNotification *bgp.BGPMessage
    71  	Data            []byte
    72  }
    73  
    74  func newfsmStateReason(typ fsmStateReasonType, notif *bgp.BGPMessage, data []byte) *fsmStateReason {
    75  	var reasonCode peerDownReason
    76  	switch typ {
    77  	case fsmDying, fsmInvalidMsg, fsmNotificationSent, fsmHoldTimerExpired, fsmIdleTimerExpired, fsmRestartTimerExpired:
    78  		reasonCode = peerDownByLocal
    79  	case fsmAdminDown:
    80  		reasonCode = peerDownByLocalWithoutNotification
    81  	case fsmNotificationRecv, fsmGracefulRestart, fsmHardReset:
    82  		reasonCode = peerDownByRemote
    83  	case fsmReadFailed, fsmWriteFailed:
    84  		reasonCode = peerDownByRemoteWithoutNotification
    85  	}
    86  	return &fsmStateReason{
    87  		Type:            typ,
    88  		peerDownReason:  reasonCode,
    89  		BGPNotification: notif,
    90  		Data:            data,
    91  	}
    92  }
    93  
    94  func (r fsmStateReason) String() string {
    95  	switch r.Type {
    96  	case fsmDying:
    97  		return "dying"
    98  	case fsmAdminDown:
    99  		return "admin-down"
   100  	case fsmReadFailed:
   101  		return "read-failed"
   102  	case fsmWriteFailed:
   103  		return "write-failed"
   104  	case fsmNotificationSent:
   105  		body := r.BGPNotification.Body.(*bgp.BGPNotification)
   106  		return fmt.Sprintf("notification-sent %s", bgp.NewNotificationErrorCode(body.ErrorCode, body.ErrorSubcode).String())
   107  	case fsmNotificationRecv:
   108  		body := r.BGPNotification.Body.(*bgp.BGPNotification)
   109  		return fmt.Sprintf("notification-received %s", bgp.NewNotificationErrorCode(body.ErrorCode, body.ErrorSubcode).String())
   110  	case fsmHoldTimerExpired:
   111  		return "hold-timer-expired"
   112  	case fsmIdleTimerExpired:
   113  		return "idle-hold-timer-expired"
   114  	case fsmRestartTimerExpired:
   115  		return "restart-timer-expired"
   116  	case fsmGracefulRestart:
   117  		return "graceful-restart"
   118  	case fsmInvalidMsg:
   119  		return "invalid-msg"
   120  	case fsmNewConnection:
   121  		return "new-connection"
   122  	case fsmOpenMsgReceived:
   123  		return "open-msg-received"
   124  	case fsmOpenMsgNegotiated:
   125  		return "open-msg-negotiated"
   126  	case fsmHardReset:
   127  		return "hard-reset"
   128  	default:
   129  		return "unknown"
   130  	}
   131  }
   132  
   133  type fsmMsgType int
   134  
   135  const (
   136  	_ fsmMsgType = iota
   137  	fsmMsgStateChange
   138  	fsmMsgBGPMessage
   139  	fsmMsgRouteRefresh
   140  )
   141  
   142  type fsmMsg struct {
   143  	MsgType     fsmMsgType
   144  	MsgSrc      string
   145  	MsgData     interface{}
   146  	StateReason *fsmStateReason
   147  	PathList    []*table.Path
   148  	timestamp   time.Time
   149  	payload     []byte
   150  	Version     uint
   151  }
   152  
   153  type fsmOutgoingMsg struct {
   154  	Paths        []*table.Path
   155  	Notification *bgp.BGPMessage
   156  	StayIdle     bool
   157  }
   158  
   159  const (
   160  	holdtimeOpensent = 240
   161  	holdtimeIdle     = 5
   162  )
   163  
   164  type adminState int
   165  
   166  const (
   167  	adminStateUp adminState = iota
   168  	adminStateDown
   169  	adminStatePfxCt
   170  )
   171  
   172  func (s adminState) String() string {
   173  	switch s {
   174  	case adminStateUp:
   175  		return "adminStateUp"
   176  	case adminStateDown:
   177  		return "adminStateDown"
   178  	case adminStatePfxCt:
   179  		return "adminStatePfxCt"
   180  	default:
   181  		return "Unknown"
   182  	}
   183  }
   184  
   185  type adminStateOperation struct {
   186  	State         adminState
   187  	Communication []byte
   188  }
   189  
   190  var fsmVersion uint
   191  
   192  type fsm struct {
   193  	gConf                *config.Global
   194  	pConf                *config.Neighbor
   195  	lock                 sync.RWMutex
   196  	state                bgp.FSMState
   197  	reason               *fsmStateReason
   198  	conn                 net.Conn
   199  	connCh               chan net.Conn
   200  	idleHoldTime         float64
   201  	opensentHoldTime     float64
   202  	adminState           adminState
   203  	adminStateCh         chan adminStateOperation
   204  	h                    *fsmHandler
   205  	rfMap                map[bgp.RouteFamily]bgp.BGPAddPathMode
   206  	capMap               map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface
   207  	recvOpen             *bgp.BGPMessage
   208  	peerInfo             *table.PeerInfo
   209  	policy               *table.RoutingPolicy
   210  	gracefulRestartTimer *time.Timer
   211  	twoByteAsTrans       bool
   212  	version              uint
   213  	marshallingOptions   *bgp.MarshallingOption
   214  }
   215  
   216  func (fsm *fsm) bgpMessageStateUpdate(MessageType uint8, isIn bool) {
   217  	fsm.lock.Lock()
   218  	defer fsm.lock.Unlock()
   219  	state := &fsm.pConf.State.Messages
   220  	timer := &fsm.pConf.Timers
   221  	if isIn {
   222  		state.Received.Total++
   223  	} else {
   224  		state.Sent.Total++
   225  	}
   226  	switch MessageType {
   227  	case bgp.BGP_MSG_OPEN:
   228  		if isIn {
   229  			state.Received.Open++
   230  		} else {
   231  			state.Sent.Open++
   232  		}
   233  	case bgp.BGP_MSG_UPDATE:
   234  		if isIn {
   235  			state.Received.Update++
   236  			timer.State.UpdateRecvTime = time.Now().Unix()
   237  		} else {
   238  			state.Sent.Update++
   239  		}
   240  	case bgp.BGP_MSG_NOTIFICATION:
   241  		if isIn {
   242  			state.Received.Notification++
   243  		} else {
   244  			state.Sent.Notification++
   245  		}
   246  	case bgp.BGP_MSG_KEEPALIVE:
   247  		if isIn {
   248  			state.Received.Keepalive++
   249  		} else {
   250  			state.Sent.Keepalive++
   251  		}
   252  	case bgp.BGP_MSG_ROUTE_REFRESH:
   253  		if isIn {
   254  			state.Received.Refresh++
   255  		} else {
   256  			state.Sent.Refresh++
   257  		}
   258  	default:
   259  		if isIn {
   260  			state.Received.Discarded++
   261  		} else {
   262  			state.Sent.Discarded++
   263  		}
   264  	}
   265  }
   266  
   267  func (fsm *fsm) bmpStatsUpdate(statType uint16, increment int) {
   268  	fsm.lock.Lock()
   269  	defer fsm.lock.Unlock()
   270  	stats := &fsm.pConf.State.Messages.Received
   271  	switch statType {
   272  	// TODO
   273  	// Support other stat types.
   274  	case bmp.BMP_STAT_TYPE_WITHDRAW_UPDATE:
   275  		stats.WithdrawUpdate += uint32(increment)
   276  	case bmp.BMP_STAT_TYPE_WITHDRAW_PREFIX:
   277  		stats.WithdrawPrefix += uint32(increment)
   278  	}
   279  }
   280  
   281  func newFSM(gConf *config.Global, pConf *config.Neighbor, policy *table.RoutingPolicy) *fsm {
   282  	adminState := adminStateUp
   283  	if pConf.Config.AdminDown {
   284  		adminState = adminStateDown
   285  	}
   286  	pConf.State.SessionState = config.IntToSessionStateMap[int(bgp.BGP_FSM_IDLE)]
   287  	pConf.Timers.State.Downtime = time.Now().Unix()
   288  	fsmVersion++
   289  	fsm := &fsm{
   290  		gConf:                gConf,
   291  		pConf:                pConf,
   292  		state:                bgp.BGP_FSM_IDLE,
   293  		connCh:               make(chan net.Conn, 1),
   294  		opensentHoldTime:     float64(holdtimeOpensent),
   295  		adminState:           adminState,
   296  		adminStateCh:         make(chan adminStateOperation, 1),
   297  		rfMap:                make(map[bgp.RouteFamily]bgp.BGPAddPathMode),
   298  		capMap:               make(map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface),
   299  		peerInfo:             table.NewPeerInfo(gConf, pConf),
   300  		policy:               policy,
   301  		gracefulRestartTimer: time.NewTimer(time.Hour),
   302  		version:              fsmVersion,
   303  	}
   304  	fsm.gracefulRestartTimer.Stop()
   305  	return fsm
   306  }
   307  
   308  func (fsm *fsm) StateChange(nextState bgp.FSMState) {
   309  	fsm.lock.Lock()
   310  	defer fsm.lock.Unlock()
   311  
   312  	log.WithFields(log.Fields{
   313  		"Topic":  "Peer",
   314  		"Key":    fsm.pConf.State.NeighborAddress,
   315  		"old":    fsm.state.String(),
   316  		"new":    nextState.String(),
   317  		"reason": fsm.reason,
   318  	}).Debug("state changed")
   319  	fsm.state = nextState
   320  	switch nextState {
   321  	case bgp.BGP_FSM_ESTABLISHED:
   322  		fsm.pConf.Timers.State.Uptime = time.Now().Unix()
   323  		fsm.pConf.State.EstablishedCount++
   324  		// reset the state set by the previous session
   325  		fsm.twoByteAsTrans = false
   326  		if _, y := fsm.capMap[bgp.BGP_CAP_FOUR_OCTET_AS_NUMBER]; !y {
   327  			fsm.twoByteAsTrans = true
   328  			break
   329  		}
   330  		y := func() bool {
   331  			for _, c := range capabilitiesFromConfig(fsm.pConf) {
   332  				switch c.(type) {
   333  				case *bgp.CapFourOctetASNumber:
   334  					return true
   335  				}
   336  			}
   337  			return false
   338  		}()
   339  		if !y {
   340  			fsm.twoByteAsTrans = true
   341  		}
   342  	default:
   343  		fsm.pConf.Timers.State.Downtime = time.Now().Unix()
   344  	}
   345  }
   346  
   347  func hostport(addr net.Addr) (string, uint16) {
   348  	if addr != nil {
   349  		host, port, err := net.SplitHostPort(addr.String())
   350  		if err != nil {
   351  			return "", 0
   352  		}
   353  		p, _ := strconv.ParseUint(port, 10, 16)
   354  		return host, uint16(p)
   355  	}
   356  	return "", 0
   357  }
   358  
   359  func (fsm *fsm) RemoteHostPort() (string, uint16) {
   360  	return hostport(fsm.conn.RemoteAddr())
   361  
   362  }
   363  
   364  func (fsm *fsm) LocalHostPort() (string, uint16) {
   365  	return hostport(fsm.conn.LocalAddr())
   366  }
   367  
   368  func (fsm *fsm) sendNotificationFromErrorMsg(e *bgp.MessageError) (*bgp.BGPMessage, error) {
   369  	fsm.lock.RLock()
   370  	established := fsm.h != nil && fsm.h.conn != nil
   371  	fsm.lock.RUnlock()
   372  
   373  	if established {
   374  		m := bgp.NewBGPNotificationMessage(e.TypeCode, e.SubTypeCode, e.Data)
   375  		b, _ := m.Serialize()
   376  		_, err := fsm.h.conn.Write(b)
   377  		if err == nil {
   378  			fsm.bgpMessageStateUpdate(m.Header.Type, false)
   379  			fsm.h.sentNotification = m
   380  		}
   381  		fsm.h.conn.Close()
   382  		log.WithFields(log.Fields{
   383  			"Topic": "Peer",
   384  			"Key":   fsm.pConf.State.NeighborAddress,
   385  			"Data":  e,
   386  		}).Warn("sent notification")
   387  		return m, nil
   388  	}
   389  	return nil, fmt.Errorf("can't send notification to %s since TCP connection is not established", fsm.pConf.State.NeighborAddress)
   390  }
   391  
   392  func (fsm *fsm) sendNotification(code, subType uint8, data []byte, msg string) (*bgp.BGPMessage, error) {
   393  	e := bgp.NewMessageError(code, subType, data, msg)
   394  	return fsm.sendNotificationFromErrorMsg(e.(*bgp.MessageError))
   395  }
   396  
   397  type fsmHandler struct {
   398  	fsm              *fsm
   399  	conn             net.Conn
   400  	msgCh            *channels.InfiniteChannel
   401  	stateReasonCh    chan fsmStateReason
   402  	incoming         *channels.InfiniteChannel
   403  	stateCh          chan *fsmMsg
   404  	outgoing         *channels.InfiniteChannel
   405  	holdTimerResetCh chan bool
   406  	sentNotification *bgp.BGPMessage
   407  	ctx              context.Context
   408  	ctxCancel        context.CancelFunc
   409  	wg               *sync.WaitGroup
   410  }
   411  
   412  func newFSMHandler(fsm *fsm, incoming *channels.InfiniteChannel, stateCh chan *fsmMsg, outgoing *channels.InfiniteChannel) *fsmHandler {
   413  	ctx, cancel := context.WithCancel(context.Background())
   414  	h := &fsmHandler{
   415  		fsm:              fsm,
   416  		stateReasonCh:    make(chan fsmStateReason, 2),
   417  		incoming:         incoming,
   418  		stateCh:          stateCh,
   419  		outgoing:         outgoing,
   420  		holdTimerResetCh: make(chan bool, 2),
   421  		wg:               &sync.WaitGroup{},
   422  		ctx:              ctx,
   423  		ctxCancel:        cancel,
   424  	}
   425  	h.wg.Add(1)
   426  	go h.loop(ctx, h.wg)
   427  	return h
   428  }
   429  
   430  func (h *fsmHandler) idle(ctx context.Context) (bgp.FSMState, *fsmStateReason) {
   431  	fsm := h.fsm
   432  
   433  	fsm.lock.RLock()
   434  	idleHoldTimer := time.NewTimer(time.Second * time.Duration(fsm.idleHoldTime))
   435  	fsm.lock.RUnlock()
   436  
   437  	for {
   438  		select {
   439  		case <-ctx.Done():
   440  			return -1, newfsmStateReason(fsmDying, nil, nil)
   441  		case <-fsm.gracefulRestartTimer.C:
   442  			fsm.lock.RLock()
   443  			restarting := fsm.pConf.GracefulRestart.State.PeerRestarting
   444  			fsm.lock.RUnlock()
   445  
   446  			if restarting {
   447  				fsm.lock.RLock()
   448  				log.WithFields(log.Fields{
   449  					"Topic": "Peer",
   450  					"Key":   fsm.pConf.State.NeighborAddress,
   451  					"State": fsm.state.String(),
   452  				}).Warn("graceful restart timer expired")
   453  				fsm.lock.RUnlock()
   454  				return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmRestartTimerExpired, nil, nil)
   455  			}
   456  		case conn, ok := <-fsm.connCh:
   457  			if !ok {
   458  				break
   459  			}
   460  			conn.Close()
   461  			fsm.lock.RLock()
   462  			log.WithFields(log.Fields{
   463  				"Topic": "Peer",
   464  				"Key":   fsm.pConf.State.NeighborAddress,
   465  				"State": fsm.state.String(),
   466  			}).Warn("Closed an accepted connection")
   467  			fsm.lock.RUnlock()
   468  
   469  		case <-idleHoldTimer.C:
   470  			fsm.lock.RLock()
   471  			adminStateUp := fsm.adminState == adminStateUp
   472  			fsm.lock.RUnlock()
   473  
   474  			if adminStateUp {
   475  				fsm.lock.Lock()
   476  				log.WithFields(log.Fields{
   477  					"Topic":    "Peer",
   478  					"Key":      fsm.pConf.State.NeighborAddress,
   479  					"Duration": fsm.idleHoldTime,
   480  				}).Debug("IdleHoldTimer expired")
   481  				fsm.idleHoldTime = holdtimeIdle
   482  				fsm.lock.Unlock()
   483  				return bgp.BGP_FSM_ACTIVE, newfsmStateReason(fsmIdleTimerExpired, nil, nil)
   484  
   485  			} else {
   486  				log.WithFields(log.Fields{"Topic": "Peer"}).Debug("IdleHoldTimer expired, but stay at idle because the admin state is DOWN")
   487  			}
   488  
   489  		case stateOp := <-fsm.adminStateCh:
   490  			err := h.changeadminState(stateOp.State)
   491  			if err == nil {
   492  				switch stateOp.State {
   493  				case adminStateDown:
   494  					// stop idle hold timer
   495  					idleHoldTimer.Stop()
   496  
   497  				case adminStateUp:
   498  					// restart idle hold timer
   499  					fsm.lock.RLock()
   500  					idleHoldTimer.Reset(time.Second * time.Duration(fsm.idleHoldTime))
   501  					fsm.lock.RUnlock()
   502  				}
   503  			}
   504  		}
   505  	}
   506  }
   507  
   508  func (h *fsmHandler) connectLoop(ctx context.Context, wg *sync.WaitGroup) {
   509  	defer wg.Done()
   510  	fsm := h.fsm
   511  
   512  	tick, addr, port, password, ttl, ttlMin, localAddress := func() (int, string, int, string, uint8, uint8, string) {
   513  		fsm.lock.RLock()
   514  		defer fsm.lock.RUnlock()
   515  
   516  		tick := int(fsm.pConf.Timers.Config.ConnectRetry)
   517  		if tick < minConnectRetry {
   518  			tick = minConnectRetry
   519  		}
   520  
   521  		addr := fsm.pConf.State.NeighborAddress
   522  		port := int(bgp.BGP_PORT)
   523  		if fsm.pConf.Transport.Config.RemotePort != 0 {
   524  			port = int(fsm.pConf.Transport.Config.RemotePort)
   525  		}
   526  		password := fsm.pConf.Config.AuthPassword
   527  		ttl := uint8(0)
   528  		ttlMin := uint8(0)
   529  
   530  		if fsm.pConf.TtlSecurity.Config.Enabled {
   531  			ttl = 255
   532  			ttlMin = fsm.pConf.TtlSecurity.Config.TtlMin
   533  		} else if fsm.pConf.Config.PeerAs != 0 && fsm.pConf.Config.PeerType == config.PEER_TYPE_EXTERNAL {
   534  			ttl = 1
   535  			if fsm.pConf.EbgpMultihop.Config.Enabled {
   536  				ttl = fsm.pConf.EbgpMultihop.Config.MultihopTtl
   537  			}
   538  		}
   539  		return tick, addr, port, password, ttl, ttlMin, fsm.pConf.Transport.Config.LocalAddress
   540  	}()
   541  
   542  	for {
   543  		r := rand.New(rand.NewSource(time.Now().UnixNano()))
   544  		timer := time.NewTimer(time.Duration(r.Intn(tick)+tick) * time.Second)
   545  		select {
   546  		case <-ctx.Done():
   547  			log.WithFields(log.Fields{
   548  				"Topic": "Peer",
   549  				"Key":   addr,
   550  			}).Debug("stop connect loop")
   551  			timer.Stop()
   552  			return
   553  		case <-timer.C:
   554  			log.WithFields(log.Fields{
   555  				"Topic": "Peer",
   556  				"Key":   addr,
   557  			}).Debug("try to connect")
   558  		}
   559  
   560  		laddr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(localAddress, "0"))
   561  		if err != nil {
   562  			log.WithFields(log.Fields{
   563  				"Topic": "Peer",
   564  				"Key":   addr,
   565  			}).Warnf("failed to resolve local address: %s", err)
   566  		}
   567  
   568  		if err == nil {
   569  			d := net.Dialer{
   570  				LocalAddr: laddr,
   571  				Timeout:   time.Duration(tick-1) * time.Second,
   572  				Control: func(network, address string, c syscall.RawConn) error {
   573  					return dialerControl(network, address, c, ttl, ttlMin, password)
   574  				},
   575  			}
   576  
   577  			conn, err := d.DialContext(ctx, "tcp", net.JoinHostPort(addr, fmt.Sprintf("%d", port)))
   578  			select {
   579  			case <-ctx.Done():
   580  				log.WithFields(log.Fields{
   581  					"Topic": "Peer",
   582  					"Key":   addr,
   583  				}).Debug("stop connect loop")
   584  				return
   585  			default:
   586  			}
   587  
   588  			if err == nil {
   589  				select {
   590  				case fsm.connCh <- conn:
   591  					return
   592  				default:
   593  					conn.Close()
   594  					log.WithFields(log.Fields{
   595  						"Topic": "Peer",
   596  						"Key":   addr,
   597  					}).Warn("active conn is closed to avoid being blocked")
   598  				}
   599  			} else {
   600  				log.WithFields(log.Fields{
   601  					"Topic": "Peer",
   602  					"Key":   addr,
   603  				}).Debugf("failed to connect: %s", err)
   604  			}
   605  		}
   606  	}
   607  }
   608  
   609  func (h *fsmHandler) active(ctx context.Context) (bgp.FSMState, *fsmStateReason) {
   610  	c, cancel := context.WithCancel(ctx)
   611  
   612  	var wg sync.WaitGroup
   613  	wg.Add(1)
   614  	go h.connectLoop(c, &wg)
   615  
   616  	defer func() {
   617  		cancel()
   618  		wg.Wait()
   619  	}()
   620  
   621  	fsm := h.fsm
   622  	for {
   623  		select {
   624  		case <-ctx.Done():
   625  			return -1, newfsmStateReason(fsmDying, nil, nil)
   626  		case conn, ok := <-fsm.connCh:
   627  			if !ok {
   628  				break
   629  			}
   630  			fsm.lock.Lock()
   631  			fsm.conn = conn
   632  			fsm.lock.Unlock()
   633  			ttl := 0
   634  			ttlMin := 0
   635  
   636  			fsm.lock.RLock()
   637  			if fsm.pConf.TtlSecurity.Config.Enabled {
   638  				ttl = 255
   639  				ttlMin = int(fsm.pConf.TtlSecurity.Config.TtlMin)
   640  			} else if fsm.pConf.Config.PeerAs != 0 && fsm.pConf.Config.PeerType == config.PEER_TYPE_EXTERNAL {
   641  				if fsm.pConf.EbgpMultihop.Config.Enabled {
   642  					ttl = int(fsm.pConf.EbgpMultihop.Config.MultihopTtl)
   643  				} else if fsm.pConf.Transport.Config.Ttl != 0 {
   644  					ttl = int(fsm.pConf.Transport.Config.Ttl)
   645  				} else {
   646  					ttl = 1
   647  				}
   648  			} else if fsm.pConf.Transport.Config.Ttl != 0 {
   649  				ttl = int(fsm.pConf.Transport.Config.Ttl)
   650  			}
   651  			if ttl != 0 {
   652  				if err := setTCPTTLSockopt(conn.(*net.TCPConn), ttl); err != nil {
   653  					log.WithFields(log.Fields{
   654  						"Topic": "Peer",
   655  						"Key":   fsm.pConf.Config.NeighborAddress,
   656  						"State": fsm.state.String(),
   657  					}).Warnf("cannot set TTL(=%d) for peer: %s", ttl, err)
   658  				}
   659  			}
   660  			if ttlMin != 0 {
   661  				if err := setTCPMinTTLSockopt(conn.(*net.TCPConn), ttlMin); err != nil {
   662  					log.WithFields(log.Fields{
   663  						"Topic": "Peer",
   664  						"Key":   fsm.pConf.Config.NeighborAddress,
   665  						"State": fsm.state.String(),
   666  					}).Warnf("cannot set minimal TTL(=%d) for peer: %s", ttl, err)
   667  				}
   668  			}
   669  			fsm.lock.RUnlock()
   670  			// we don't implement delayed open timer so move to opensent right
   671  			// away.
   672  			return bgp.BGP_FSM_OPENSENT, newfsmStateReason(fsmNewConnection, nil, nil)
   673  		case <-fsm.gracefulRestartTimer.C:
   674  			fsm.lock.RLock()
   675  			restarting := fsm.pConf.GracefulRestart.State.PeerRestarting
   676  			fsm.lock.RUnlock()
   677  			if restarting {
   678  				fsm.lock.RLock()
   679  				log.WithFields(log.Fields{
   680  					"Topic": "Peer",
   681  					"Key":   fsm.pConf.State.NeighborAddress,
   682  					"State": fsm.state.String(),
   683  				}).Warn("graceful restart timer expired")
   684  				fsm.lock.RUnlock()
   685  				return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmRestartTimerExpired, nil, nil)
   686  			}
   687  		case err := <-h.stateReasonCh:
   688  			return bgp.BGP_FSM_IDLE, &err
   689  		case stateOp := <-fsm.adminStateCh:
   690  			err := h.changeadminState(stateOp.State)
   691  			if err == nil {
   692  				switch stateOp.State {
   693  				case adminStateDown:
   694  					return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmAdminDown, nil, nil)
   695  				case adminStateUp:
   696  					log.WithFields(log.Fields{
   697  						"Topic":      "Peer",
   698  						"Key":        fsm.pConf.State.NeighborAddress,
   699  						"State":      fsm.state.String(),
   700  						"adminState": stateOp.State.String(),
   701  					}).Panic("code logic bug")
   702  				}
   703  			}
   704  		}
   705  	}
   706  }
   707  
   708  func capAddPathFromConfig(pConf *config.Neighbor) bgp.ParameterCapabilityInterface {
   709  	tuples := make([]*bgp.CapAddPathTuple, 0, len(pConf.AfiSafis))
   710  	for _, af := range pConf.AfiSafis {
   711  		var mode bgp.BGPAddPathMode
   712  		if af.AddPaths.State.Receive {
   713  			mode |= bgp.BGP_ADD_PATH_RECEIVE
   714  		}
   715  		if af.AddPaths.State.SendMax > 0 {
   716  			mode |= bgp.BGP_ADD_PATH_SEND
   717  		}
   718  		if mode > 0 {
   719  			tuples = append(tuples, bgp.NewCapAddPathTuple(af.State.Family, mode))
   720  		}
   721  	}
   722  	if len(tuples) == 0 {
   723  		return nil
   724  	}
   725  	return bgp.NewCapAddPath(tuples)
   726  }
   727  
   728  func capabilitiesFromConfig(pConf *config.Neighbor) []bgp.ParameterCapabilityInterface {
   729  	caps := make([]bgp.ParameterCapabilityInterface, 0, 4)
   730  	caps = append(caps, bgp.NewCapRouteRefresh())
   731  	for _, af := range pConf.AfiSafis {
   732  		caps = append(caps, bgp.NewCapMultiProtocol(af.State.Family))
   733  	}
   734  	caps = append(caps, bgp.NewCapFourOctetASNumber(pConf.Config.LocalAs))
   735  
   736  	if c := pConf.GracefulRestart.Config; c.Enabled {
   737  		tuples := []*bgp.CapGracefulRestartTuple{}
   738  		ltuples := []*bgp.CapLongLivedGracefulRestartTuple{}
   739  
   740  		// RFC 4724 4.1
   741  		// To re-establish the session with its peer, the Restarting Speaker
   742  		// MUST set the "Restart State" bit in the Graceful Restart Capability
   743  		// of the OPEN message.
   744  		restarting := pConf.GracefulRestart.State.LocalRestarting
   745  
   746  		if !c.HelperOnly {
   747  			for i, rf := range pConf.AfiSafis {
   748  				if m := rf.MpGracefulRestart.Config; m.Enabled {
   749  					// When restarting, always flag forwaring bit.
   750  					// This can be a lie, depending on how gobgpd is used.
   751  					// For a route-server use-case, since a route-server
   752  					// itself doesn't forward packets, and the dataplane
   753  					// is a l2 switch which continues to work with no
   754  					// relation to bgpd, this behavior is ok.
   755  					// TODO consideration of other use-cases
   756  					tuples = append(tuples, bgp.NewCapGracefulRestartTuple(rf.State.Family, restarting))
   757  					pConf.AfiSafis[i].MpGracefulRestart.State.Advertised = true
   758  				}
   759  				if m := rf.LongLivedGracefulRestart.Config; m.Enabled {
   760  					ltuples = append(ltuples, bgp.NewCapLongLivedGracefulRestartTuple(rf.State.Family, restarting, m.RestartTime))
   761  				}
   762  			}
   763  		}
   764  		restartTime := c.RestartTime
   765  		notification := c.NotificationEnabled
   766  		caps = append(caps, bgp.NewCapGracefulRestart(restarting, notification, restartTime, tuples))
   767  		if c.LongLivedEnabled {
   768  			caps = append(caps, bgp.NewCapLongLivedGracefulRestart(ltuples))
   769  		}
   770  	}
   771  
   772  	// unnumbered BGP
   773  	if pConf.Config.NeighborInterface != "" {
   774  		tuples := []*bgp.CapExtendedNexthopTuple{}
   775  		families, _ := config.AfiSafis(pConf.AfiSafis).ToRfList()
   776  		for _, family := range families {
   777  			if family == bgp.RF_IPv6_UC {
   778  				continue
   779  			}
   780  			tuple := bgp.NewCapExtendedNexthopTuple(family, bgp.AFI_IP6)
   781  			tuples = append(tuples, tuple)
   782  		}
   783  		caps = append(caps, bgp.NewCapExtendedNexthop(tuples))
   784  	}
   785  
   786  	// ADD-PATH Capability
   787  	if c := capAddPathFromConfig(pConf); c != nil {
   788  		caps = append(caps, capAddPathFromConfig(pConf))
   789  	}
   790  
   791  	return caps
   792  }
   793  
   794  func buildopen(gConf *config.Global, pConf *config.Neighbor) *bgp.BGPMessage {
   795  	caps := capabilitiesFromConfig(pConf)
   796  	opt := bgp.NewOptionParameterCapability(caps)
   797  	holdTime := uint16(pConf.Timers.Config.HoldTime)
   798  	as := pConf.Config.LocalAs
   799  	if as > (1<<16)-1 {
   800  		as = bgp.AS_TRANS
   801  	}
   802  	return bgp.NewBGPOpenMessage(uint16(as), holdTime, gConf.Config.RouterId,
   803  		[]bgp.OptionParameterInterface{opt})
   804  }
   805  
   806  func readAll(conn net.Conn, length int) ([]byte, error) {
   807  	buf := make([]byte, length)
   808  	_, err := io.ReadFull(conn, buf)
   809  	if err != nil {
   810  		return nil, err
   811  	}
   812  	return buf, nil
   813  }
   814  
   815  func getPathAttrFromBGPUpdate(m *bgp.BGPUpdate, typ bgp.BGPAttrType) bgp.PathAttributeInterface {
   816  	for _, a := range m.PathAttributes {
   817  		if a.GetType() == typ {
   818  			return a
   819  		}
   820  	}
   821  	return nil
   822  }
   823  
   824  func hasOwnASLoop(ownAS uint32, limit int, asPath *bgp.PathAttributeAsPath) bool {
   825  	cnt := 0
   826  	for _, param := range asPath.Value {
   827  		for _, as := range param.GetAS() {
   828  			if as == ownAS {
   829  				cnt++
   830  				if cnt > limit {
   831  					return true
   832  				}
   833  			}
   834  		}
   835  	}
   836  	return false
   837  }
   838  
   839  func extractRouteFamily(p *bgp.PathAttributeInterface) *bgp.RouteFamily {
   840  	attr := *p
   841  
   842  	var afi uint16
   843  	var safi uint8
   844  
   845  	switch a := attr.(type) {
   846  	case *bgp.PathAttributeMpReachNLRI:
   847  		afi = a.AFI
   848  		safi = a.SAFI
   849  	case *bgp.PathAttributeMpUnreachNLRI:
   850  		afi = a.AFI
   851  		safi = a.SAFI
   852  	default:
   853  		return nil
   854  	}
   855  
   856  	rf := bgp.AfiSafiToRouteFamily(afi, safi)
   857  	return &rf
   858  }
   859  
   860  func (h *fsmHandler) afiSafiDisable(rf bgp.RouteFamily) string {
   861  	h.fsm.lock.Lock()
   862  	defer h.fsm.lock.Unlock()
   863  
   864  	n := bgp.AddressFamilyNameMap[rf]
   865  
   866  	for i, a := range h.fsm.pConf.AfiSafis {
   867  		if string(a.Config.AfiSafiName) == n {
   868  			h.fsm.pConf.AfiSafis[i].State.Enabled = false
   869  			break
   870  		}
   871  	}
   872  	newList := make([]bgp.ParameterCapabilityInterface, 0)
   873  	for _, c := range h.fsm.capMap[bgp.BGP_CAP_MULTIPROTOCOL] {
   874  		if c.(*bgp.CapMultiProtocol).CapValue == rf {
   875  			continue
   876  		}
   877  		newList = append(newList, c)
   878  	}
   879  	h.fsm.capMap[bgp.BGP_CAP_MULTIPROTOCOL] = newList
   880  	return n
   881  }
   882  
   883  func (h *fsmHandler) handlingError(m *bgp.BGPMessage, e error, useRevisedError bool) bgp.ErrorHandling {
   884  	handling := bgp.ERROR_HANDLING_NONE
   885  	if m.Header.Type == bgp.BGP_MSG_UPDATE && useRevisedError {
   886  		factor := e.(*bgp.MessageError)
   887  		handling = factor.ErrorHandling
   888  		switch handling {
   889  		case bgp.ERROR_HANDLING_ATTRIBUTE_DISCARD:
   890  			h.fsm.lock.RLock()
   891  			log.WithFields(log.Fields{
   892  				"Topic": "Peer",
   893  				"Key":   h.fsm.pConf.State.NeighborAddress,
   894  				"State": h.fsm.state.String(),
   895  				"error": e,
   896  			}).Warn("Some attributes were discarded")
   897  			h.fsm.lock.RUnlock()
   898  		case bgp.ERROR_HANDLING_TREAT_AS_WITHDRAW:
   899  			m.Body = bgp.TreatAsWithdraw(m.Body.(*bgp.BGPUpdate))
   900  			h.fsm.lock.RLock()
   901  			log.WithFields(log.Fields{
   902  				"Topic": "Peer",
   903  				"Key":   h.fsm.pConf.State.NeighborAddress,
   904  				"State": h.fsm.state.String(),
   905  				"error": e,
   906  			}).Warn("the received Update message was treated as withdraw")
   907  			h.fsm.lock.RUnlock()
   908  		case bgp.ERROR_HANDLING_AFISAFI_DISABLE:
   909  			rf := extractRouteFamily(factor.ErrorAttribute)
   910  			if rf == nil {
   911  				h.fsm.lock.RLock()
   912  				log.WithFields(log.Fields{
   913  					"Topic": "Peer",
   914  					"Key":   h.fsm.pConf.State.NeighborAddress,
   915  					"State": h.fsm.state.String(),
   916  				}).Warn("Error occurred during AFI/SAFI disabling")
   917  				h.fsm.lock.RUnlock()
   918  			} else {
   919  				n := h.afiSafiDisable(*rf)
   920  				h.fsm.lock.RLock()
   921  				log.WithFields(log.Fields{
   922  					"Topic": "Peer",
   923  					"Key":   h.fsm.pConf.State.NeighborAddress,
   924  					"State": h.fsm.state.String(),
   925  					"error": e,
   926  				}).Warnf("Capability %s was disabled", n)
   927  				h.fsm.lock.RUnlock()
   928  			}
   929  		}
   930  	} else {
   931  		handling = bgp.ERROR_HANDLING_SESSION_RESET
   932  	}
   933  	return handling
   934  }
   935  
   936  func (h *fsmHandler) recvMessageWithError() (*fsmMsg, error) {
   937  	sendToStateReasonCh := func(typ fsmStateReasonType, notif *bgp.BGPMessage) {
   938  		// probably doesn't happen but be cautious
   939  		select {
   940  		case h.stateReasonCh <- *newfsmStateReason(typ, notif, nil):
   941  		default:
   942  		}
   943  	}
   944  
   945  	headerBuf, err := readAll(h.conn, bgp.BGP_HEADER_LENGTH)
   946  	if err != nil {
   947  		sendToStateReasonCh(fsmReadFailed, nil)
   948  		return nil, err
   949  	}
   950  
   951  	hd := &bgp.BGPHeader{}
   952  	err = hd.DecodeFromBytes(headerBuf)
   953  	if err != nil {
   954  		h.fsm.bgpMessageStateUpdate(0, true)
   955  		h.fsm.lock.RLock()
   956  		log.WithFields(log.Fields{
   957  			"Topic": "Peer",
   958  			"Key":   h.fsm.pConf.State.NeighborAddress,
   959  			"State": h.fsm.state.String(),
   960  			"error": err,
   961  		}).Warn("Session will be reset due to malformed BGP Header")
   962  		fmsg := &fsmMsg{
   963  			MsgType: fsmMsgBGPMessage,
   964  			MsgSrc:  h.fsm.pConf.State.NeighborAddress,
   965  			MsgData: err,
   966  			Version: h.fsm.version,
   967  		}
   968  		h.fsm.lock.RUnlock()
   969  		return fmsg, err
   970  	}
   971  
   972  	bodyBuf, err := readAll(h.conn, int(hd.Len)-bgp.BGP_HEADER_LENGTH)
   973  	if err != nil {
   974  		sendToStateReasonCh(fsmReadFailed, nil)
   975  		return nil, err
   976  	}
   977  
   978  	now := time.Now()
   979  	handling := bgp.ERROR_HANDLING_NONE
   980  
   981  	h.fsm.lock.RLock()
   982  	useRevisedError := h.fsm.pConf.ErrorHandling.Config.TreatAsWithdraw
   983  	options := h.fsm.marshallingOptions
   984  	h.fsm.lock.RUnlock()
   985  
   986  	m, err := bgp.ParseBGPBody(hd, bodyBuf, options)
   987  	if err != nil {
   988  		handling = h.handlingError(m, err, useRevisedError)
   989  		h.fsm.bgpMessageStateUpdate(0, true)
   990  	} else {
   991  		h.fsm.bgpMessageStateUpdate(m.Header.Type, true)
   992  		err = bgp.ValidateBGPMessage(m)
   993  	}
   994  	h.fsm.lock.RLock()
   995  	fmsg := &fsmMsg{
   996  		MsgType:   fsmMsgBGPMessage,
   997  		MsgSrc:    h.fsm.pConf.State.NeighborAddress,
   998  		timestamp: now,
   999  		Version:   h.fsm.version,
  1000  	}
  1001  	h.fsm.lock.RUnlock()
  1002  
  1003  	switch handling {
  1004  	case bgp.ERROR_HANDLING_AFISAFI_DISABLE:
  1005  		fmsg.MsgData = m
  1006  		return fmsg, nil
  1007  	case bgp.ERROR_HANDLING_SESSION_RESET:
  1008  		h.fsm.lock.RLock()
  1009  		log.WithFields(log.Fields{
  1010  			"Topic": "Peer",
  1011  			"Key":   h.fsm.pConf.State.NeighborAddress,
  1012  			"State": h.fsm.state.String(),
  1013  			"error": err,
  1014  		}).Warn("Session will be reset due to malformed BGP message")
  1015  		h.fsm.lock.RUnlock()
  1016  		fmsg.MsgData = err
  1017  		return fmsg, err
  1018  	default:
  1019  		fmsg.MsgData = m
  1020  
  1021  		h.fsm.lock.RLock()
  1022  		establishedState := h.fsm.state == bgp.BGP_FSM_ESTABLISHED
  1023  		h.fsm.lock.RUnlock()
  1024  
  1025  		if establishedState {
  1026  			switch m.Header.Type {
  1027  			case bgp.BGP_MSG_ROUTE_REFRESH:
  1028  				fmsg.MsgType = fsmMsgRouteRefresh
  1029  			case bgp.BGP_MSG_UPDATE:
  1030  				body := m.Body.(*bgp.BGPUpdate)
  1031  				isEBGP := h.fsm.pConf.IsEBGPPeer(h.fsm.gConf)
  1032  				isConfed := h.fsm.pConf.IsConfederationMember(h.fsm.gConf)
  1033  
  1034  				fmsg.payload = make([]byte, len(headerBuf)+len(bodyBuf))
  1035  				copy(fmsg.payload, headerBuf)
  1036  				copy(fmsg.payload[len(headerBuf):], bodyBuf)
  1037  
  1038  				h.fsm.lock.RLock()
  1039  				rfMap := h.fsm.rfMap
  1040  				h.fsm.lock.RUnlock()
  1041  				ok, err := bgp.ValidateUpdateMsg(body, rfMap, isEBGP, isConfed)
  1042  				if !ok {
  1043  					handling = h.handlingError(m, err, useRevisedError)
  1044  				}
  1045  				if handling == bgp.ERROR_HANDLING_SESSION_RESET {
  1046  					h.fsm.lock.RLock()
  1047  					log.WithFields(log.Fields{
  1048  						"Topic": "Peer",
  1049  						"Key":   h.fsm.pConf.State.NeighborAddress,
  1050  						"State": h.fsm.state.String(),
  1051  						"error": err,
  1052  					}).Warn("Session will be reset due to malformed BGP update message")
  1053  					h.fsm.lock.RUnlock()
  1054  					fmsg.MsgData = err
  1055  					return fmsg, err
  1056  				}
  1057  
  1058  				if routes := len(body.WithdrawnRoutes); routes > 0 {
  1059  					h.fsm.bmpStatsUpdate(bmp.BMP_STAT_TYPE_WITHDRAW_UPDATE, 1)
  1060  					h.fsm.bmpStatsUpdate(bmp.BMP_STAT_TYPE_WITHDRAW_PREFIX, routes)
  1061  				} else if attr := getPathAttrFromBGPUpdate(body, bgp.BGP_ATTR_TYPE_MP_UNREACH_NLRI); attr != nil {
  1062  					mpUnreach := attr.(*bgp.PathAttributeMpUnreachNLRI)
  1063  					if routes = len(mpUnreach.Value); routes > 0 {
  1064  						h.fsm.bmpStatsUpdate(bmp.BMP_STAT_TYPE_WITHDRAW_UPDATE, 1)
  1065  						h.fsm.bmpStatsUpdate(bmp.BMP_STAT_TYPE_WITHDRAW_PREFIX, routes)
  1066  					}
  1067  				}
  1068  
  1069  				table.UpdatePathAttrs4ByteAs(body)
  1070  				if err = table.UpdatePathAggregator4ByteAs(body); err != nil {
  1071  					fmsg.MsgData = err
  1072  					return fmsg, err
  1073  				}
  1074  
  1075  				h.fsm.lock.RLock()
  1076  				peerInfo := h.fsm.peerInfo
  1077  				h.fsm.lock.RUnlock()
  1078  				fmsg.PathList = table.ProcessMessage(m, peerInfo, fmsg.timestamp)
  1079  				fallthrough
  1080  			case bgp.BGP_MSG_KEEPALIVE:
  1081  				// if the length of h.holdTimerResetCh
  1082  				// isn't zero, the timer will be reset
  1083  				// soon anyway.
  1084  				select {
  1085  				case h.holdTimerResetCh <- true:
  1086  				default:
  1087  				}
  1088  				if m.Header.Type == bgp.BGP_MSG_KEEPALIVE {
  1089  					return nil, nil
  1090  				}
  1091  			case bgp.BGP_MSG_NOTIFICATION:
  1092  				body := m.Body.(*bgp.BGPNotification)
  1093  				if body.ErrorCode == bgp.BGP_ERROR_CEASE && (body.ErrorSubcode == bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN || body.ErrorSubcode == bgp.BGP_ERROR_SUB_ADMINISTRATIVE_RESET) {
  1094  					communication, rest := decodeAdministrativeCommunication(body.Data)
  1095  					h.fsm.lock.RLock()
  1096  					log.WithFields(log.Fields{
  1097  						"Topic":               "Peer",
  1098  						"Key":                 h.fsm.pConf.State.NeighborAddress,
  1099  						"Code":                body.ErrorCode,
  1100  						"Subcode":             body.ErrorSubcode,
  1101  						"Communicated-Reason": communication,
  1102  						"Data":                rest,
  1103  					}).Warn("received notification")
  1104  					h.fsm.lock.RUnlock()
  1105  				} else {
  1106  					h.fsm.lock.RLock()
  1107  					log.WithFields(log.Fields{
  1108  						"Topic":   "Peer",
  1109  						"Key":     h.fsm.pConf.State.NeighborAddress,
  1110  						"Code":    body.ErrorCode,
  1111  						"Subcode": body.ErrorSubcode,
  1112  						"Data":    body.Data,
  1113  					}).Warn("received notification")
  1114  					h.fsm.lock.RUnlock()
  1115  				}
  1116  
  1117  				h.fsm.lock.RLock()
  1118  				s := h.fsm.pConf.GracefulRestart.State
  1119  				hardReset := s.Enabled && s.NotificationEnabled && body.ErrorCode == bgp.BGP_ERROR_CEASE && body.ErrorSubcode == bgp.BGP_ERROR_SUB_HARD_RESET
  1120  				h.fsm.lock.RUnlock()
  1121  				if hardReset {
  1122  					sendToStateReasonCh(fsmHardReset, m)
  1123  				} else {
  1124  					sendToStateReasonCh(fsmNotificationRecv, m)
  1125  				}
  1126  				return nil, nil
  1127  			}
  1128  		}
  1129  	}
  1130  	return fmsg, nil
  1131  }
  1132  
  1133  func (h *fsmHandler) recvMessage(ctx context.Context, wg *sync.WaitGroup) error {
  1134  	defer func() {
  1135  		h.msgCh.Close()
  1136  		wg.Done()
  1137  	}()
  1138  	fmsg, _ := h.recvMessageWithError()
  1139  	if fmsg != nil {
  1140  		h.msgCh.In() <- fmsg
  1141  	}
  1142  	return nil
  1143  }
  1144  
  1145  func open2Cap(open *bgp.BGPOpen, n *config.Neighbor) (map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface, map[bgp.RouteFamily]bgp.BGPAddPathMode) {
  1146  	capMap := make(map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface)
  1147  	for _, p := range open.OptParams {
  1148  		if paramCap, y := p.(*bgp.OptionParameterCapability); y {
  1149  			for _, c := range paramCap.Capability {
  1150  				m, ok := capMap[c.Code()]
  1151  				if !ok {
  1152  					m = make([]bgp.ParameterCapabilityInterface, 0, 1)
  1153  				}
  1154  				capMap[c.Code()] = append(m, c)
  1155  			}
  1156  		}
  1157  	}
  1158  
  1159  	// squash add path cap
  1160  	if caps, y := capMap[bgp.BGP_CAP_ADD_PATH]; y {
  1161  		items := make([]*bgp.CapAddPathTuple, 0, len(caps))
  1162  		for _, c := range caps {
  1163  			items = append(items, c.(*bgp.CapAddPath).Tuples...)
  1164  		}
  1165  		capMap[bgp.BGP_CAP_ADD_PATH] = []bgp.ParameterCapabilityInterface{bgp.NewCapAddPath(items)}
  1166  	}
  1167  
  1168  	// remote open message may not include multi-protocol capability
  1169  	if _, y := capMap[bgp.BGP_CAP_MULTIPROTOCOL]; !y {
  1170  		capMap[bgp.BGP_CAP_MULTIPROTOCOL] = []bgp.ParameterCapabilityInterface{bgp.NewCapMultiProtocol(bgp.RF_IPv4_UC)}
  1171  	}
  1172  
  1173  	local := n.CreateRfMap()
  1174  	remote := make(map[bgp.RouteFamily]bgp.BGPAddPathMode)
  1175  	for _, c := range capMap[bgp.BGP_CAP_MULTIPROTOCOL] {
  1176  		family := c.(*bgp.CapMultiProtocol).CapValue
  1177  		remote[family] = bgp.BGP_ADD_PATH_NONE
  1178  		for _, a := range capMap[bgp.BGP_CAP_ADD_PATH] {
  1179  			for _, i := range a.(*bgp.CapAddPath).Tuples {
  1180  				if i.RouteFamily == family {
  1181  					remote[family] = i.Mode
  1182  				}
  1183  			}
  1184  		}
  1185  	}
  1186  	negotiated := make(map[bgp.RouteFamily]bgp.BGPAddPathMode)
  1187  	for family, mode := range local {
  1188  		if m, y := remote[family]; y {
  1189  			n := bgp.BGP_ADD_PATH_NONE
  1190  			if mode&bgp.BGP_ADD_PATH_SEND > 0 && m&bgp.BGP_ADD_PATH_RECEIVE > 0 {
  1191  				n |= bgp.BGP_ADD_PATH_SEND
  1192  			}
  1193  			if mode&bgp.BGP_ADD_PATH_RECEIVE > 0 && m&bgp.BGP_ADD_PATH_SEND > 0 {
  1194  				n |= bgp.BGP_ADD_PATH_RECEIVE
  1195  			}
  1196  			negotiated[family] = n
  1197  		}
  1198  	}
  1199  	return capMap, negotiated
  1200  }
  1201  
  1202  func (h *fsmHandler) opensent(ctx context.Context) (bgp.FSMState, *fsmStateReason) {
  1203  	fsm := h.fsm
  1204  
  1205  	fsm.lock.RLock()
  1206  	m := buildopen(fsm.gConf, fsm.pConf)
  1207  	fsm.lock.RUnlock()
  1208  
  1209  	b, _ := m.Serialize()
  1210  	fsm.conn.Write(b)
  1211  	fsm.bgpMessageStateUpdate(m.Header.Type, false)
  1212  
  1213  	h.msgCh = channels.NewInfiniteChannel()
  1214  
  1215  	fsm.lock.RLock()
  1216  	h.conn = fsm.conn
  1217  	fsm.lock.RUnlock()
  1218  
  1219  	var wg sync.WaitGroup
  1220  	wg.Add(1)
  1221  	defer wg.Wait()
  1222  	go h.recvMessage(ctx, &wg)
  1223  
  1224  	// RFC 4271 P.60
  1225  	// sets its HoldTimer to a large value
  1226  	// A HoldTimer value of 4 minutes is suggested as a "large value"
  1227  	// for the HoldTimer
  1228  	fsm.lock.RLock()
  1229  	holdTimer := time.NewTimer(time.Second * time.Duration(fsm.opensentHoldTime))
  1230  	fsm.lock.RUnlock()
  1231  
  1232  	for {
  1233  		select {
  1234  		case <-ctx.Done():
  1235  			h.conn.Close()
  1236  			return -1, newfsmStateReason(fsmDying, nil, nil)
  1237  		case conn, ok := <-fsm.connCh:
  1238  			if !ok {
  1239  				break
  1240  			}
  1241  			conn.Close()
  1242  			fsm.lock.RLock()
  1243  			log.WithFields(log.Fields{
  1244  				"Topic": "Peer",
  1245  				"Key":   fsm.pConf.State.NeighborAddress,
  1246  				"State": fsm.state.String(),
  1247  			}).Warn("Closed an accepted connection")
  1248  			fsm.lock.RUnlock()
  1249  		case <-fsm.gracefulRestartTimer.C:
  1250  			fsm.lock.RLock()
  1251  			restarting := fsm.pConf.GracefulRestart.State.PeerRestarting
  1252  			fsm.lock.RUnlock()
  1253  			if restarting {
  1254  				fsm.lock.RLock()
  1255  				log.WithFields(log.Fields{
  1256  					"Topic": "Peer",
  1257  					"Key":   fsm.pConf.State.NeighborAddress,
  1258  					"State": fsm.state.String(),
  1259  				}).Warn("graceful restart timer expired")
  1260  				fsm.lock.RUnlock()
  1261  				h.conn.Close()
  1262  				return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmRestartTimerExpired, nil, nil)
  1263  			}
  1264  		case i, ok := <-h.msgCh.Out():
  1265  			if !ok {
  1266  				continue
  1267  			}
  1268  			e := i.(*fsmMsg)
  1269  			switch e.MsgData.(type) {
  1270  			case *bgp.BGPMessage:
  1271  				m := e.MsgData.(*bgp.BGPMessage)
  1272  				if m.Header.Type == bgp.BGP_MSG_OPEN {
  1273  					fsm.lock.Lock()
  1274  					fsm.recvOpen = m
  1275  					fsm.lock.Unlock()
  1276  
  1277  					body := m.Body.(*bgp.BGPOpen)
  1278  
  1279  					fsm.lock.RLock()
  1280  					fsmPeerAS := fsm.pConf.Config.PeerAs
  1281  					fsm.lock.RUnlock()
  1282  					peerAs, err := bgp.ValidateOpenMsg(body, fsmPeerAS)
  1283  					if err != nil {
  1284  						m, _ := fsm.sendNotificationFromErrorMsg(err.(*bgp.MessageError))
  1285  						return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmInvalidMsg, m, nil)
  1286  					}
  1287  
  1288  					// ASN negotiation was skipped
  1289  					fsm.lock.RLock()
  1290  					asnNegotiationSkipped := fsm.pConf.Config.PeerAs == 0
  1291  					fsm.lock.RUnlock()
  1292  					if asnNegotiationSkipped {
  1293  						fsm.lock.Lock()
  1294  						typ := config.PEER_TYPE_EXTERNAL
  1295  						if fsm.peerInfo.LocalAS == peerAs {
  1296  							typ = config.PEER_TYPE_INTERNAL
  1297  						}
  1298  						fsm.pConf.State.PeerType = typ
  1299  						log.WithFields(log.Fields{
  1300  							"Topic": "Peer",
  1301  							"Key":   fsm.pConf.State.NeighborAddress,
  1302  							"State": fsm.state.String(),
  1303  						}).Infof("skipped asn negotiation: peer-as: %d, peer-type: %s", peerAs, typ)
  1304  						fsm.lock.Unlock()
  1305  					} else {
  1306  						fsm.lock.Lock()
  1307  						fsm.pConf.State.PeerType = fsm.pConf.Config.PeerType
  1308  						fsm.lock.Unlock()
  1309  					}
  1310  					fsm.lock.Lock()
  1311  					fsm.pConf.State.PeerAs = peerAs
  1312  					fsm.peerInfo.AS = peerAs
  1313  					fsm.peerInfo.ID = body.ID
  1314  					fsm.capMap, fsm.rfMap = open2Cap(body, fsm.pConf)
  1315  
  1316  					if _, y := fsm.capMap[bgp.BGP_CAP_ADD_PATH]; y {
  1317  						fsm.marshallingOptions = &bgp.MarshallingOption{
  1318  							AddPath: fsm.rfMap,
  1319  						}
  1320  					} else {
  1321  						fsm.marshallingOptions = nil
  1322  					}
  1323  
  1324  					// calculate HoldTime
  1325  					// RFC 4271 P.13
  1326  					// a BGP speaker MUST calculate the value of the Hold Timer
  1327  					// by using the smaller of its configured Hold Time and the Hold Time
  1328  					// received in the OPEN message.
  1329  					holdTime := float64(body.HoldTime)
  1330  					myHoldTime := fsm.pConf.Timers.Config.HoldTime
  1331  					if holdTime > myHoldTime {
  1332  						fsm.pConf.Timers.State.NegotiatedHoldTime = myHoldTime
  1333  					} else {
  1334  						fsm.pConf.Timers.State.NegotiatedHoldTime = holdTime
  1335  					}
  1336  
  1337  					keepalive := fsm.pConf.Timers.Config.KeepaliveInterval
  1338  					if n := fsm.pConf.Timers.State.NegotiatedHoldTime; n < myHoldTime {
  1339  						keepalive = n / 3
  1340  					}
  1341  					fsm.pConf.Timers.State.KeepaliveInterval = keepalive
  1342  
  1343  					gr, ok := fsm.capMap[bgp.BGP_CAP_GRACEFUL_RESTART]
  1344  					if fsm.pConf.GracefulRestart.Config.Enabled && ok {
  1345  						state := &fsm.pConf.GracefulRestart.State
  1346  						state.Enabled = true
  1347  						cap := gr[len(gr)-1].(*bgp.CapGracefulRestart)
  1348  						state.PeerRestartTime = uint16(cap.Time)
  1349  
  1350  						for _, t := range cap.Tuples {
  1351  							n := bgp.AddressFamilyNameMap[bgp.AfiSafiToRouteFamily(t.AFI, t.SAFI)]
  1352  							for i, a := range fsm.pConf.AfiSafis {
  1353  								if string(a.Config.AfiSafiName) == n {
  1354  									fsm.pConf.AfiSafis[i].MpGracefulRestart.State.Enabled = true
  1355  									fsm.pConf.AfiSafis[i].MpGracefulRestart.State.Received = true
  1356  									break
  1357  								}
  1358  							}
  1359  						}
  1360  
  1361  						// RFC 4724 4.1
  1362  						// To re-establish the session with its peer, the Restarting Speaker
  1363  						// MUST set the "Restart State" bit in the Graceful Restart Capability
  1364  						// of the OPEN message.
  1365  						if fsm.pConf.GracefulRestart.State.PeerRestarting && cap.Flags&0x08 == 0 {
  1366  							log.WithFields(log.Fields{
  1367  								"Topic": "Peer",
  1368  								"Key":   fsm.pConf.State.NeighborAddress,
  1369  								"State": fsm.state.String(),
  1370  							}).Warn("restart flag is not set")
  1371  							// send notification?
  1372  							h.conn.Close()
  1373  							fsm.lock.Unlock()
  1374  							return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmInvalidMsg, nil, nil)
  1375  						}
  1376  
  1377  						// RFC 4724 3
  1378  						// The most significant bit is defined as the Restart State (R)
  1379  						// bit, ...(snip)... When set (value 1), this bit
  1380  						// indicates that the BGP speaker has restarted, and its peer MUST
  1381  						// NOT wait for the End-of-RIB marker from the speaker before
  1382  						// advertising routing information to the speaker.
  1383  						if fsm.pConf.GracefulRestart.State.LocalRestarting && cap.Flags&0x08 != 0 {
  1384  							log.WithFields(log.Fields{
  1385  								"Topic": "Peer",
  1386  								"Key":   fsm.pConf.State.NeighborAddress,
  1387  								"State": fsm.state.String(),
  1388  							}).Debug("peer has restarted, skipping wait for EOR")
  1389  							for i := range fsm.pConf.AfiSafis {
  1390  								fsm.pConf.AfiSafis[i].MpGracefulRestart.State.EndOfRibReceived = true
  1391  							}
  1392  						}
  1393  						if fsm.pConf.GracefulRestart.Config.NotificationEnabled && cap.Flags&0x04 > 0 {
  1394  							fsm.pConf.GracefulRestart.State.NotificationEnabled = true
  1395  						}
  1396  					}
  1397  					llgr, ok2 := fsm.capMap[bgp.BGP_CAP_LONG_LIVED_GRACEFUL_RESTART]
  1398  					if fsm.pConf.GracefulRestart.Config.LongLivedEnabled && ok && ok2 {
  1399  						fsm.pConf.GracefulRestart.State.LongLivedEnabled = true
  1400  						cap := llgr[len(llgr)-1].(*bgp.CapLongLivedGracefulRestart)
  1401  						for _, t := range cap.Tuples {
  1402  							n := bgp.AddressFamilyNameMap[bgp.AfiSafiToRouteFamily(t.AFI, t.SAFI)]
  1403  							for i, a := range fsm.pConf.AfiSafis {
  1404  								if string(a.Config.AfiSafiName) == n {
  1405  									fsm.pConf.AfiSafis[i].LongLivedGracefulRestart.State.Enabled = true
  1406  									fsm.pConf.AfiSafis[i].LongLivedGracefulRestart.State.Received = true
  1407  									fsm.pConf.AfiSafis[i].LongLivedGracefulRestart.State.PeerRestartTime = t.RestartTime
  1408  									break
  1409  								}
  1410  							}
  1411  						}
  1412  					}
  1413  
  1414  					fsm.lock.Unlock()
  1415  					msg := bgp.NewBGPKeepAliveMessage()
  1416  					b, _ := msg.Serialize()
  1417  					fsm.conn.Write(b)
  1418  					fsm.bgpMessageStateUpdate(msg.Header.Type, false)
  1419  					return bgp.BGP_FSM_OPENCONFIRM, newfsmStateReason(fsmOpenMsgReceived, nil, nil)
  1420  				} else {
  1421  					// send notification?
  1422  					h.conn.Close()
  1423  					return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmInvalidMsg, nil, nil)
  1424  				}
  1425  			case *bgp.MessageError:
  1426  				m, _ := fsm.sendNotificationFromErrorMsg(e.MsgData.(*bgp.MessageError))
  1427  				return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmInvalidMsg, m, nil)
  1428  			default:
  1429  				log.WithFields(log.Fields{
  1430  					"Topic": "Peer",
  1431  					"Key":   fsm.pConf.State.NeighborAddress,
  1432  					"State": fsm.state.String(),
  1433  					"Data":  e.MsgData,
  1434  				}).Panic("unknown msg type")
  1435  			}
  1436  		case err := <-h.stateReasonCh:
  1437  			h.conn.Close()
  1438  			return bgp.BGP_FSM_IDLE, &err
  1439  		case <-holdTimer.C:
  1440  			m, _ := fsm.sendNotification(bgp.BGP_ERROR_HOLD_TIMER_EXPIRED, 0, nil, "hold timer expired")
  1441  			return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmHoldTimerExpired, m, nil)
  1442  		case stateOp := <-fsm.adminStateCh:
  1443  			err := h.changeadminState(stateOp.State)
  1444  			if err == nil {
  1445  				switch stateOp.State {
  1446  				case adminStateDown:
  1447  					h.conn.Close()
  1448  					return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmAdminDown, m, nil)
  1449  				case adminStateUp:
  1450  					log.WithFields(log.Fields{
  1451  						"Topic":      "Peer",
  1452  						"Key":        fsm.pConf.State.NeighborAddress,
  1453  						"State":      fsm.state.String(),
  1454  						"adminState": stateOp.State.String(),
  1455  					}).Panic("code logic bug")
  1456  				}
  1457  			}
  1458  		}
  1459  	}
  1460  }
  1461  
  1462  func keepaliveTicker(fsm *fsm) *time.Ticker {
  1463  	fsm.lock.RLock()
  1464  	defer fsm.lock.RUnlock()
  1465  
  1466  	negotiatedTime := fsm.pConf.Timers.State.NegotiatedHoldTime
  1467  	if negotiatedTime == 0 {
  1468  		return &time.Ticker{}
  1469  	}
  1470  	sec := time.Second * time.Duration(fsm.pConf.Timers.State.KeepaliveInterval)
  1471  	if sec == 0 {
  1472  		sec = time.Second
  1473  	}
  1474  	return time.NewTicker(sec)
  1475  }
  1476  
  1477  func (h *fsmHandler) openconfirm(ctx context.Context) (bgp.FSMState, *fsmStateReason) {
  1478  	fsm := h.fsm
  1479  	ticker := keepaliveTicker(fsm)
  1480  	h.msgCh = channels.NewInfiniteChannel()
  1481  	fsm.lock.RLock()
  1482  	h.conn = fsm.conn
  1483  
  1484  	var wg sync.WaitGroup
  1485  	defer wg.Wait()
  1486  	wg.Add(1)
  1487  	go h.recvMessage(ctx, &wg)
  1488  
  1489  	var holdTimer *time.Timer
  1490  	if fsm.pConf.Timers.State.NegotiatedHoldTime == 0 {
  1491  		holdTimer = &time.Timer{}
  1492  	} else {
  1493  		// RFC 4271 P.65
  1494  		// sets the HoldTimer according to the negotiated value
  1495  		holdTimer = time.NewTimer(time.Second * time.Duration(fsm.pConf.Timers.State.NegotiatedHoldTime))
  1496  	}
  1497  	fsm.lock.RUnlock()
  1498  
  1499  	for {
  1500  		select {
  1501  		case <-ctx.Done():
  1502  			h.conn.Close()
  1503  			return -1, newfsmStateReason(fsmDying, nil, nil)
  1504  		case conn, ok := <-fsm.connCh:
  1505  			if !ok {
  1506  				break
  1507  			}
  1508  			conn.Close()
  1509  			fsm.lock.RLock()
  1510  			log.WithFields(log.Fields{
  1511  				"Topic": "Peer",
  1512  				"Key":   fsm.pConf.State.NeighborAddress,
  1513  				"State": fsm.state.String(),
  1514  			}).Warn("Closed an accepted connection")
  1515  			fsm.lock.RUnlock()
  1516  		case <-fsm.gracefulRestartTimer.C:
  1517  			fsm.lock.RLock()
  1518  			restarting := fsm.pConf.GracefulRestart.State.PeerRestarting
  1519  			fsm.lock.RUnlock()
  1520  			if restarting {
  1521  				fsm.lock.RLock()
  1522  				log.WithFields(log.Fields{
  1523  					"Topic": "Peer",
  1524  					"Key":   fsm.pConf.State.NeighborAddress,
  1525  					"State": fsm.state.String(),
  1526  				}).Warn("graceful restart timer expired")
  1527  				fsm.lock.RUnlock()
  1528  				h.conn.Close()
  1529  				return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmRestartTimerExpired, nil, nil)
  1530  			}
  1531  		case <-ticker.C:
  1532  			m := bgp.NewBGPKeepAliveMessage()
  1533  			b, _ := m.Serialize()
  1534  			// TODO: check error
  1535  			fsm.conn.Write(b)
  1536  			fsm.bgpMessageStateUpdate(m.Header.Type, false)
  1537  		case i, ok := <-h.msgCh.Out():
  1538  			if !ok {
  1539  				continue
  1540  			}
  1541  			e := i.(*fsmMsg)
  1542  			switch e.MsgData.(type) {
  1543  			case *bgp.BGPMessage:
  1544  				m := e.MsgData.(*bgp.BGPMessage)
  1545  				if m.Header.Type == bgp.BGP_MSG_KEEPALIVE {
  1546  					return bgp.BGP_FSM_ESTABLISHED, newfsmStateReason(fsmOpenMsgNegotiated, nil, nil)
  1547  				}
  1548  				// send notification ?
  1549  				h.conn.Close()
  1550  				return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmInvalidMsg, nil, nil)
  1551  			case *bgp.MessageError:
  1552  				m, _ := fsm.sendNotificationFromErrorMsg(e.MsgData.(*bgp.MessageError))
  1553  				return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmInvalidMsg, m, nil)
  1554  			default:
  1555  				log.WithFields(log.Fields{
  1556  					"Topic": "Peer",
  1557  					"Key":   fsm.pConf.State.NeighborAddress,
  1558  					"State": fsm.state.String(),
  1559  					"Data":  e.MsgData,
  1560  				}).Panic("unknown msg type")
  1561  			}
  1562  		case err := <-h.stateReasonCh:
  1563  			h.conn.Close()
  1564  			return bgp.BGP_FSM_IDLE, &err
  1565  		case <-holdTimer.C:
  1566  			m, _ := fsm.sendNotification(bgp.BGP_ERROR_HOLD_TIMER_EXPIRED, 0, nil, "hold timer expired")
  1567  			return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmHoldTimerExpired, m, nil)
  1568  		case stateOp := <-fsm.adminStateCh:
  1569  			err := h.changeadminState(stateOp.State)
  1570  			if err == nil {
  1571  				switch stateOp.State {
  1572  				case adminStateDown:
  1573  					h.conn.Close()
  1574  					return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmAdminDown, nil, nil)
  1575  				case adminStateUp:
  1576  					log.WithFields(log.Fields{
  1577  						"Topic":      "Peer",
  1578  						"Key":        fsm.pConf.State.NeighborAddress,
  1579  						"State":      fsm.state.String(),
  1580  						"adminState": stateOp.State.String(),
  1581  					}).Panic("code logic bug")
  1582  				}
  1583  			}
  1584  		}
  1585  	}
  1586  }
  1587  
  1588  func (h *fsmHandler) sendMessageloop(ctx context.Context, wg *sync.WaitGroup) error {
  1589  	defer wg.Done()
  1590  	conn := h.conn
  1591  	fsm := h.fsm
  1592  	ticker := keepaliveTicker(fsm)
  1593  	send := func(m *bgp.BGPMessage) error {
  1594  		fsm.lock.RLock()
  1595  		if fsm.twoByteAsTrans && m.Header.Type == bgp.BGP_MSG_UPDATE {
  1596  			log.WithFields(log.Fields{
  1597  				"Topic": "Peer",
  1598  				"Key":   fsm.pConf.State.NeighborAddress,
  1599  				"State": fsm.state.String(),
  1600  				"Data":  m,
  1601  			}).Debug("update for 2byte AS peer")
  1602  			table.UpdatePathAttrs2ByteAs(m.Body.(*bgp.BGPUpdate))
  1603  			table.UpdatePathAggregator2ByteAs(m.Body.(*bgp.BGPUpdate))
  1604  		}
  1605  		b, err := m.Serialize(h.fsm.marshallingOptions)
  1606  		fsm.lock.RUnlock()
  1607  		if err != nil {
  1608  			fsm.lock.RLock()
  1609  			log.WithFields(log.Fields{
  1610  				"Topic": "Peer",
  1611  				"Key":   fsm.pConf.State.NeighborAddress,
  1612  				"State": fsm.state.String(),
  1613  				"Data":  err,
  1614  			}).Warn("failed to serialize")
  1615  			fsm.lock.RUnlock()
  1616  			fsm.bgpMessageStateUpdate(0, false)
  1617  			return nil
  1618  		}
  1619  		fsm.lock.RLock()
  1620  		err = conn.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(fsm.pConf.Timers.State.NegotiatedHoldTime)))
  1621  		fsm.lock.RUnlock()
  1622  		if err != nil {
  1623  			h.stateReasonCh <- *newfsmStateReason(fsmWriteFailed, nil, nil)
  1624  			conn.Close()
  1625  			return fmt.Errorf("failed to set write deadline")
  1626  		}
  1627  		_, err = conn.Write(b)
  1628  		if err != nil {
  1629  			fsm.lock.RLock()
  1630  			log.WithFields(log.Fields{
  1631  				"Topic": "Peer",
  1632  				"Key":   fsm.pConf.State.NeighborAddress,
  1633  				"State": fsm.state.String(),
  1634  				"Data":  err,
  1635  			}).Warn("failed to send")
  1636  			fsm.lock.RUnlock()
  1637  			h.stateReasonCh <- *newfsmStateReason(fsmWriteFailed, nil, nil)
  1638  			conn.Close()
  1639  			return fmt.Errorf("closed")
  1640  		}
  1641  		fsm.bgpMessageStateUpdate(m.Header.Type, false)
  1642  
  1643  		switch m.Header.Type {
  1644  		case bgp.BGP_MSG_NOTIFICATION:
  1645  			body := m.Body.(*bgp.BGPNotification)
  1646  			if body.ErrorCode == bgp.BGP_ERROR_CEASE && (body.ErrorSubcode == bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN || body.ErrorSubcode == bgp.BGP_ERROR_SUB_ADMINISTRATIVE_RESET) {
  1647  				communication, rest := decodeAdministrativeCommunication(body.Data)
  1648  				fsm.lock.RLock()
  1649  				log.WithFields(log.Fields{
  1650  					"Topic":               "Peer",
  1651  					"Key":                 fsm.pConf.State.NeighborAddress,
  1652  					"State":               fsm.state.String(),
  1653  					"Code":                body.ErrorCode,
  1654  					"Subcode":             body.ErrorSubcode,
  1655  					"Communicated-Reason": communication,
  1656  					"Data":                rest,
  1657  				}).Warn("sent notification")
  1658  				fsm.lock.RUnlock()
  1659  			} else {
  1660  				fsm.lock.RLock()
  1661  				log.WithFields(log.Fields{
  1662  					"Topic":   "Peer",
  1663  					"Key":     fsm.pConf.State.NeighborAddress,
  1664  					"State":   fsm.state.String(),
  1665  					"Code":    body.ErrorCode,
  1666  					"Subcode": body.ErrorSubcode,
  1667  					"Data":    body.Data,
  1668  				}).Warn("sent notification")
  1669  				fsm.lock.RUnlock()
  1670  			}
  1671  			h.stateReasonCh <- *newfsmStateReason(fsmNotificationSent, m, nil)
  1672  			conn.Close()
  1673  			return fmt.Errorf("closed")
  1674  		case bgp.BGP_MSG_UPDATE:
  1675  			update := m.Body.(*bgp.BGPUpdate)
  1676  			fsm.lock.RLock()
  1677  			log.WithFields(log.Fields{
  1678  				"Topic":       "Peer",
  1679  				"Key":         fsm.pConf.State.NeighborAddress,
  1680  				"State":       fsm.state.String(),
  1681  				"nlri":        update.NLRI,
  1682  				"withdrawals": update.WithdrawnRoutes,
  1683  				"attributes":  update.PathAttributes,
  1684  			}).Debug("sent update")
  1685  			fsm.lock.RUnlock()
  1686  		default:
  1687  			fsm.lock.RLock()
  1688  			log.WithFields(log.Fields{
  1689  				"Topic": "Peer",
  1690  				"Key":   fsm.pConf.State.NeighborAddress,
  1691  				"State": fsm.state.String(),
  1692  				"data":  m,
  1693  			}).Debug("sent")
  1694  			fsm.lock.RUnlock()
  1695  		}
  1696  		return nil
  1697  	}
  1698  
  1699  	for {
  1700  		select {
  1701  		case <-ctx.Done():
  1702  			return nil
  1703  		case o := <-h.outgoing.Out():
  1704  			switch m := o.(type) {
  1705  			case *fsmOutgoingMsg:
  1706  				h.fsm.lock.RLock()
  1707  				options := h.fsm.marshallingOptions
  1708  				h.fsm.lock.RUnlock()
  1709  				for _, msg := range table.CreateUpdateMsgFromPaths(m.Paths, options) {
  1710  					if err := send(msg); err != nil {
  1711  						return nil
  1712  					}
  1713  				}
  1714  				if m.Notification != nil {
  1715  					if m.StayIdle {
  1716  						// current user is only prefix-limit
  1717  						// fix me if this is not the case
  1718  						h.changeadminState(adminStatePfxCt)
  1719  					}
  1720  					if err := send(m.Notification); err != nil {
  1721  						return nil
  1722  					}
  1723  				}
  1724  			default:
  1725  				return nil
  1726  			}
  1727  		case <-ticker.C:
  1728  			if err := send(bgp.NewBGPKeepAliveMessage()); err != nil {
  1729  				return nil
  1730  			}
  1731  		}
  1732  	}
  1733  }
  1734  
  1735  func (h *fsmHandler) recvMessageloop(ctx context.Context, wg *sync.WaitGroup) error {
  1736  	defer wg.Done()
  1737  	for {
  1738  		fmsg, err := h.recvMessageWithError()
  1739  		if fmsg != nil {
  1740  			h.msgCh.In() <- fmsg
  1741  		}
  1742  		if err != nil {
  1743  			return nil
  1744  		}
  1745  	}
  1746  }
  1747  
  1748  func (h *fsmHandler) established(ctx context.Context) (bgp.FSMState, *fsmStateReason) {
  1749  	var wg sync.WaitGroup
  1750  	fsm := h.fsm
  1751  	fsm.lock.Lock()
  1752  	h.conn = fsm.conn
  1753  	fsm.lock.Unlock()
  1754  
  1755  	defer wg.Wait()
  1756  	wg.Add(2)
  1757  
  1758  	go h.sendMessageloop(ctx, &wg)
  1759  	h.msgCh = h.incoming
  1760  	go h.recvMessageloop(ctx, &wg)
  1761  
  1762  	var holdTimer *time.Timer
  1763  	if fsm.pConf.Timers.State.NegotiatedHoldTime == 0 {
  1764  		holdTimer = &time.Timer{}
  1765  	} else {
  1766  		fsm.lock.RLock()
  1767  		holdTimer = time.NewTimer(time.Second * time.Duration(fsm.pConf.Timers.State.NegotiatedHoldTime))
  1768  		fsm.lock.RUnlock()
  1769  	}
  1770  
  1771  	fsm.gracefulRestartTimer.Stop()
  1772  
  1773  	for {
  1774  		select {
  1775  		case <-ctx.Done():
  1776  			h.conn.Close()
  1777  			return -1, newfsmStateReason(fsmDying, nil, nil)
  1778  		case conn, ok := <-fsm.connCh:
  1779  			if !ok {
  1780  				break
  1781  			}
  1782  			conn.Close()
  1783  			fsm.lock.RLock()
  1784  			log.WithFields(log.Fields{
  1785  				"Topic": "Peer",
  1786  				"Key":   fsm.pConf.State.NeighborAddress,
  1787  				"State": fsm.state.String(),
  1788  			}).Warn("Closed an accepted connection")
  1789  			fsm.lock.RUnlock()
  1790  		case err := <-h.stateReasonCh:
  1791  			h.conn.Close()
  1792  			// if recv goroutine hit an error and sent to
  1793  			// stateReasonCh, then tx goroutine might take
  1794  			// long until it exits because it waits for
  1795  			// ctx.Done() or keepalive timer. So let kill
  1796  			// it now.
  1797  			h.outgoing.In() <- err
  1798  			fsm.lock.RLock()
  1799  			if s := fsm.pConf.GracefulRestart.State; s.Enabled &&
  1800  				(s.NotificationEnabled && err.Type == fsmNotificationRecv ||
  1801  					err.Type == fsmReadFailed ||
  1802  					err.Type == fsmWriteFailed) {
  1803  				err = *newfsmStateReason(fsmGracefulRestart, nil, nil)
  1804  				log.WithFields(log.Fields{
  1805  					"Topic": "Peer",
  1806  					"Key":   fsm.pConf.State.NeighborAddress,
  1807  					"State": fsm.state.String(),
  1808  				}).Info("peer graceful restart")
  1809  				fsm.gracefulRestartTimer.Reset(time.Duration(fsm.pConf.GracefulRestart.State.PeerRestartTime) * time.Second)
  1810  			}
  1811  			fsm.lock.RUnlock()
  1812  			return bgp.BGP_FSM_IDLE, &err
  1813  		case <-holdTimer.C:
  1814  			fsm.lock.RLock()
  1815  			log.WithFields(log.Fields{
  1816  				"Topic": "Peer",
  1817  				"Key":   fsm.pConf.State.NeighborAddress,
  1818  				"State": fsm.state.String(),
  1819  			}).Warn("hold timer expired")
  1820  			fsm.lock.RUnlock()
  1821  			m := bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_HOLD_TIMER_EXPIRED, 0, nil)
  1822  			h.outgoing.In() <- &fsmOutgoingMsg{Notification: m}
  1823  			return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmHoldTimerExpired, m, nil)
  1824  		case <-h.holdTimerResetCh:
  1825  			fsm.lock.RLock()
  1826  			if fsm.pConf.Timers.State.NegotiatedHoldTime != 0 {
  1827  				holdTimer.Reset(time.Second * time.Duration(fsm.pConf.Timers.State.NegotiatedHoldTime))
  1828  			}
  1829  			fsm.lock.RUnlock()
  1830  		case stateOp := <-fsm.adminStateCh:
  1831  			err := h.changeadminState(stateOp.State)
  1832  			if err == nil {
  1833  				switch stateOp.State {
  1834  				case adminStateDown:
  1835  					m := bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN, stateOp.Communication)
  1836  					h.outgoing.In() <- &fsmOutgoingMsg{Notification: m}
  1837  				}
  1838  			}
  1839  		}
  1840  	}
  1841  }
  1842  
  1843  func (h *fsmHandler) loop(ctx context.Context, wg *sync.WaitGroup) error {
  1844  	defer wg.Done()
  1845  
  1846  	fsm := h.fsm
  1847  	fsm.lock.RLock()
  1848  	oldState := fsm.state
  1849  	fsm.lock.RUnlock()
  1850  
  1851  	var reason *fsmStateReason
  1852  	nextState := bgp.FSMState(-1)
  1853  	fsm.lock.RLock()
  1854  	fsmState := fsm.state
  1855  	fsm.lock.RUnlock()
  1856  
  1857  	switch fsmState {
  1858  	case bgp.BGP_FSM_IDLE:
  1859  		nextState, reason = h.idle(ctx)
  1860  		// case bgp.BGP_FSM_CONNECT:
  1861  		// 	nextState = h.connect()
  1862  	case bgp.BGP_FSM_ACTIVE:
  1863  		nextState, reason = h.active(ctx)
  1864  	case bgp.BGP_FSM_OPENSENT:
  1865  		nextState, reason = h.opensent(ctx)
  1866  	case bgp.BGP_FSM_OPENCONFIRM:
  1867  		nextState, reason = h.openconfirm(ctx)
  1868  	case bgp.BGP_FSM_ESTABLISHED:
  1869  		nextState, reason = h.established(ctx)
  1870  	}
  1871  
  1872  	fsm.lock.RLock()
  1873  	fsm.reason = reason
  1874  
  1875  	if nextState == bgp.BGP_FSM_ESTABLISHED && oldState == bgp.BGP_FSM_OPENCONFIRM {
  1876  		log.WithFields(log.Fields{
  1877  			"Topic": "Peer",
  1878  			"Key":   fsm.pConf.State.NeighborAddress,
  1879  			"State": fsm.state.String(),
  1880  		}).Info("Peer Up")
  1881  	}
  1882  
  1883  	if oldState == bgp.BGP_FSM_ESTABLISHED {
  1884  		// The main goroutine sent the notificaiton due to
  1885  		// deconfiguration or something.
  1886  		reason := fsm.reason
  1887  		if fsm.h.sentNotification != nil {
  1888  			reason.Type = fsmNotificationSent
  1889  			reason.peerDownReason = peerDownByLocal
  1890  			reason.BGPNotification = fsm.h.sentNotification
  1891  		}
  1892  		log.WithFields(log.Fields{
  1893  			"Topic":  "Peer",
  1894  			"Key":    fsm.pConf.State.NeighborAddress,
  1895  			"State":  fsm.state.String(),
  1896  			"Reason": reason.String(),
  1897  		}).Info("Peer Down")
  1898  	}
  1899  	fsm.lock.RUnlock()
  1900  
  1901  	// under zero means that the context was canceled.
  1902  	if nextState >= bgp.BGP_FSM_IDLE {
  1903  		fsm.lock.RLock()
  1904  		h.stateCh <- &fsmMsg{
  1905  			MsgType:     fsmMsgStateChange,
  1906  			MsgSrc:      fsm.pConf.State.NeighborAddress,
  1907  			MsgData:     nextState,
  1908  			StateReason: reason,
  1909  			Version:     h.fsm.version,
  1910  		}
  1911  		fsm.lock.RUnlock()
  1912  	}
  1913  	return nil
  1914  }
  1915  
  1916  func (h *fsmHandler) changeadminState(s adminState) error {
  1917  	h.fsm.lock.Lock()
  1918  	defer h.fsm.lock.Unlock()
  1919  
  1920  	fsm := h.fsm
  1921  	if fsm.adminState != s {
  1922  		log.WithFields(log.Fields{
  1923  			"Topic":      "Peer",
  1924  			"Key":        fsm.pConf.State.NeighborAddress,
  1925  			"State":      fsm.state.String(),
  1926  			"adminState": s.String(),
  1927  		}).Debug("admin state changed")
  1928  
  1929  		fsm.adminState = s
  1930  		fsm.pConf.State.AdminDown = !fsm.pConf.State.AdminDown
  1931  
  1932  		switch s {
  1933  		case adminStateUp:
  1934  			log.WithFields(log.Fields{
  1935  				"Topic": "Peer",
  1936  				"Key":   fsm.pConf.State.NeighborAddress,
  1937  				"State": fsm.state.String(),
  1938  			}).Info("Administrative start")
  1939  		case adminStateDown:
  1940  			log.WithFields(log.Fields{
  1941  				"Topic": "Peer",
  1942  				"Key":   fsm.pConf.State.NeighborAddress,
  1943  				"State": fsm.state.String(),
  1944  			}).Info("Administrative shutdown")
  1945  		case adminStatePfxCt:
  1946  			log.WithFields(log.Fields{
  1947  				"Topic": "Peer",
  1948  				"Key":   fsm.pConf.State.NeighborAddress,
  1949  				"State": fsm.state.String(),
  1950  			}).Info("Administrative shutdown(Prefix limit reached)")
  1951  		}
  1952  
  1953  	} else {
  1954  		log.WithFields(log.Fields{
  1955  			"Topic": "Peer",
  1956  			"Key":   fsm.pConf.State.NeighborAddress,
  1957  			"State": fsm.state.String(),
  1958  		}).Warn("cannot change to the same state")
  1959  
  1960  		return fmt.Errorf("cannot change to the same state.")
  1961  	}
  1962  	return nil
  1963  }