Skip to content
Snippets Groups Projects
peer.go 2.76 KiB
Newer Older
  • Learn to ignore specific revisions
  • Oliver Herms's avatar
    Oliver Herms committed
    package server
    
    import (
    	"net"
    
    Oliver Herms's avatar
    Oliver Herms committed
    	"sync"
    	"time"
    
    Oliver Herms's avatar
    Oliver Herms committed
    
    
    	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
    	"github.com/bio-routing/bio-rd/routingtable"
    
    Oliver Herms's avatar
    Oliver Herms committed
    	"github.com/bio-routing/bio-rd/routingtable/filter"
    
    Oliver Herms's avatar
    Oliver Herms committed
    	"github.com/bio-routing/bio-rd/routingtable/locRIB"
    
    
    Oliver Herms's avatar
    Oliver Herms committed
    	"github.com/bio-routing/bio-rd/config"
    
    Oliver Herms's avatar
    Oliver Herms committed
    )
    
    type Peer struct {
    
    Oliver Herms's avatar
    Oliver Herms committed
    	server            *BGPServer
    	addr              net.IP
    	peerASN           uint32
    	localASN          uint32
    	fsms              []*FSM2
    	fsmsMu            sync.Mutex
    	rib               *locRIB.LocRIB
    	routerID          uint32
    	addPathSend       routingtable.ClientOptions
    	addPathRecv       bool
    	reconnectInterval time.Duration
    	keepaliveTime     time.Duration
    	holdTime          time.Duration
    	optOpenParams     []packet.OptParam
    	importFilter      *filter.Filter
    	exportFilter      *filter.Filter
    
    Oliver Herms's avatar
    Oliver Herms committed
    }
    
    
    Oliver Herms's avatar
    Oliver Herms committed
    func (p *Peer) collisionHandling(callingFSM *FSM2) bool {
    	p.fsmsMu.Lock()
    	defer p.fsmsMu.Unlock()
    
    	for _, fsm := range p.fsms {
    		if callingFSM == fsm {
    			continue
    		}
    
    		fsm.stateMu.RLock()
    		isEstablished := isEstablishedState(fsm.state)
    		isOpenConfirm := isOpenConfirmState(fsm.state)
    		fsm.stateMu.RUnlock()
    
    		if isEstablished {
    			return true
    		}
    
    		if !isOpenConfirm {
    			continue
    		}
    
    		if p.routerID < callingFSM.neighborID {
    			fsm.cease()
    		} else {
    			return true
    		}
    	}
    
    	return false
    }
    
    func isOpenConfirmState(s state) bool {
    	switch s.(type) {
    	case openConfirmState:
    		return true
    	}
    
    	return false
    }
    
    func isEstablishedState(s state) bool {
    	switch s.(type) {
    	case establishedState:
    		return true
    	}
    
    	return false
    }
    
    func NewPeer(c config.Peer, rib *locRIB.LocRIB, server *BGPServer) (*Peer, error) {
    
    Oliver Herms's avatar
    Oliver Herms committed
    	p := &Peer{
    
    Oliver Herms's avatar
    Oliver Herms committed
    		server:            server,
    		addr:              c.PeerAddress,
    		peerASN:           c.PeerAS,
    		localASN:          c.LocalAS,
    		fsms:              make([]*FSM2, 0),
    		rib:               rib,
    		addPathSend:       c.AddPathSend,
    		addPathRecv:       c.AddPathRecv,
    		reconnectInterval: c.ReconnectInterval,
    		keepaliveTime:     c.KeepAlive,
    		holdTime:          c.HoldTimer,
    		optOpenParams:     make([]packet.OptParam, 0),
    
    Oliver Herms's avatar
    Oliver Herms committed
    	}
    
    Oliver Herms's avatar
    Oliver Herms committed
    	p.fsms = append(p.fsms, NewActiveFSM2(p))
    
    
    	caps := make([]packet.Capability, 0)
    
    	addPath := uint8(0)
    
    Oliver Herms's avatar
    Oliver Herms committed
    	if c.AddPathRecv {
    
    		addPath += packet.AddPathReceive
    	}
    	if !c.AddPathSend.BestOnly {
    		addPath += packet.AddPathSend
    	}
    
    	if addPath > 0 {
    		caps = append(caps, packet.Capability{
    			Code: packet.AddPathCapabilityCode,
    			Value: packet.AddPathCapability{
    				AFI:         packet.IPv4AFI,
    				SAFI:        packet.UnicastSAFI,
    				SendReceive: addPath,
    			},
    		})
    	}
    
    	for _, cap := range caps {
    		p.optOpenParams = append(p.optOpenParams, packet.OptParam{
    			Type:  packet.CapabilitiesParamType,
    			Value: cap,
    		})
    	}
    
    
    Oliver Herms's avatar
    Oliver Herms committed
    	return p, nil
    }
    
    func (p *Peer) GetAddr() net.IP {
    	return p.addr
    }
    
    func (p *Peer) Start() {
    
    Oliver Herms's avatar
    Oliver Herms committed
    	p.fsms[0].start()
    
    Oliver Herms's avatar
    Oliver Herms committed
    }