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