diff --git a/protocols/bgp/server/fsm2.go b/protocols/bgp/server/fsm.go similarity index 93% rename from protocols/bgp/server/fsm2.go rename to protocols/bgp/server/fsm.go index 9b8163ab22dd53966f4efb25c38e1bfd7b826451..c4754257af98f0076e60a402b01f06966d4a0218 100644 --- a/protocols/bgp/server/fsm2.go +++ b/protocols/bgp/server/fsm.go @@ -219,13 +219,7 @@ func (fsm *FSM) resetConnectRetryCounter() { } func (fsm *FSM) sendOpen() error { - msg := packet.SerializeOpenMsg(&packet.BGPOpen{ - Version: BGPVersion, - ASN: uint16(fsm.peer.localASN), - HoldTime: uint16(fsm.peer.holdTime / time.Second), - BGPIdentifier: fsm.peer.server.routerID, - OptParams: fsm.peer.optOpenParams, - }) + msg := packet.SerializeOpenMsg(fsm.openMessage()) _, err := fsm.con.Write(msg) if err != nil { @@ -235,6 +229,24 @@ func (fsm *FSM) sendOpen() error { return nil } +func (fsm *FSM) openMessage() *packet.BGPOpen { + return &packet.BGPOpen{ + Version: BGPVersion, + ASN: fsm.local16BitASN(), + HoldTime: uint16(fsm.peer.holdTime / time.Second), + BGPIdentifier: fsm.peer.routerID, + OptParams: fsm.peer.optOpenParams, + } +} + +func (fsm *FSM) local16BitASN() uint16 { + if fsm.peer.localASN > uint32(^uint16(0)) { + return packet.ASTransASN + } + + return uint16(fsm.peer.localASN) +} + func (fsm *FSM) sendNotification(errorCode uint8, errorSubCode uint8) error { msg := packet.SerializeNotificationMsg(&packet.BGPNotification{}) diff --git a/protocols/bgp/server/fsm_test.go b/protocols/bgp/server/fsm_test.go new file mode 100644 index 0000000000000000000000000000000000000000..1dc8e9dd7288fabd8625a1b0bbb604401ab3aa86 --- /dev/null +++ b/protocols/bgp/server/fsm_test.go @@ -0,0 +1,98 @@ +package server + +import ( + "testing" + "time" + + "github.com/bio-routing/bio-rd/protocols/bgp/packet" + "github.com/stretchr/testify/assert" +) + +func TestOpenMessage(t *testing.T) { + tests := []struct { + name string + localASN uint32 + holdTime time.Duration + routerID uint32 + expected packet.BGPOpen + }{ + { + name: "16bit ASN", + localASN: 12345, + holdTime: time.Duration(30 * time.Second), + routerID: 1, + expected: packet.BGPOpen{ + ASN: 12345, + BGPIdentifier: 1, + HoldTime: 30, + OptParams: []packet.OptParam{ + packet.OptParam{ + Type: packet.CapabilitiesParamType, + Value: packet.Capabilities{ + packet.Capability{ + Code: 65, + Value: packet.ASN4Capability{ + ASN4: 12345, + }, + }, + }, + }, + }, + Version: 4, + }, + }, + { + name: "32bit ASN", + localASN: 202739, + holdTime: time.Duration(30 * time.Second), + routerID: 1, + expected: packet.BGPOpen{ + ASN: 23456, + BGPIdentifier: 1, + HoldTime: 30, + OptParams: []packet.OptParam{ + packet.OptParam{ + Type: packet.CapabilitiesParamType, + Value: packet.Capabilities{ + packet.Capability{ + Code: 65, + Value: packet.ASN4Capability{ + ASN4: 202739, + }, + }, + }, + }, + }, + Version: 4, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + p := Peer{ + localASN: test.localASN, + holdTime: test.holdTime, + routerID: test.routerID, + optOpenParams: []packet.OptParam{ + packet.OptParam{ + Type: packet.CapabilitiesParamType, + Value: packet.Capabilities{ + packet.Capability{ + Code: 65, + Value: packet.ASN4Capability{ + ASN4: test.localASN, + }, + }, + }, + }, + }, + } + + fsm := newFSM2(&p) + msg := fsm.openMessage() + + assert.Equal(t, &test.expected, msg) + }) + } +} diff --git a/protocols/bgp/server/peer.go b/protocols/bgp/server/peer.go index a0e4c623b5d4d30bdb877311c879b7c568332859..ba77f1756168dd9656812aa67c29e456c2587476 100644 --- a/protocols/bgp/server/peer.go +++ b/protocols/bgp/server/peer.go @@ -87,7 +87,6 @@ func NewPeer(c config.Peer, rib routingtable.RouteTableClient, server *BGPServer server: server, addr: c.PeerAddress, peerASN: c.PeerAS, - localASN: c.LocalAS, fsms: make([]*FSM, 0), rib: rib, addPathSend: c.AddPathSend, @@ -103,24 +102,12 @@ func NewPeer(c config.Peer, rib routingtable.RouteTableClient, server *BGPServer caps := make([]packet.Capability, 0) - addPath := uint8(0) - if c.AddPathRecv { - addPath += packet.AddPathReceive - } - if !c.AddPathSend.BestOnly { - addPath += packet.AddPathSend + addPathEnabled, addPathCap := handleAddPathCapability(c) + if addPathEnabled { + caps = append(caps, addPathCap) } - if addPath > 0 { - caps = append(caps, packet.Capability{ - Code: packet.AddPathCapabilityCode, - Value: packet.AddPathCapability{ - AFI: packet.IPv4AFI, - SAFI: packet.UnicastSAFI, - SendReceive: addPath, - }, - }) - } + caps = append(caps, asn4Capability(c)) for _, cap := range caps { p.optOpenParams = append(p.optOpenParams, packet.OptParam{ @@ -132,6 +119,38 @@ func NewPeer(c config.Peer, rib routingtable.RouteTableClient, server *BGPServer return p, nil } +func asn4Capability(c config.Peer) packet.Capability { + return packet.Capability{ + Code: packet.ASN4CapabilityCode, + Value: packet.ASN4Capability{ + ASN4: c.LocalAS, + }, + } +} + +func handleAddPathCapability(c config.Peer) (bool, packet.Capability) { + addPath := uint8(0) + if c.AddPathRecv { + addPath += packet.AddPathReceive + } + if !c.AddPathSend.BestOnly { + addPath += packet.AddPathSend + } + + if addPath == 0 { + return false, packet.Capability{} + } + + return true, packet.Capability{ + Code: packet.AddPathCapabilityCode, + Value: packet.AddPathCapability{ + AFI: packet.IPv4AFI, + SAFI: packet.UnicastSAFI, + SendReceive: addPath, + }, + } +} + func filterOrDefault(f *filter.Filter) *filter.Filter { if f != nil { return f