diff --git a/main.go b/main.go
index 7220ba4a6c669dd44368ccbc81c16e72c534d0d7..7c5bd7f1ba15450a5679688079307d3e0428e626 100644
--- a/main.go
+++ b/main.go
@@ -40,9 +40,9 @@ func main() {
 
 	b.AddPeer(config.Peer{
 		AdminEnabled:      true,
-		LocalAS:           6695,
+		LocalAS:           65200,
 		PeerAS:            65300,
-		PeerAddress:       net.IP([]byte{169, 254, 200, 1}),
+		PeerAddress:       net.IP([]byte{172, 17, 0, 3}),
 		LocalAddress:      net.IP([]byte{169, 254, 200, 0}),
 		ReconnectInterval: time.Second * 15,
 		HoldTime:          time.Second * 90,
@@ -59,9 +59,9 @@ func main() {
 
 	b.AddPeer(config.Peer{
 		AdminEnabled:      true,
-		LocalAS:           6695,
+		LocalAS:           65200,
 		PeerAS:            65100,
-		PeerAddress:       net.IP([]byte{169, 254, 100, 0}),
+		PeerAddress:       net.IP([]byte{172, 17, 0, 2}),
 		LocalAddress:      net.IP([]byte{169, 254, 100, 1}),
 		ReconnectInterval: time.Second * 15,
 		HoldTime:          time.Second * 90,
diff --git a/protocols/bgp/packet/BUILD.bazel b/protocols/bgp/packet/BUILD.bazel
index 10c8af2338d9c6ce76bb2f37d23355b04d21af69..66762a51dfcce62cd24b01dbc3d288dd7c26fbcf 100644
--- a/protocols/bgp/packet/BUILD.bazel
+++ b/protocols/bgp/packet/BUILD.bazel
@@ -9,6 +9,7 @@ go_library(
         "encoder.go",
         "large_community.go",
         "nlri.go",
+        "options.go",
         "parameters.go",
         "path_attribute_flags.go",
         "path_attributes.go",
diff --git a/protocols/bgp/packet/bgp.go b/protocols/bgp/packet/bgp.go
index 622b46f37b115dd27779a285284d177d75695230..8082f5dd8c02ae2c74a23013bcdb4c63d524d52b 100644
--- a/protocols/bgp/packet/bgp.go
+++ b/protocols/bgp/packet/bgp.go
@@ -92,9 +92,11 @@ const (
 	UnicastSAFI           = 1
 	CapabilitiesParamType = 2
 	AddPathCapabilityCode = 69
+	ASN4CapabilityCode    = 65
 	AddPathReceive        = 1
 	AddPathSend           = 2
 	AddPathSendReceive    = 3
+	ASTransASN            = 23456
 )
 
 type BGPError struct {
@@ -119,7 +121,7 @@ type BGPHeader struct {
 
 type BGPOpen struct {
 	Version       uint8
-	AS            uint16
+	ASN           uint16
 	HoldTime      uint16
 	BGPIdentifier uint32
 	OptParmLen    uint8
diff --git a/protocols/bgp/packet/decoder.go b/protocols/bgp/packet/decoder.go
index 31583bf1b68257625dfaa3d8b8e40893982d6713..c4d583f2138edfbbfb5b9be33b2a1c11764ee0bd 100644
--- a/protocols/bgp/packet/decoder.go
+++ b/protocols/bgp/packet/decoder.go
@@ -10,13 +10,13 @@ import (
 )
 
 // Decode decodes a BGP message
-func Decode(buf *bytes.Buffer) (*BGPMessage, error) {
+func Decode(buf *bytes.Buffer, opt *Options) (*BGPMessage, error) {
 	hdr, err := decodeHeader(buf)
 	if err != nil {
 		return nil, fmt.Errorf("Failed to decode header: %v", err)
 	}
 
-	body, err := decodeMsgBody(buf, hdr.Type, hdr.Length-MinLen)
+	body, err := decodeMsgBody(buf, hdr.Type, hdr.Length-MinLen, opt)
 	if err != nil {
 		return nil, fmt.Errorf("Failed to decode message: %v", err)
 	}
@@ -27,12 +27,12 @@ func Decode(buf *bytes.Buffer) (*BGPMessage, error) {
 	}, nil
 }
 
-func decodeMsgBody(buf *bytes.Buffer, msgType uint8, l uint16) (interface{}, error) {
+func decodeMsgBody(buf *bytes.Buffer, msgType uint8, l uint16, opt *Options) (interface{}, error) {
 	switch msgType {
 	case OpenMsg:
 		return decodeOpenMsg(buf)
 	case UpdateMsg:
-		return decodeUpdateMsg(buf, l)
+		return decodeUpdateMsg(buf, l, opt)
 	case KeepaliveMsg:
 		return nil, nil // Nothing to decode in Keepalive message
 	case NotificationMsg:
@@ -41,7 +41,7 @@ func decodeMsgBody(buf *bytes.Buffer, msgType uint8, l uint16) (interface{}, err
 	return nil, fmt.Errorf("Unknown message type: %d", msgType)
 }
 
-func decodeUpdateMsg(buf *bytes.Buffer, l uint16) (*BGPUpdate, error) {
+func decodeUpdateMsg(buf *bytes.Buffer, l uint16, opt *Options) (*BGPUpdate, error) {
 	msg := &BGPUpdate{}
 
 	err := decode(buf, []interface{}{&msg.WithdrawnRoutesLen})
@@ -59,7 +59,7 @@ func decodeUpdateMsg(buf *bytes.Buffer, l uint16) (*BGPUpdate, error) {
 		return msg, err
 	}
 
-	msg.PathAttributes, err = decodePathAttrs(buf, msg.TotalPathAttrLen)
+	msg.PathAttributes, err = decodePathAttrs(buf, msg.TotalPathAttrLen, opt)
 	if err != nil {
 		return msg, err
 	}
@@ -141,7 +141,7 @@ func _decodeOpenMsg(buf *bytes.Buffer) (interface{}, error) {
 
 	fields := []interface{}{
 		&msg.Version,
-		&msg.AS,
+		&msg.ASN,
 		&msg.HoldTime,
 		&msg.BGPIdentifier,
 		&msg.OptParmLen,
@@ -238,6 +238,12 @@ func decodeCapability(buf *bytes.Buffer) (Capability, error) {
 			return cap, fmt.Errorf("Unable to decode add path capability")
 		}
 		cap.Value = addPathCap
+	case ASN4CapabilityCode:
+		asn4Cap, err := decodeASN4Capability(buf)
+		if err != nil {
+			return cap, fmt.Errorf("Unable to decode 4 octet ASN capability")
+		}
+		cap.Value = asn4Cap
 	default:
 		for i := uint8(0); i < cap.Length; i++ {
 			_, err := buf.ReadByte()
@@ -266,6 +272,20 @@ func decodeAddPathCapability(buf *bytes.Buffer) (AddPathCapability, error) {
 	return addPathCap, nil
 }
 
+func decodeASN4Capability(buf *bytes.Buffer) (ASN4Capability, error) {
+	asn4Cap := ASN4Capability{}
+	fields := []interface{}{
+		&asn4Cap.ASN4,
+	}
+
+	err := decode(buf, fields)
+	if err != nil {
+		return asn4Cap, err
+	}
+
+	return asn4Cap, nil
+}
+
 func validateOpen(msg *BGPOpen) error {
 	if msg.Version != BGP4Version {
 		return BGPError{
diff --git a/protocols/bgp/packet/decoder_test.go b/protocols/bgp/packet/decoder_test.go
index a9ae237b9cb94a3e0ec6af0b988bc09f41d3f806..56416186ba1d714a13fb4f248281d3d5f48451dd 100644
--- a/protocols/bgp/packet/decoder_test.go
+++ b/protocols/bgp/packet/decoder_test.go
@@ -3,6 +3,7 @@ package packet
 import (
 	"bytes"
 	"fmt"
+	"strconv"
 	"testing"
 
 	"github.com/bio-routing/bio-rd/net"
@@ -70,7 +71,7 @@ func BenchmarkDecodeUpdateMsg(b *testing.B) {
 
 	for i := 0; i < b.N; i++ {
 		buf := bytes.NewBuffer(input)
-		_, err := decodeUpdateMsg(buf, uint16(len(input)))
+		_, err := decodeUpdateMsg(buf, uint16(len(input)), &Options{})
 		if err != nil {
 			fmt.Printf("decodeUpdateMsg failed: %v\n", err)
 		}
@@ -156,7 +157,7 @@ func TestDecode(t *testing.T) {
 				},
 				Body: &BGPOpen{
 					Version:       4,
-					AS:            200,
+					ASN:           200,
 					HoldTime:      15,
 					BGPIdentifier: uint32(169090600),
 					OptParmLen:    0,
@@ -184,7 +185,7 @@ func TestDecode(t *testing.T) {
 				},
 				Body: &BGPOpen{
 					Version:       4,
-					AS:            200,
+					ASN:           200,
 					HoldTime:      15,
 					BGPIdentifier: uint32(100),
 				},
@@ -251,7 +252,7 @@ func TestDecode(t *testing.T) {
 
 	for _, test := range tests {
 		buf := bytes.NewBuffer(test.input)
-		msg, err := Decode(buf)
+		msg, err := Decode(buf, &Options{})
 
 		if err != nil && !test.wantFail {
 			t.Errorf("Unexpected error in test %d: %v", test.testNum, err)
@@ -1369,9 +1370,9 @@ func TestDecodeUpdateMsg(t *testing.T) {
 		},
 		{
 			// 2 withdraws with four path attributes (Communities + AS4Path +AS4Aggregator + Origin), valid update
-			testNum: 19,
+			testNum: 20,
 			input: []byte{0, 5, 8, 10, 16, 192, 168,
-				0, 30, // Total Path Attribute Length
+				0, 32, // Total Path Attribute Length
 
 				0,          // Attribute flags
 				8,          // Attribute Type code (Community)
@@ -1379,10 +1380,12 @@ func TestDecodeUpdateMsg(t *testing.T) {
 				0, 0, 1, 0, // Arbitrary Community
 				0, 0, 1, 1, // Arbitrary Community
 
-				128,        // Attribute flags
-				17,         // Attribute Type code (AS4Path)
-				4,          // Length
-				0, 0, 2, 3, // Arbitrary Bytes
+				128,                    // Attribute flags
+				17,                     // Attribute Type code (AS4Path)
+				6,                      // Length
+				2,                      // AS_SEQUENCE
+				1,                      // Number of ASNs
+				0x00, 0x03, 0x17, 0xf3, // 202739
 
 				128,        // Attribute flags
 				18,         // Attribute Type code (AS4Aggregator)
@@ -1406,7 +1409,7 @@ func TestDecodeUpdateMsg(t *testing.T) {
 						Pfxlen: 16,
 					},
 				},
-				TotalPathAttrLen: 30,
+				TotalPathAttrLen: 32,
 				PathAttributes: &PathAttribute{
 					Optional:       false,
 					Transitive:     false,
@@ -1420,9 +1423,15 @@ func TestDecodeUpdateMsg(t *testing.T) {
 						Transitive:     false,
 						Partial:        false,
 						ExtendedLength: false,
-						Length:         4,
+						Length:         6,
 						TypeCode:       17,
-						Value:          uint32(515),
+						Value: ASPath{
+							ASPathSegment{
+								Type:  2,
+								Count: 1,
+								ASNs:  []uint32{202739},
+							},
+						},
 						Next: &PathAttribute{
 							Optional:       true,
 							Transitive:     false,
@@ -1447,29 +1456,31 @@ func TestDecodeUpdateMsg(t *testing.T) {
 		},
 	}
 
+	t.Parallel()
+
 	for _, test := range tests {
-		buf := bytes.NewBuffer(test.input)
-		l := test.explicitLength
-		if l == 0 {
-			l = uint16(len(test.input))
-		}
-		msg, err := decodeUpdateMsg(buf, l)
+		t.Run(strconv.Itoa(test.testNum), func(t *testing.T) {
+			buf := bytes.NewBuffer(test.input)
+			l := test.explicitLength
+			if l == 0 {
+				l = uint16(len(test.input))
+			}
+			msg, err := decodeUpdateMsg(buf, l, &Options{})
 
-		if err != nil && !test.wantFail {
-			t.Errorf("Unexpected error in test %d: %v", test.testNum, err)
-			continue
-		}
+			if err != nil && !test.wantFail {
+				t.Fatalf("Unexpected error in test %d: %v", test.testNum, err)
+			}
 
-		if err == nil && test.wantFail {
-			t.Errorf("Expected error did not happen in test %d", test.testNum)
-			continue
-		}
+			if err == nil && test.wantFail {
+				t.Fatalf("Expected error did not happen in test %d", test.testNum)
+			}
 
-		if err != nil && test.wantFail {
-			continue
-		}
+			if err != nil && test.wantFail {
+				return
+			}
 
-		assert.Equalf(t, test.expected, msg, "%d", test.testNum)
+			assert.Equalf(t, test.expected, msg, "%d", test.testNum)
+		})
 	}
 }
 
@@ -1490,7 +1501,7 @@ func TestDecodeMsgBody(t *testing.T) {
 	}
 
 	for _, test := range tests {
-		res, err := decodeMsgBody(test.buffer, test.msgType, test.length)
+		res, err := decodeMsgBody(test.buffer, test.msgType, test.length, &Options{})
 		if test.wantFail && err == nil {
 			t.Errorf("Expected error dit not happen in test %q", test.name)
 		}
@@ -1512,7 +1523,7 @@ func TestDecodeOpenMsg(t *testing.T) {
 			wantFail: false,
 			expected: &BGPOpen{
 				Version:       4,
-				AS:            257,
+				ASN:           257,
 				HoldTime:      15,
 				BGPIdentifier: 169090600,
 				OptParmLen:    0,
diff --git a/protocols/bgp/packet/encoder.go b/protocols/bgp/packet/encoder.go
index ea87d1ff64cfc946688e738ae9f7ffa372cf10c7..ac9bc4483199b81f4e8ecc25c6b91e3ec8361b9c 100644
--- a/protocols/bgp/packet/encoder.go
+++ b/protocols/bgp/packet/encoder.go
@@ -35,7 +35,7 @@ func SerializeOpenMsg(msg *BGPOpen) []byte {
 	serializeHeader(buf, openLen, OpenMsg)
 
 	buf.WriteByte(msg.Version)
-	buf.Write(convert.Uint16Byte(msg.AS))
+	buf.Write(convert.Uint16Byte(msg.ASN))
 	buf.Write(convert.Uint16Byte(msg.HoldTime))
 	buf.Write(convert.Uint32Byte(msg.BGPIdentifier))
 
@@ -63,7 +63,7 @@ func serializeHeader(buf *bytes.Buffer, length uint16, typ uint8) {
 	buf.WriteByte(typ)
 }
 
-func (b *BGPUpdateAddPath) SerializeUpdate() ([]byte, error) {
+func (b *BGPUpdateAddPath) SerializeUpdate(opt *Options) ([]byte, error) {
 	budget := MaxLen - MinLen
 	buf := bytes.NewBuffer(nil)
 
@@ -78,7 +78,7 @@ func (b *BGPUpdateAddPath) SerializeUpdate() ([]byte, error) {
 
 	pathAttributesBuf := bytes.NewBuffer(nil)
 	for pa := b.PathAttributes; pa != nil; pa = pa.Next {
-		paLen := int(pa.serialize(pathAttributesBuf))
+		paLen := int(pa.serialize(pathAttributesBuf, opt))
 		budget -= paLen
 		if budget < 0 {
 			return nil, fmt.Errorf("update too long")
@@ -122,7 +122,7 @@ func (b *BGPUpdateAddPath) SerializeUpdate() ([]byte, error) {
 	return buf.Bytes(), nil
 }
 
-func (b *BGPUpdate) SerializeUpdate() ([]byte, error) {
+func (b *BGPUpdate) SerializeUpdate(opt *Options) ([]byte, error) {
 	budget := MaxLen - MinLen
 	buf := bytes.NewBuffer(nil)
 
@@ -137,7 +137,7 @@ func (b *BGPUpdate) SerializeUpdate() ([]byte, error) {
 
 	pathAttributesBuf := bytes.NewBuffer(nil)
 	for pa := b.PathAttributes; pa != nil; pa = pa.Next {
-		paLen := int(pa.serialize(pathAttributesBuf))
+		paLen := int(pa.serialize(pathAttributesBuf, opt))
 		budget -= paLen
 		if budget < 0 {
 			return nil, fmt.Errorf("update too long")
diff --git a/protocols/bgp/packet/encoder_test.go b/protocols/bgp/packet/encoder_test.go
index 0d4f70a3483dabd8f7332dd148c72b09df626dee..fd7405d735a5d11a4117d144e7086828c86f5628 100644
--- a/protocols/bgp/packet/encoder_test.go
+++ b/protocols/bgp/packet/encoder_test.go
@@ -70,7 +70,7 @@ func TestSerializeOpenMsg(t *testing.T) {
 			name: "Valid #1",
 			input: &BGPOpen{
 				Version:       4,
-				AS:            15169,
+				ASN:           15169,
 				HoldTime:      120,
 				BGPIdentifier: convert.Uint32([]byte{100, 111, 120, 130}),
 				OptParmLen:    0,
diff --git a/protocols/bgp/packet/options.go b/protocols/bgp/packet/options.go
new file mode 100644
index 0000000000000000000000000000000000000000..b2d35bc60cbe17490f94314c28da26de9a19e40a
--- /dev/null
+++ b/protocols/bgp/packet/options.go
@@ -0,0 +1,5 @@
+package packet
+
+type Options struct {
+	Supports4OctetASN bool
+}
diff --git a/protocols/bgp/packet/parameters.go b/protocols/bgp/packet/parameters.go
index 8edf42fc58e05bb3b73cacd4272012844bedcd45..0ed9af66fe01f96600c02eeb2c00b69b11edc76c 100644
--- a/protocols/bgp/packet/parameters.go
+++ b/protocols/bgp/packet/parameters.go
@@ -52,3 +52,11 @@ func (a AddPathCapability) serialize(buf *bytes.Buffer) {
 	buf.WriteByte(a.SAFI)
 	buf.WriteByte(a.SendReceive)
 }
+
+type ASN4Capability struct {
+	ASN4 uint32
+}
+
+func (a ASN4Capability) serialize(buf *bytes.Buffer) {
+	buf.Write(convert.Uint32Byte(a.ASN4))
+}
diff --git a/protocols/bgp/packet/path_attributes.go b/protocols/bgp/packet/path_attributes.go
index 3b3192034590bd357b29a13833a2bcaaa632f0cf..acd5c78ab813c5b3cc6442f61067c85471366545 100644
--- a/protocols/bgp/packet/path_attributes.go
+++ b/protocols/bgp/packet/path_attributes.go
@@ -9,7 +9,7 @@ import (
 	"github.com/taktv6/tflow2/convert"
 )
 
-func decodePathAttrs(buf *bytes.Buffer, tpal uint16) (*PathAttribute, error) {
+func decodePathAttrs(buf *bytes.Buffer, tpal uint16, opt *Options) (*PathAttribute, error) {
 	var ret *PathAttribute
 	var eol *PathAttribute
 	var pa *PathAttribute
@@ -18,7 +18,7 @@ func decodePathAttrs(buf *bytes.Buffer, tpal uint16) (*PathAttribute, error) {
 
 	p := uint16(0)
 	for p < tpal {
-		pa, consumed, err = decodePathAttr(buf)
+		pa, consumed, err = decodePathAttr(buf, opt)
 		if err != nil {
 			return nil, fmt.Errorf("Unable to decode path attr: %v", err)
 		}
@@ -36,7 +36,7 @@ func decodePathAttrs(buf *bytes.Buffer, tpal uint16) (*PathAttribute, error) {
 	return ret, nil
 }
 
-func decodePathAttr(buf *bytes.Buffer) (pa *PathAttribute, consumed uint16, err error) {
+func decodePathAttr(buf *bytes.Buffer, opt *Options) (pa *PathAttribute, consumed uint16, err error) {
 	pa = &PathAttribute{}
 
 	err = decodePathAttrFlags(buf, pa)
@@ -63,9 +63,18 @@ func decodePathAttr(buf *bytes.Buffer) (pa *PathAttribute, consumed uint16, err
 			return nil, consumed, fmt.Errorf("Failed to decode Origin: %v", err)
 		}
 	case ASPathAttr:
-		if err := pa.decodeASPath(buf); err != nil {
+		asnLength := uint8(2)
+		if opt.Supports4OctetASN {
+			asnLength = 4
+		}
+
+		if err := pa.decodeASPath(buf, asnLength); err != nil {
 			return nil, consumed, fmt.Errorf("Failed to decode AS Path: %v", err)
 		}
+	case AS4PathAttr:
+		if err := pa.decodeASPath(buf, 4); err != nil {
+			return nil, consumed, fmt.Errorf("Failed to decode AS4 Path: %v", err)
+		}
 	case NextHopAttr:
 		if err := pa.decodeNextHop(buf); err != nil {
 			return nil, consumed, fmt.Errorf("Failed to decode Next-Hop: %v", err)
@@ -88,10 +97,6 @@ func decodePathAttr(buf *bytes.Buffer) (pa *PathAttribute, consumed uint16, err
 		if err := pa.decodeCommunities(buf); err != nil {
 			return nil, consumed, fmt.Errorf("Failed to decode Community: %v", err)
 		}
-	case AS4PathAttr:
-		if err := pa.decodeAS4Path(buf); err != nil {
-			return nil, consumed, fmt.Errorf("Failed to skip not supported AS4Path: %v", err)
-		}
 	case AS4AggregatorAttr:
 		if err := pa.decodeAS4Aggregator(buf); err != nil {
 			return nil, consumed, fmt.Errorf("Failed to skip not supported AS4Aggregator: %v", err)
@@ -139,14 +144,11 @@ func (pa *PathAttribute) decodeOrigin(buf *bytes.Buffer) error {
 	return dumpNBytes(buf, pa.Length-p)
 }
 
-func (pa *PathAttribute) decodeASPath(buf *bytes.Buffer) error {
+func (pa *PathAttribute) decodeASPath(buf *bytes.Buffer, asnLength uint8) error {
 	pa.Value = make(ASPath, 0)
-
 	p := uint16(0)
 	for p < pa.Length {
-		segment := ASPathSegment{
-			ASNs: make([]uint32, 0),
-		}
+		segment := ASPathSegment{}
 
 		err := decode(buf, []interface{}{&segment.Type, &segment.Count})
 		if err != nil {
@@ -162,23 +164,51 @@ func (pa *PathAttribute) decodeASPath(buf *bytes.Buffer) error {
 			return fmt.Errorf("Invalid AS Path segment length: %d", segment.Count)
 		}
 
+		segment.ASNs = make([]uint32, segment.Count)
 		for i := uint8(0); i < segment.Count; i++ {
-			asn := uint16(0)
-
-			err := decode(buf, []interface{}{&asn})
+			asn, err := pa.decodeASN(buf, asnLength)
 			if err != nil {
 				return err
 			}
-			p += 2
+			p += uint16(asnLength)
 
-			segment.ASNs = append(segment.ASNs, uint32(asn))
+			segment.ASNs[i] = asn
 		}
+
 		pa.Value = append(pa.Value.(ASPath), segment)
 	}
 
 	return nil
 }
 
+func (pa *PathAttribute) decodeASN(buf *bytes.Buffer, asnSize uint8) (asn uint32, err error) {
+	if asnSize == 4 {
+		return pa.decode4ByteASN(buf)
+	}
+
+	return pa.decode2ByteASN(buf)
+}
+
+func (pa *PathAttribute) decode4ByteASN(buf *bytes.Buffer) (asn uint32, err error) {
+	asn4 := uint32(0)
+	err = decode(buf, []interface{}{&asn4})
+	if err != nil {
+		return 0, err
+	}
+
+	return uint32(asn4), nil
+}
+
+func (pa *PathAttribute) decode2ByteASN(buf *bytes.Buffer) (asn uint32, err error) {
+	asn4 := uint16(0)
+	err = decode(buf, []interface{}{&asn4})
+	if err != nil {
+		return 0, err
+	}
+
+	return uint32(asn4), nil
+}
+
 func (pa *PathAttribute) decodeNextHop(buf *bytes.Buffer) error {
 	return pa.decodeUint32(buf, "next hop")
 }
@@ -273,10 +303,6 @@ func (pa *PathAttribute) decodeLargeCommunities(buf *bytes.Buffer) error {
 	return nil
 }
 
-func (pa *PathAttribute) decodeAS4Path(buf *bytes.Buffer) error {
-	return pa.decodeUint32(buf, "AS4Path")
-}
-
 func (pa *PathAttribute) decodeAS4Aggregator(buf *bytes.Buffer) error {
 	return pa.decodeUint32(buf, "AS4Aggregator")
 }
@@ -383,14 +409,14 @@ func dumpNBytes(buf *bytes.Buffer, n uint16) error {
 	return nil
 }
 
-func (pa *PathAttribute) serialize(buf *bytes.Buffer) uint8 {
+func (pa *PathAttribute) serialize(buf *bytes.Buffer, opt *Options) uint8 {
 	pathAttrLen := uint8(0)
 
 	switch pa.TypeCode {
 	case OriginAttr:
 		pathAttrLen = pa.serializeOrigin(buf)
 	case ASPathAttr:
-		pathAttrLen = pa.serializeASPath(buf)
+		pathAttrLen = pa.serializeASPath(buf, opt)
 	case NextHopAttr:
 		pathAttrLen = pa.serializeNextHop(buf)
 	case MEDAttr:
@@ -421,21 +447,32 @@ func (pa *PathAttribute) serializeOrigin(buf *bytes.Buffer) uint8 {
 	return 4
 }
 
-func (pa *PathAttribute) serializeASPath(buf *bytes.Buffer) uint8 {
+func (pa *PathAttribute) serializeASPath(buf *bytes.Buffer, opt *Options) uint8 {
 	attrFlags := uint8(0)
 	attrFlags = setTransitive(attrFlags)
 	buf.WriteByte(attrFlags)
 	buf.WriteByte(ASPathAttr)
 
+	asnLength := uint8(2)
+	if opt.Supports4OctetASN {
+		asnLength = 4
+	}
+
 	length := uint8(0)
 	segmentsBuf := bytes.NewBuffer(nil)
 	for _, segment := range pa.Value.(ASPath) {
 		segmentsBuf.WriteByte(segment.Type)
 		segmentsBuf.WriteByte(uint8(len(segment.ASNs)))
+
 		for _, asn := range segment.ASNs {
-			segmentsBuf.Write(convert.Uint16Byte(uint16(asn)))
+			if asnLength == 2 {
+				segmentsBuf.Write(convert.Uint16Byte(uint16(asn)))
+			} else {
+				segmentsBuf.Write(convert.Uint32Byte(asn))
+			}
 		}
-		length += 2 + uint8(len(segment.ASNs))*2
+		fmt.Println(segment.ASNs)
+		length += 2 + uint8(len(segment.ASNs))*asnLength
 	}
 
 	buf.WriteByte(length)
diff --git a/protocols/bgp/packet/path_attributes_test.go b/protocols/bgp/packet/path_attributes_test.go
index 248b731714389096a62e2381a548780beb8318e7..c3d5ecda2e4d484ba48809651248e4ecd1c82188 100644
--- a/protocols/bgp/packet/path_attributes_test.go
+++ b/protocols/bgp/packet/path_attributes_test.go
@@ -50,7 +50,7 @@ func TestDecodePathAttrs(t *testing.T) {
 	}
 
 	for _, test := range tests {
-		res, err := decodePathAttrs(bytes.NewBuffer(test.input), uint16(len(test.input)))
+		res, err := decodePathAttrs(bytes.NewBuffer(test.input), uint16(len(test.input)), &Options{})
 
 		if test.wantFail && err == nil {
 			t.Errorf("Expected error did not happen for test %q", test.name)
@@ -173,7 +173,7 @@ func TestDecodePathAttr(t *testing.T) {
 	}
 
 	for _, test := range tests {
-		res, _, err := decodePathAttr(bytes.NewBuffer(test.input))
+		res, _, err := decodePathAttr(bytes.NewBuffer(test.input), &Options{})
 
 		if test.wantFail && err == nil {
 			t.Errorf("Expected error did not happen for test %q", test.name)
@@ -264,6 +264,7 @@ func TestDecodeASPath(t *testing.T) {
 		input          []byte
 		wantFail       bool
 		explicitLength uint16
+		use4OctetASNs  bool
 		expected       *PathAttribute
 	}{
 		{
@@ -308,6 +309,28 @@ func TestDecodeASPath(t *testing.T) {
 				},
 			},
 		},
+		{
+			name: "32 bit ASNs in AS_PATH",
+			input: []byte{
+				1, // AS_SEQUENCE
+				3, // Path Length
+				0, 0, 0, 100, 0, 0, 0, 222, 0, 0, 0, 240,
+			},
+			wantFail:      false,
+			use4OctetASNs: true,
+			expected: &PathAttribute{
+				Length: 14,
+				Value: ASPath{
+					ASPathSegment{
+						Type:  1,
+						Count: 3,
+						ASNs: []uint32{
+							100, 222, 240,
+						},
+					},
+				},
+			},
+		},
 		{
 			name:           "Empty input",
 			input:          []byte{},
@@ -326,28 +349,36 @@ func TestDecodeASPath(t *testing.T) {
 	}
 
 	for _, test := range tests {
-		l := uint16(len(test.input))
-		if test.explicitLength != 0 {
-			l = test.explicitLength
-		}
-		pa := &PathAttribute{
-			Length: l,
-		}
-		err := pa.decodeASPath(bytes.NewBuffer(test.input))
+		t.Run(test.name, func(t *testing.T) {
+			l := uint16(len(test.input))
+			if test.explicitLength != 0 {
+				l = test.explicitLength
+			}
+			pa := &PathAttribute{
+				Length: l,
+			}
 
-		if test.wantFail && err == nil {
-			t.Errorf("Expected error did not happen for test %q", test.name)
-		}
+			asnLength := uint8(2)
+			if test.use4OctetASNs {
+				asnLength = 4
+			}
 
-		if !test.wantFail && err != nil {
-			t.Errorf("Unexpected failure for test %q: %v", test.name, err)
-		}
+			err := pa.decodeASPath(bytes.NewBuffer(test.input), asnLength)
 
-		if err != nil {
-			continue
-		}
+			if test.wantFail && err == nil {
+				t.Errorf("Expected error did not happen for test %q", test.name)
+			}
 
-		assert.Equal(t, test.expected, pa)
+			if !test.wantFail && err != nil {
+				t.Errorf("Unexpected failure for test %q: %v", test.name, err)
+			}
+
+			if err != nil {
+				return
+			}
+
+			assert.Equal(t, test.expected, pa)
+		})
 	}
 }
 
@@ -1239,6 +1270,7 @@ func TestSerializeASPath(t *testing.T) {
 		input       *PathAttribute
 		expected    []byte
 		expectedLen uint8
+		use32BitASN bool
 	}{
 		{
 			name: "Test #1",
@@ -1265,17 +1297,49 @@ func TestSerializeASPath(t *testing.T) {
 			},
 			expectedLen: 10,
 		},
+		{
+			name: "32bit ASN",
+			input: &PathAttribute{
+				TypeCode: ASPathAttr,
+				Value: ASPath{
+					{
+						Type: 2, // Sequence
+						ASNs: []uint32{
+							100, 200, 210,
+						},
+					},
+				},
+			},
+			expected: []byte{
+				64,           // Attribute flags
+				2,            // Type
+				14,           // Length
+				2,            // AS_SEQUENCE
+				3,            // ASN count
+				0, 0, 0, 100, // ASN 100
+				0, 0, 0, 200, // ASN 200
+				0, 0, 0, 210, // ASN 210
+			},
+			expectedLen: 16,
+			use32BitASN: true,
+		},
 	}
 
+	t.Parallel()
+
 	for _, test := range tests {
-		buf := bytes.NewBuffer(nil)
-		n := test.input.serializeASPath(buf)
-		if n != test.expectedLen {
-			t.Errorf("Unexpected length for test %q: %d", test.name, n)
-			continue
-		}
+		t.Run(test.name, func(t *testing.T) {
+			buf := bytes.NewBuffer(nil)
+			opt := &Options{
+				Supports4OctetASN: test.use32BitASN,
+			}
+			n := test.input.serializeASPath(buf, opt)
+			if n != test.expectedLen {
+				t.Fatalf("Unexpected length for test %q: %d", test.name, n)
+			}
 
-		assert.Equal(t, test.expected, buf.Bytes())
+			assert.Equal(t, test.expected, buf.Bytes())
+		})
 	}
 }
 
@@ -1561,7 +1625,8 @@ func TestSerialize(t *testing.T) {
 	}
 
 	for _, test := range tests {
-		res, err := test.msg.SerializeUpdate()
+		opt := &Options{}
+		res, err := test.msg.SerializeUpdate(opt)
 		if err != nil {
 			if test.wantFail {
 				continue
@@ -1767,7 +1832,8 @@ func TestSerializeAddPath(t *testing.T) {
 	}
 
 	for _, test := range tests {
-		res, err := test.msg.SerializeUpdate()
+		opt := &Options{}
+		res, err := test.msg.SerializeUpdate(opt)
 		if err != nil {
 			if test.wantFail {
 				continue
diff --git a/protocols/bgp/server/BUILD.bazel b/protocols/bgp/server/BUILD.bazel
index a82fe9fb50cdd5b85b8e219da7b264c4cba06ef4..345c18806a64e01267a63dc585e74864867db36a 100644
--- a/protocols/bgp/server/BUILD.bazel
+++ b/protocols/bgp/server/BUILD.bazel
@@ -41,6 +41,8 @@ go_library(
 go_test(
     name = "go_default_test",
     srcs = [
+        "fsm_open_sent_test.go",
+        "fsm_test.go",
         "server_test.go",
         "update_helper_test.go",
         "withdraw_test.go",
diff --git a/protocols/bgp/server/fsm.go b/protocols/bgp/server/fsm.go
index 0c5221391c80e1dbd7bf1262d2506192eba80924..cf970b40483511c2ecafc1d36597f66117de06ef 100644
--- a/protocols/bgp/server/fsm.go
+++ b/protocols/bgp/server/fsm.go
@@ -57,6 +57,8 @@ type FSM struct {
 	capAddPathSend bool
 	capAddPathRecv bool
 
+	options *packet.Options
+
 	local net.IP
 
 	ribsInitialized bool
@@ -100,6 +102,7 @@ func newFSM2(peer *peer) *FSM {
 		msgRecvFailCh:    make(chan error),
 		stopMsgRecvCh:    make(chan struct{}),
 		rib:              peer.rib,
+		options:          &packet.Options{},
 	}
 }
 
@@ -220,13 +223,7 @@ func (fsm *FSM) resetConnectRetryCounter() {
 }
 
 func (fsm *FSM) sendOpen() error {
-	msg := packet.SerializeOpenMsg(&packet.BGPOpen{
-		Version:       BGPVersion,
-		AS:            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 {
@@ -236,6 +233,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_established.go b/protocols/bgp/server/fsm_established.go
index 58facab0cd4ad487245cfe431a73478d3ca455a8..66480407dc7e39e174b4f391017bfdc8c9f2e05f 100644
--- a/protocols/bgp/server/fsm_established.go
+++ b/protocols/bgp/server/fsm_established.go
@@ -158,7 +158,7 @@ func (s *establishedState) keepaliveTimerExpired() (state, string) {
 }
 
 func (s *establishedState) msgReceived(data []byte) (state, string) {
-	msg, err := packet.Decode(bytes.NewBuffer(data))
+	msg, err := packet.Decode(bytes.NewBuffer(data), s.fsm.options)
 	if err != nil {
 		switch bgperr := err.(type) {
 		case packet.BGPError:
diff --git a/protocols/bgp/server/fsm_open_confirm.go b/protocols/bgp/server/fsm_open_confirm.go
index d2d25e4f533ec30d9a5d15aec25504d055c45f54..07b8a6152dd64c56055c7cbd0745980e462c3886 100644
--- a/protocols/bgp/server/fsm_open_confirm.go
+++ b/protocols/bgp/server/fsm_open_confirm.go
@@ -82,7 +82,7 @@ func (s *openConfirmState) keepaliveTimerExpired() (state, string) {
 }
 
 func (s *openConfirmState) msgReceived(data []byte) (state, string) {
-	msg, err := packet.Decode(bytes.NewBuffer(data))
+	msg, err := packet.Decode(bytes.NewBuffer(data), s.fsm.options)
 	if err != nil {
 		switch bgperr := err.(type) {
 		case packet.BGPError:
diff --git a/protocols/bgp/server/fsm_open_sent.go b/protocols/bgp/server/fsm_open_sent.go
index 63680636d8e0c65afe1dad9ec9d1280c34e9c37d..848c76697fb3a415b7e56131b67d3576d0e01722 100644
--- a/protocols/bgp/server/fsm_open_sent.go
+++ b/protocols/bgp/server/fsm_open_sent.go
@@ -10,7 +10,8 @@ import (
 )
 
 type openSentState struct {
-	fsm *FSM
+	fsm         *FSM
+	peerASNRcvd uint32
 }
 
 func newOpenSentState(fsm *FSM) *openSentState {
@@ -73,7 +74,7 @@ func (s *openSentState) holdTimerExpired() (state, string) {
 }
 
 func (s *openSentState) msgReceived(data []byte) (state, string) {
-	msg, err := packet.Decode(bytes.NewBuffer(data))
+	msg, err := packet.Decode(bytes.NewBuffer(data), s.fsm.options)
 	if err != nil {
 		switch bgperr := err.(type) {
 		case packet.BGPError:
@@ -104,6 +105,8 @@ func (s *openSentState) unexpectedMessage() (state, string) {
 
 func (s *openSentState) openMsgReceived(msg *packet.BGPMessage) (state, string) {
 	openMsg := msg.Body.(*packet.BGPOpen)
+	s.peerASNRcvd = uint32(openMsg.ASN)
+
 	s.fsm.neighborID = openMsg.BGPIdentifier
 	stopTimer(s.fsm.connectRetryTimer)
 	if s.fsm.peer.collisionHandling(s.fsm) {
@@ -114,6 +117,10 @@ func (s *openSentState) openMsgReceived(msg *packet.BGPMessage) (state, string)
 		return s.tcpFailure()
 	}
 
+	return s.handleOpenMessage(openMsg)
+}
+
+func (s *openSentState) handleOpenMessage(openMsg *packet.BGPOpen) (state, string) {
 	s.fsm.holdTime = time.Duration(math.Min(float64(s.fsm.peer.holdTime), float64(time.Duration(openMsg.HoldTime)*time.Second)))
 	if s.fsm.holdTime != 0 {
 		if !s.fsm.holdTimer.Reset(s.fsm.holdTime) {
@@ -123,7 +130,13 @@ func (s *openSentState) openMsgReceived(msg *packet.BGPMessage) (state, string)
 		s.fsm.keepaliveTimer = time.NewTimer(s.fsm.keepaliveTime)
 	}
 
+	s.peerASNRcvd = uint32(openMsg.ASN)
 	s.processOpenOptions(openMsg.OptParams)
+
+	if s.peerASNRcvd != s.fsm.peer.peerASN {
+		return newCeaseState(), fmt.Sprintf("Expected session from %d, got open message with ASN %d", s.fsm.peer.peerASN, s.peerASNRcvd)
+	}
+
 	return newOpenConfirmState(s.fsm), "Received OPEN message"
 }
 
@@ -153,7 +166,8 @@ func (s *openSentState) processCapability(cap packet.Capability) {
 	switch cap.Code {
 	case packet.AddPathCapabilityCode:
 		s.processAddPathCapability(cap.Value.(packet.AddPathCapability))
-
+	case packet.ASN4CapabilityCode:
+		s.processASN4Capability(cap.Value.(packet.ASN4Capability))
 	}
 }
 
@@ -184,6 +198,14 @@ func (s *openSentState) processAddPathCapability(addPathCap packet.AddPathCapabi
 	}
 }
 
+func (s *openSentState) processASN4Capability(cap packet.ASN4Capability) {
+	s.fsm.options.Supports4OctetASN = true
+
+	if s.peerASNRcvd == packet.ASTransASN {
+		s.peerASNRcvd = cap.ASN4
+	}
+}
+
 func (s *openSentState) notification(msg *packet.BGPMessage) (state, string) {
 	stopTimer(s.fsm.connectRetryTimer)
 	s.fsm.con.Close()
diff --git a/protocols/bgp/server/fsm_open_sent_test.go b/protocols/bgp/server/fsm_open_sent_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..39057c6480f84c21d025e335cd95b2c7b34b2b08
--- /dev/null
+++ b/protocols/bgp/server/fsm_open_sent_test.go
@@ -0,0 +1,87 @@
+package server
+
+import (
+	"testing"
+
+	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestOpenMsgReceived(t *testing.T) {
+	tests := []struct {
+		asn        uint32
+		name       string
+		msg        packet.BGPOpen
+		wantsCease bool
+	}{
+		{
+			name: "valid open message (16bit ASN)",
+			asn:  12345,
+			msg: packet.BGPOpen{
+				HoldTime:      90,
+				BGPIdentifier: 1,
+				Version:       4,
+				ASN:           12345,
+			},
+		},
+		{
+			name: "valid open message (32bit ASN)",
+			asn:  202739,
+			msg: packet.BGPOpen{
+				HoldTime:      90,
+				BGPIdentifier: 1,
+				Version:       4,
+				ASN:           23456,
+				OptParmLen:    1,
+				OptParams: []packet.OptParam{
+					{
+						Type:   packet.CapabilitiesParamType,
+						Length: 6,
+						Value: packet.Capabilities{
+							packet.Capability{
+								Code:   packet.ASN4CapabilityCode,
+								Length: 4,
+								Value: packet.ASN4Capability{
+									ASN4: 202739,
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "open message does not match configured remote ASN",
+			asn:  12345,
+			msg: packet.BGPOpen{
+				HoldTime:      90,
+				BGPIdentifier: 1,
+				Version:       4,
+				ASN:           54321,
+			},
+			wantsCease: true,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			fsm := newFSM2(&peer{
+				peerASN: test.asn,
+			})
+
+			s := &openSentState{
+				fsm: fsm,
+			}
+
+			state, _ := s.handleOpenMessage(&test.msg)
+
+			if test.wantsCease {
+				assert.IsType(t, &ceaseState{}, state, "state")
+				return
+			}
+
+			assert.IsType(t, &openConfirmState{}, state, "state")
+			assert.Equal(t, test.asn, s.peerASNRcvd, "asn")
+		})
+	}
+}
diff --git a/protocols/bgp/server/fsm_test.go b/protocols/bgp/server/fsm_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..c0b293936118c345060049cfcee77a4325861741
--- /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 3e5e6aeea408d1be12c4fd1ca38b6e62ba2af3b4..fe12b36d485879278df074456027c73f4149b910 100644
--- a/protocols/bgp/server/peer.go
+++ b/protocols/bgp/server/peer.go
@@ -127,24 +127,12 @@ func newPeer(c config.Peer, rib *locRIB.LocRIB, server *bgpServer) (*peer, error
 
 	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{
@@ -156,6 +144,38 @@ func newPeer(c config.Peer, rib *locRIB.LocRIB, server *bgpServer) (*peer, error
 	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
diff --git a/protocols/bgp/server/server.go b/protocols/bgp/server/server.go
index f0354f7ed1587ffd2ec84132ec50e117edfb72bb..4015f44b78b834f9793fd8c469f1c0fd6d25e6df 100644
--- a/protocols/bgp/server/server.go
+++ b/protocols/bgp/server/server.go
@@ -15,7 +15,6 @@ import (
 )
 
 const (
-	uint16max  = 65535
 	BGPVersion = 4
 )
 
@@ -115,10 +114,6 @@ func (b *bgpServer) incomingConnectionWorker() {
 }
 
 func (b *bgpServer) AddPeer(c config.Peer, rib *locRIB.LocRIB) error {
-	if c.LocalAS > uint16max || c.PeerAS > uint16max {
-		return fmt.Errorf("32bit ASNs are not supported yet")
-	}
-
 	peer, err := newPeer(c, rib, b)
 	if err != nil {
 		return err
diff --git a/protocols/bgp/server/update_helper.go b/protocols/bgp/server/update_helper.go
index e0a24a6e3bbf1369b59b25d04f1f6c3c16930844..c45181803ee3c5c54f777cfbb66e7d3ad6831d53 100644
--- a/protocols/bgp/server/update_helper.go
+++ b/protocols/bgp/server/update_helper.go
@@ -72,11 +72,11 @@ func addOptionalPathAttribues(p *route.Path, parent *packet.PathAttribute) error
 }
 
 type serializeAbleUpdate interface {
-	SerializeUpdate() ([]byte, error)
+	SerializeUpdate(opt *packet.Options) ([]byte, error)
 }
 
-func serializeAndSendUpdate(out io.Writer, update serializeAbleUpdate) error {
-	updateBytes, err := update.SerializeUpdate()
+func serializeAndSendUpdate(out io.Writer, update serializeAbleUpdate, opt *packet.Options) error {
+	updateBytes, err := update.SerializeUpdate(opt)
 	if err != nil {
 		log.Errorf("Unable to serialize BGP Update: %v", err)
 		return nil
diff --git a/protocols/bgp/server/update_helper_test.go b/protocols/bgp/server/update_helper_test.go
index 5752edded4aba03b66acd88950796e21c2c82620..d2d0a7fcf424276b6a351176cebc9a3959f9ec69 100644
--- a/protocols/bgp/server/update_helper_test.go
+++ b/protocols/bgp/server/update_helper_test.go
@@ -16,7 +16,7 @@ import (
 
 type failingUpdate struct{}
 
-func (f *failingUpdate) SerializeUpdate() ([]byte, error) {
+func (f *failingUpdate) SerializeUpdate(opt *packet.Options) ([]byte, error) {
 	return nil, errors.New("general error")
 }
 
@@ -94,12 +94,12 @@ func TestSerializeAndSendUpdate(t *testing.T) {
 	}
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
-			err := serializeAndSendUpdate(test.buf, test.testUpdate)
+			opt := &packet.Options{}
+			err := serializeAndSendUpdate(test.buf, test.testUpdate, opt)
 			assert.Equal(t, test.err, err)
 
 			assert.Equal(t, test.expected, test.buf.Bytes())
 		})
-
 	}
 }
 
diff --git a/protocols/bgp/server/update_sender.go b/protocols/bgp/server/update_sender.go
index 67fb6662febaec64942dd48c6164ad00b0441bc4..a6ae74afeb29d7e5c3b4ec9538a6ecc18ffce32f 100644
--- a/protocols/bgp/server/update_sender.go
+++ b/protocols/bgp/server/update_sender.go
@@ -42,12 +42,12 @@ func (u *UpdateSender) AddPath(pfx net.Prefix, p *route.Path) error {
 		},
 	}
 
-	return serializeAndSendUpdate(u.fsm.con, update)
+	return serializeAndSendUpdate(u.fsm.con, update, u.fsm.options)
 }
 
 // RemovePath withdraws prefix `pfx` from a peer
 func (u *UpdateSender) RemovePath(pfx net.Prefix, p *route.Path) bool {
-	err := withDrawPrefixes(u.fsm.con, pfx)
+	err := withDrawPrefixes(u.fsm.con, u.fsm.options, pfx)
 	return err == nil
 }
 
diff --git a/protocols/bgp/server/update_sender_add_path.go b/protocols/bgp/server/update_sender_add_path.go
index 7abef161e4f5accd6b49b423849fbbd3d4a56742..afdb71f31ba31618bed84f175478cc95f18f850f 100644
--- a/protocols/bgp/server/update_sender_add_path.go
+++ b/protocols/bgp/server/update_sender_add_path.go
@@ -39,12 +39,12 @@ func (u *UpdateSenderAddPath) AddPath(pfx net.Prefix, p *route.Path) error {
 			Pfxlen:         pfx.Pfxlen(),
 		},
 	}
-	return serializeAndSendUpdate(u.fsm.con, update)
+	return serializeAndSendUpdate(u.fsm.con, update, u.fsm.options)
 }
 
 // RemovePath withdraws prefix `pfx` from a peer
 func (u *UpdateSenderAddPath) RemovePath(pfx net.Prefix, p *route.Path) bool {
-	err := withDrawPrefixesAddPath(u.fsm.con, pfx, p)
+	err := withDrawPrefixesAddPath(u.fsm.con, u.fsm.options, pfx, p)
 	return err == nil
 }
 
diff --git a/protocols/bgp/server/withdraw.go b/protocols/bgp/server/withdraw.go
index 42e97a399cdcf8c208fc29063f7213e4d780ad96..089f9f2c0f7a0e25d1c5d1f2e9f292cdeec74a3c 100644
--- a/protocols/bgp/server/withdraw.go
+++ b/protocols/bgp/server/withdraw.go
@@ -11,7 +11,7 @@ import (
 
 // withDrawPrefixes generates a BGPUpdate message and write it to the given
 // io.Writer.
-func withDrawPrefixes(out io.Writer, prefixes ...net.Prefix) error {
+func withDrawPrefixes(out io.Writer, opt *packet.Options, prefixes ...net.Prefix) error {
 	if len(prefixes) < 1 {
 		return nil
 	}
@@ -35,13 +35,13 @@ func withDrawPrefixes(out io.Writer, prefixes ...net.Prefix) error {
 	update := &packet.BGPUpdate{
 		WithdrawnRoutes: rootNLRI,
 	}
-	return serializeAndSendUpdate(out, update)
+	return serializeAndSendUpdate(out, update, opt)
 
 }
 
 // withDrawPrefixesAddPath generates a BGPUpdateAddPath message and write it to the given
 // io.Writer.
-func withDrawPrefixesAddPath(out io.Writer, pfx net.Prefix, p *route.Path) error {
+func withDrawPrefixesAddPath(out io.Writer, opt *packet.Options, pfx net.Prefix, p *route.Path) error {
 	if p.Type != route.BGPPathType {
 		return errors.New("wrong path type, expected BGPPathType")
 	}
@@ -55,5 +55,5 @@ func withDrawPrefixesAddPath(out io.Writer, pfx net.Prefix, p *route.Path) error
 			Pfxlen:         pfx.Pfxlen(),
 		},
 	}
-	return serializeAndSendUpdate(out, update)
+	return serializeAndSendUpdate(out, update, opt)
 }
diff --git a/protocols/bgp/server/withdraw_test.go b/protocols/bgp/server/withdraw_test.go
index 0df94f75259aa446af0d78d1a65aa9ea7a4c67b2..d8831c3eb526d3afdaceb0a3506bf5dca39c2c41 100644
--- a/protocols/bgp/server/withdraw_test.go
+++ b/protocols/bgp/server/withdraw_test.go
@@ -3,6 +3,8 @@ package server
 import (
 	"testing"
 
+	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
+
 	"errors"
 
 	"bytes"
@@ -52,7 +54,8 @@ func TestWithDrawPrefixes(t *testing.T) {
 	}
 	for _, tc := range testcases {
 		buf := bytes.NewBuffer([]byte{})
-		err := withDrawPrefixes(buf, tc.Prefix...)
+		opt := &packet.Options{}
+		err := withDrawPrefixes(buf, opt, tc.Prefix...)
 		assert.Equal(t, tc.ExpectedError, err, "error mismatch in testcase %v", tc.Name)
 		assert.Equal(t, tc.Expected, buf.Bytes(), "expected different bytes in testcase %v", tc.Name)
 	}
@@ -108,7 +111,8 @@ func TestWithDrawPrefixesAddPath(t *testing.T) {
 	}
 	for _, tc := range testcases {
 		buf := bytes.NewBuffer([]byte{})
-		err := withDrawPrefixesAddPath(buf, tc.Prefix, tc.Path)
+		opt := &packet.Options{}
+		err := withDrawPrefixesAddPath(buf, opt, tc.Prefix, tc.Path)
 		assert.Equal(t, tc.ExpectedError, err, "error mismatch in testcase %v", tc.Name)
 		assert.Equal(t, tc.Expected, buf.Bytes(), "expected different bytes in testcase %v", tc.Name)
 	}