Newer
Older
"github.com/bio-routing/bio-rd/config"
bnet "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/protocols/bgp/packet"
"github.com/bio-routing/bio-rd/routingtable"
"github.com/bio-routing/bio-rd/routingtable/locRIB"
type peer struct {
server *bgpServer
addr bnet.IP
localAddr bnet.IP
peerASN uint32
localASN uint32
// guarded by fsmsMu
fsms []*FSM
fsmsMu sync.Mutex
routerID uint32
reconnectInterval time.Duration
keepaliveTime time.Duration
holdTime time.Duration
optOpenParams []packet.OptParam
routeServerClient bool
routeReflectorClient bool
ipv4MultiProtocolAdvertised bool
clusterID uint32
ipv4 *peerAddressFamily
ipv6 *peerAddressFamily
type peerAddressFamily struct {
importFilter *filter.Filter
exportFilter *filter.Filter
addPathSend routingtable.ClientOptions
addPathReceive bool
func (p *peer) addressFamily(afi uint16, safi uint8) *peerAddressFamily {
if safi != packet.UnicastSAFI {
return nil
}
switch afi {
case packet.IPv4AFI:
return p.ipv4
case packet.IPv6AFI:
return p.ipv6
default:
return nil
}
}
func (p *peer) collisionHandling(callingFSM *FSM) bool {
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
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
// NewPeer creates a new peer with the given config. If an connection is established, the adjRIBIN of the peer is connected
// to the given rib. To actually connect the peer, call Start() on the returned peer.
func newPeer(c config.Peer, server *bgpServer) (*peer, error) {
if c.LocalAS == 0 {
c.LocalAS = server.localASN
}
server: server,
addr: c.PeerAddress,
peerASN: c.PeerAS,
localASN: c.LocalAS,
fsms: make([]*FSM, 0),
reconnectInterval: c.ReconnectInterval,
keepaliveTime: c.KeepAlive,
holdTime: c.HoldTime,
optOpenParams: make([]packet.OptParam, 0),
routeServerClient: c.RouteServerClient,
routeReflectorClient: c.RouteReflectorClient,
clusterID: c.RouteReflectorClusterID,
Maximilian Wilhelm
committed
importFilter: filterOrDefault(c.IPv4.ImportFilter),
exportFilter: filterOrDefault(c.IPv4.ExportFilter),
addPathReceive: c.IPv4.AddPathRecv,
addPathSend: c.IPv4.AddPathSend,
if p.ipv4.rib == nil {
return nil, fmt.Errorf("No RIB for IPv4 unicast configured")
}
Maximilian Wilhelm
committed
// If we are a route reflector and no ClusterID was set, use our RouterID
if p.routeReflectorClient && p.clusterID == 0 {
p.clusterID = c.RouterID
}
caps = append(caps, addPathCapabilities(c)...)
if c.IPv4 != nil && c.AdvertiseIPv4MultiProtocol {
caps = append(caps, multiProtocolCapability(packet.IPv4AFI))
p.ipv4MultiProtocolAdvertised = true
}
importFilter: filterOrDefault(c.IPv6.ImportFilter),
exportFilter: filterOrDefault(c.IPv6.ExportFilter),
addPathReceive: c.IPv6.AddPathRecv,
addPathSend: c.IPv6.AddPathSend,
caps = append(caps, multiProtocolCapability(packet.IPv6AFI))
if p.ipv6.rib == nil {
return nil, fmt.Errorf("No RIB for IPv6 unicast configured")
}
p.optOpenParams = append(p.optOpenParams, packet.OptParam{
Type: packet.CapabilitiesParamType,
Value: caps,
})
p.fsms = append(p.fsms, NewActiveFSM(p))
func asn4Capability(c config.Peer) packet.Capability {
return packet.Capability{
Code: packet.ASN4CapabilityCode,
Value: packet.ASN4Capability{
ASN4: c.LocalAS,
},
}
}
func multiProtocolCapability(afi uint16) packet.Capability {
return packet.Capability{
Code: packet.MultiProtocolCapabilityCode,
Value: packet.MultiProtocolCapability{
AFI: afi,
SAFI: packet.UnicastSAFI,
},
}
}
func addPathCapabilities(c config.Peer) []packet.Capability {
caps := make([]packet.Capability, 0)
enabled, cap := addPathCapabilityForFamily(c.IPv4, packet.IPv4AFI, packet.UnicastSAFI)
if enabled {
caps = append(caps, cap)
}
enabled, cap = addPathCapabilityForFamily(c.IPv6, packet.IPv6AFI, packet.UnicastSAFI)
if enabled {
caps = append(caps, cap)
}
return caps
}
func addPathCapabilityForFamily(f *config.AddressFamilyConfig, afi uint16, safi uint8) (enabled bool, cap packet.Capability) {
if f == nil {
return false, packet.Capability{}
}
addPath += packet.AddPathSend
}
if addPath == 0 {
Code: packet.AddPathCapabilityCode,
Value: packet.AddPathCapability{
SendReceive: addPath,
},
}
}
func filterOrDefault(f *filter.Filter) *filter.Filter {
if f != nil {
return f
}
return filter.NewDrainFilter()
}
// GetAddr returns the IP address of the peer
func (p *peer) GetAddr() bnet.IP {
func (p *peer) Start() {