diff --git a/config/peer.go b/config/peer.go
index 8f7692b085e39fae5b1ec998233bf2d174a84581..355e058379721a041d029ea403216941529342fd 100644
--- a/config/peer.go
+++ b/config/peer.go
@@ -2,6 +2,8 @@ package config
 
 import (
 	"net"
+
+	"github.com/bio-routing/bio-rd/routingtable"
 )
 
 type Peer struct {
@@ -14,4 +16,6 @@ type Peer struct {
 	PeerAS       uint32
 	Passive      bool
 	RouterID     uint32
+	AddPathSend  routingtable.ClientOptions
+	AddPathRecv  uint
 }
diff --git a/main.go b/main.go
index 78171d7c20df8a77c4cdb95553591b4b19381c92..ac5805fc38a21f4b4acae1a51b838f6666a71996 100644
--- a/main.go
+++ b/main.go
@@ -10,6 +10,7 @@ import (
 
 	"github.com/bio-routing/bio-rd/config"
 	"github.com/bio-routing/bio-rd/protocols/bgp/server"
+	"github.com/bio-routing/bio-rd/routingtable"
 	"github.com/bio-routing/bio-rd/routingtable/locRIB"
 )
 
@@ -50,6 +51,10 @@ func main() {
 		KeepAlive:    30,
 		Passive:      true,
 		RouterID:     b.RouterID(),
+		AddPathSend: routingtable.ClientOptions{
+			MaxPaths: 10,
+		},
+		AddPathRecv: 1,
 	}, rib)
 
 	go func() {
diff --git a/protocols/bgp/packet/bgp.go b/protocols/bgp/packet/bgp.go
index ba1d3d32206fe90680798ec1bf7338a9ee6fee22..e6ac0e6b3f030ef905a6325fb7550237459d02be 100644
--- a/protocols/bgp/packet/bgp.go
+++ b/protocols/bgp/packet/bgp.go
@@ -76,6 +76,14 @@ const (
 	OtherConfigChange             = 8
 	ConnectionCollisionResolution = 7
 	OutOfResoutces                = 8
+
+	IPv4AFI               = 1
+	UnicastSAFI           = 1
+	CapabilitiesParamType = 2
+	AddPathCapabilityCode = 69
+	AddPathReceive        = 1
+	AddPathSend           = 2
+	AddPathSendReceive    = 3
 )
 
 type BGPError struct {
@@ -104,6 +112,7 @@ type BGPOpen struct {
 	HoldTime      uint16
 	BGPIdentifier uint32
 	OptParmLen    uint8
+	OptParams     []OptParam
 }
 
 type BGPNotification struct {
@@ -144,6 +153,6 @@ type ASPathSegment struct {
 }
 
 type Aggretator struct {
-	Addr [4]byte
+	Addr uint32
 	ASN  uint16
 }
diff --git a/protocols/bgp/packet/decoder.go b/protocols/bgp/packet/decoder.go
index 8ba824ec9fd0620a32416bc0c66c8fd3b8d4c0ef..c5274122cef840355231b3521ced3579ff9be031 100644
--- a/protocols/bgp/packet/decoder.go
+++ b/protocols/bgp/packet/decoder.go
@@ -154,9 +154,92 @@ func _decodeOpenMsg(buf *bytes.Buffer) (interface{}, error) {
 		return nil, err
 	}
 
+	msg.OptParams, err = decodeOptParams(buf, msg.OptParmLen)
+	if err != nil {
+		return nil, fmt.Errorf("Unable to decode optional parameters: %v", err)
+	}
+
 	return msg, nil
 }
 
+func decodeOptParams(buf *bytes.Buffer, optParmLen uint8) ([]OptParam, error) {
+	optParams := make([]OptParam, 0)
+	read := uint8(0)
+	for read < optParmLen {
+		o := OptParam{}
+		fields := []interface{}{
+			&o.Type,
+			&o.Length,
+		}
+
+		err := decode(buf, fields)
+		if err != nil {
+			return nil, err
+		}
+
+		read += 2
+
+		fmt.Printf("Type: %d\n", o.Type)
+		switch o.Type {
+		case CapabilitiesParamType:
+			cap, err := decodeCapability(buf)
+			if err != nil {
+				return nil, fmt.Errorf("Unable to decode capability: %v", err)
+			}
+			o.Value = cap
+			optParams = append(optParams, o)
+			read += cap.Length + 2
+		default:
+			return nil, fmt.Errorf("Unrecognized option")
+		}
+
+	}
+
+	return optParams, nil
+}
+
+func decodeCapability(buf *bytes.Buffer) (Capability, error) {
+	cap := Capability{}
+	fields := []interface{}{
+		&cap.Code,
+		&cap.Length,
+	}
+
+	err := decode(buf, fields)
+	if err != nil {
+		return cap, err
+	}
+
+	switch cap.Code {
+	case AddPathCapabilityCode:
+		addPathCap, err := decodeAddPathCapability(buf)
+		if err != nil {
+			return cap, fmt.Errorf("Unable to decode add path capability")
+		}
+		cap.Value = addPathCap
+	default:
+		return cap, fmt.Errorf("Unknown capability: %d", cap.Code)
+	}
+
+	return cap, nil
+}
+
+func decodeAddPathCapability(buf *bytes.Buffer) (AddPathCapability, error) {
+	addPathCap := AddPathCapability{}
+	fields := []interface{}{
+		&addPathCap.AFI,
+		&addPathCap.SAFI,
+		&addPathCap.SendReceive,
+	}
+
+	err := decode(buf, fields)
+	if err != nil {
+		return addPathCap, err
+	}
+
+	return addPathCap, 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 63b5631d7c0a4e165a2fea093edc9083a2ffdc06..53681371a5d7ca2bdb2a703efc25bf85ea8b0d61 100644
--- a/protocols/bgp/packet/decoder_test.go
+++ b/protocols/bgp/packet/decoder_test.go
@@ -160,6 +160,7 @@ func TestDecode(t *testing.T) {
 					HoldTime:      15,
 					BGPIdentifier: uint32(169090600),
 					OptParmLen:    0,
+					OptParams:     []OptParam{},
 				},
 			},
 		},
@@ -706,7 +707,7 @@ func TestDecodeUpdateMsg(t *testing.T) {
 							ExtendedLength: false,
 							Length:         4,
 							TypeCode:       3,
-							Value:          [4]byte{10, 11, 12, 13},
+							Value:          strAddr("10.11.12.13"),
 						},
 					},
 				},
@@ -799,7 +800,7 @@ func TestDecodeUpdateMsg(t *testing.T) {
 							ExtendedLength: false,
 							Length:         4,
 							TypeCode:       3,
-							Value:          [4]byte{10, 11, 12, 13},
+							Value:          strAddr("10.11.12.13"),
 							Next: &PathAttribute{
 								Optional:       false,
 								Transitive:     false,
@@ -905,7 +906,7 @@ func TestDecodeUpdateMsg(t *testing.T) {
 							ExtendedLength: false,
 							Length:         4,
 							TypeCode:       3,
-							Value:          [4]byte{10, 11, 12, 13},
+							Value:          strAddr("10.11.12.13"),
 							Next: &PathAttribute{
 								Optional:       false,
 								Transitive:     false,
@@ -1023,7 +1024,7 @@ func TestDecodeUpdateMsg(t *testing.T) {
 							ExtendedLength: false,
 							Length:         4,
 							TypeCode:       3,
-							Value:          [4]byte{10, 11, 12, 13},
+							Value:          strAddr("10.11.12.13"),
 							Next: &PathAttribute{
 								Optional:       false,
 								Transitive:     false,
@@ -1157,7 +1158,7 @@ func TestDecodeUpdateMsg(t *testing.T) {
 							ExtendedLength: false,
 							Length:         4,
 							TypeCode:       3,
-							Value:          [4]byte{10, 11, 12, 13},
+							Value:          strAddr("10.11.12.13"),
 							Next: &PathAttribute{
 								Optional:       false,
 								Transitive:     false,
@@ -1190,7 +1191,7 @@ func TestDecodeUpdateMsg(t *testing.T) {
 											TypeCode:       7,
 											Value: Aggretator{
 												ASN:  uint16(258),
-												Addr: [4]byte{10, 11, 12, 13},
+												Addr: strAddr("10.11.12.13"),
 											},
 										},
 									},
@@ -1201,7 +1202,7 @@ func TestDecodeUpdateMsg(t *testing.T) {
 				},
 				NLRI: &NLRI{
 					Pfxlen: 8,
-					IP:     strAddr("1.0.0.0"),
+					IP:     strAddr("11.0.0.0"),
 				},
 			},
 		},
@@ -1266,7 +1267,7 @@ func TestDecodeUpdateMsg(t *testing.T) {
 			continue
 		}
 
-		assert.Equal(t, test.expected, msg)
+		assert.Equalf(t, test.expected, msg, "%d", test.testNum)
 	}
 }
 
@@ -1313,6 +1314,7 @@ func TestDecodeOpenMsg(t *testing.T) {
 				HoldTime:      15,
 				BGPIdentifier: 169090600,
 				OptParmLen:    0,
+				OptParams:     make([]OptParam, 0),
 			},
 		},
 		{
@@ -1452,7 +1454,7 @@ func genericTest(f decodeFunc, tests []test, t *testing.T) {
 			continue
 		}
 
-		assert.Equal(t, test.expected, msg)
+		assert.Equalf(t, test.expected, msg, "%d", test.testNum)
 	}
 }
 
@@ -1536,6 +1538,157 @@ func TestValidateOpenMessage(t *testing.T) {
 	}
 }
 
+func TestDecodeOptParams(t *testing.T) {
+	tests := []struct {
+		name     string
+		input    []byte
+		wantFail bool
+		expected []OptParam
+	}{
+		{
+			name: "Add path capability",
+			input: []byte{
+				2,    // Type
+				6,    // Length
+				69,   // Code
+				4,    // Length
+				0, 1, // AFI
+				1, // SAFI
+				3, // Send/Receive
+			},
+			wantFail: false,
+			expected: []OptParam{
+				{
+					Type:   2,
+					Length: 6,
+					Value: Capability{
+						Code:   69,
+						Length: 4,
+						Value: AddPathCapability{
+							AFI:         1,
+							SAFI:        1,
+							SendReceive: 3,
+						},
+					},
+				},
+			},
+		},
+	}
+
+	for _, test := range tests {
+		buf := bytes.NewBuffer(test.input)
+		res, err := decodeOptParams(buf, uint8(len(test.input)))
+		if err != nil {
+			if test.wantFail {
+				continue
+			}
+
+			t.Errorf("Unexpected failure for test %q: %v", test.name, err)
+			continue
+		}
+
+		if test.wantFail {
+			t.Errorf("Unexpected success for test %q", test.name)
+			continue
+		}
+
+		assert.Equal(t, test.expected, res)
+	}
+}
+
+func TestDecodeCapability(t *testing.T) {
+	tests := []struct {
+		name     string
+		input    []byte
+		expected Capability
+		wantFail bool
+	}{
+		{
+			name:  "Add Path",
+			input: []byte{69, 4, 0, 1, 1, 3},
+			expected: Capability{
+				Code:   69,
+				Length: 4,
+				Value: AddPathCapability{
+					AFI:         1,
+					SAFI:        1,
+					SendReceive: 3,
+				},
+			},
+			wantFail: false,
+		},
+		{
+			name:     "Fail",
+			input:    []byte{69, 4, 0, 1},
+			wantFail: true,
+		},
+	}
+
+	for _, test := range tests {
+		cap, err := decodeCapability(bytes.NewBuffer(test.input))
+		if err != nil {
+			if test.wantFail {
+				continue
+			}
+
+			t.Errorf("Unexpected failure for test %q: %v", test.name, err)
+			continue
+		}
+
+		if test.wantFail {
+			t.Errorf("Unexpected success for test %q", err)
+			continue
+		}
+
+		assert.Equal(t, test.expected, cap)
+	}
+}
+
+func TestDecodeAddPathCapability(t *testing.T) {
+	tests := []struct {
+		name     string
+		input    []byte
+		expected AddPathCapability
+		wantFail bool
+	}{
+		{
+			name:     "ok",
+			input:    []byte{0, 1, 1, 3},
+			wantFail: false,
+			expected: AddPathCapability{
+				AFI:         1,
+				SAFI:        1,
+				SendReceive: 3,
+			},
+		},
+		{
+			name:     "Incomplete",
+			input:    []byte{0, 1, 1},
+			wantFail: true,
+		},
+	}
+
+	for _, test := range tests {
+		buf := bytes.NewBuffer(test.input)
+		cap, err := decodeAddPathCapability(buf)
+		if err != nil {
+			if test.wantFail {
+				continue
+			}
+
+			t.Errorf("Unexpected failure for test %q: %v", test.name, err)
+			continue
+		}
+
+		if test.wantFail {
+			t.Errorf("Unexpected success for test %q", test.name)
+			continue
+		}
+
+		assert.Equal(t, test.expected, cap)
+	}
+}
+
 func strAddr(s string) uint32 {
 	ret, _ := net.StrToAddr(s)
 	return ret
diff --git a/protocols/bgp/packet/encoder.go b/protocols/bgp/packet/encoder.go
index 3cfe702d14ffb66605919fe60839d98a8308b761..3f44047a0a9e86c5aeaf6271bacebf56f5fe32d1 100644
--- a/protocols/bgp/packet/encoder.go
+++ b/protocols/bgp/packet/encoder.go
@@ -34,11 +34,28 @@ func SerializeOpenMsg(msg *BGPOpen) []byte {
 	buf.Write(convert.Uint16Byte(msg.AS))
 	buf.Write(convert.Uint16Byte(msg.HoldTime))
 	buf.Write(convert.Uint32Byte(msg.BGPIdentifier))
-	buf.WriteByte(uint8(0))
+
+	optParmsBuf := bytes.NewBuffer(make([]byte, 0))
+	serializeOptParams(optParmsBuf, msg.OptParams)
+	optParms := optParmsBuf.Bytes()
+	buf.WriteByte(uint8(len(optParms)))
+	buf.Write(optParms)
 
 	return buf.Bytes()
 }
 
+func serializeOptParams(buf *bytes.Buffer, params []OptParam) {
+	for _, param := range params {
+		tmpBuf := bytes.NewBuffer(make([]byte, 0))
+		param.Value.serialize(tmpBuf)
+		payload := tmpBuf.Bytes()
+
+		buf.WriteByte(param.Type)
+		buf.WriteByte(uint8(len(payload)))
+		buf.Write(payload)
+	}
+}
+
 func serializeHeader(buf *bytes.Buffer, length uint16, typ uint8) {
 	buf.Write([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff})
 	buf.Write(convert.Uint16Byte(length))
diff --git a/protocols/bgp/packet/encoder_test.go b/protocols/bgp/packet/encoder_test.go
index eccfdfdcace6be4eeac998bdbcaa29749d0a2581..cc6968d92f353e4130abacf3298b3d80872fd25c 100644
--- a/protocols/bgp/packet/encoder_test.go
+++ b/protocols/bgp/packet/encoder_test.go
@@ -94,6 +94,53 @@ func TestSerializeOpenMsg(t *testing.T) {
 	}
 }
 
+/*func TestSerializeOptParams(t *testing.T) {
+	tests := []struct {
+		name      string
+		optParams []OptParam
+		expected  []byte
+	}{
+		{
+			name:      "empty",
+			optParams: []OptParam{},
+			expected:  []byte{},
+		},
+		{
+			name: "1 Option",
+			optParams: []OptParam{
+				{
+					Type:   100,
+					Length: 2,
+					Value:  []byte{1, 2},
+				},
+			},
+			expected: []byte{100, 2, 1, 2},
+		},
+		{
+			name: "2 Options",
+			optParams: []OptParam{
+				{
+					Type:   100,
+					Length: 2,
+					Value:  []byte{1, 2},
+				},
+				{
+					Type:   200,
+					Length: 2,
+					Value:  []byte{3, 4},
+				},
+			},
+			expected: []byte{100, 2, 1, 2, 200, 2, 3, 4},
+		},
+	}
+
+	for _, test := range tests {
+		buf := bytes.NewBuffer(make([]byte, 0))
+		serializeOptParams(buf, test.optParams)
+		assert.Equal(t, test.expected, buf.Bytes())
+	}
+}*/
+
 func TestSerializeHeader(t *testing.T) {
 	tests := []struct {
 		name     string
diff --git a/protocols/bgp/packet/parameters.go b/protocols/bgp/packet/parameters.go
new file mode 100644
index 0000000000000000000000000000000000000000..543bc4470275b3db7d3384347c51e6845ed303a2
--- /dev/null
+++ b/protocols/bgp/packet/parameters.go
@@ -0,0 +1,45 @@
+package packet
+
+import (
+	"bytes"
+
+	"github.com/taktv6/tflow2/convert"
+)
+
+type Serializable interface {
+	serialize(*bytes.Buffer)
+}
+
+type OptParam struct {
+	Type   uint8
+	Length uint8
+	Value  Serializable
+}
+
+type Capability struct {
+	Code   uint8
+	Length uint8
+	Value  Serializable
+}
+
+func (c Capability) serialize(buf *bytes.Buffer) {
+	tmpBuf := bytes.NewBuffer(make([]byte, 0))
+	c.Value.serialize(tmpBuf)
+	payload := tmpBuf.Bytes()
+
+	buf.WriteByte(c.Code)
+	buf.WriteByte(uint8(len(payload)))
+	buf.Write(payload)
+}
+
+type AddPathCapability struct {
+	AFI         uint16
+	SAFI        uint8
+	SendReceive uint8
+}
+
+func (a AddPathCapability) serialize(buf *bytes.Buffer) {
+	buf.Write(convert.Uint16Byte(a.AFI))
+	buf.WriteByte(a.SAFI)
+	buf.WriteByte(a.SendReceive)
+}
diff --git a/protocols/bgp/packet/path_attributes.go b/protocols/bgp/packet/path_attributes.go
index c305ec27a45b899cad0b9aeeba44a23d690d412f..0390b6617944b5ea1933b542b97c29ac069c52c6 100644
--- a/protocols/bgp/packet/path_attributes.go
+++ b/protocols/bgp/packet/path_attributes.go
@@ -186,24 +186,27 @@ func (pa *PathAttribute) decodeLocalPref(buf *bytes.Buffer) error {
 
 func (pa *PathAttribute) decodeAggregator(buf *bytes.Buffer) error {
 	aggr := Aggretator{}
-
 	p := uint16(0)
+
 	err := decode(buf, []interface{}{&aggr.ASN})
 	if err != nil {
 		return err
 	}
 	p += 2
 
-	n, err := buf.Read(aggr.Addr[:])
+	addr := [4]byte{}
+	n, err := buf.Read(addr[:])
 	if err != nil {
 		return err
 	}
 	if n != 4 {
-		return fmt.Errorf("Unable to read aggregator IP: buf.Read read %d bytes", n)
+		return fmt.Errorf("Unable to read next hop: buf.Read read %d bytes", n)
 	}
-	p += 4
+	aggr.Addr = fourBytesToUint32(addr)
 
 	pa.Value = aggr
+	p += 4
+
 	return dumpNBytes(buf, pa.Length-p)
 }
 
diff --git a/protocols/bgp/packet/path_attributes_test.go b/protocols/bgp/packet/path_attributes_test.go
index e413d4f88f93a66dccca5b1d1444dbf3f64dff7d..5145fddbbd25a27ff8e403ecb4f66a4cfbd60163 100644
--- a/protocols/bgp/packet/path_attributes_test.go
+++ b/protocols/bgp/packet/path_attributes_test.go
@@ -34,7 +34,7 @@ func TestDecodePathAttrs(t *testing.T) {
 				Next: &PathAttribute{
 					TypeCode: 3,
 					Length:   4,
-					Value:    [4]byte{10, 20, 30, 40},
+					Value:    strAddr("10.20.30.40"),
 				},
 			},
 		},
@@ -62,7 +62,7 @@ func TestDecodePathAttrs(t *testing.T) {
 			continue
 		}
 
-		assert.Equal(t, test.expected, res)
+		assert.Equal(t, test.expected, res, "%s", test.name)
 	}
 }
 
@@ -367,9 +367,7 @@ func TestDecodeNextHop(t *testing.T) {
 			wantFail: false,
 			expected: &PathAttribute{
 				Length: 4,
-				Value: [4]byte{
-					10, 20, 30, 40,
-				},
+				Value:  strAddr("10.20.30.40"),
 			},
 		},
 		{
@@ -538,7 +536,7 @@ func TestDecodeAggregator(t *testing.T) {
 				Length: 6,
 				Value: Aggretator{
 					ASN:  222,
-					Addr: [4]byte{10, 20, 30, 40},
+					Addr: strAddr("10.20.30.40"),
 				},
 			},
 		},
@@ -892,9 +890,9 @@ func TestSerializeNextHop(t *testing.T) {
 			name: "Test #1",
 			input: &PathAttribute{
 				TypeCode: NextHopAttr,
-				Value:    [4]byte{100, 110, 120, 130},
+				Value:    strAddr("100.110.120.130"),
 			},
-			expected:    []byte{0, 3, 4, 100, 110, 120, 130},
+			expected:    []byte{64, 3, 4, 100, 110, 120, 130},
 			expectedLen: 7,
 		},
 	}
@@ -1186,7 +1184,7 @@ func TestSerialize(t *testing.T) {
 						},
 						Next: &PathAttribute{
 							TypeCode: NextHopAttr,
-							Value:    [4]byte{10, 20, 30, 40},
+							Value:    strAddr("10.20.30.40"),
 							Next: &PathAttribute{
 								TypeCode: MEDAttr,
 								Value:    uint32(100),
@@ -1216,7 +1214,7 @@ func TestSerialize(t *testing.T) {
 			},
 			expected: []byte{
 				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-				0, 85, // Length
+				0, 86, // Length
 				2, // Msg Type
 
 				// Withdraws
@@ -1224,7 +1222,7 @@ func TestSerialize(t *testing.T) {
 				8, 10, // Withdraw 10/8
 				16, 192, 168, // Withdraw 192.168/16
 
-				0, 49, // Total Path Attribute Length
+				0, 50, // Total Path Attribute Length
 
 				// ORIGIN
 				64, // Attr. Flags
@@ -1234,6 +1232,7 @@ func TestSerialize(t *testing.T) {
 				// ASPath
 				64,                     // Attr. Flags
 				2,                      // Attr. Type Code
+				14,                     // Attr. Length
 				2,                      // Path Segment Type = AS_SEQUENCE
 				3,                      // Path Segment Length
 				0, 100, 0, 155, 0, 200, // ASNs
@@ -1288,7 +1287,7 @@ func TestSerialize(t *testing.T) {
 			continue
 		}
 
-		assert.Equal(t, test.expected, res)
+		assert.Equalf(t, test.expected, res, "%s", test.name)
 	}
 }
 
diff --git a/protocols/bgp/server/fsm.go b/protocols/bgp/server/fsm.go
index 051eaf03cd24f5d6c176935c7c288a1fe1e7c0f0..c41e03b19f90eeab6e732f14a00e5019b6ce1fd5 100644
--- a/protocols/bgp/server/fsm.go
+++ b/protocols/bgp/server/fsm.go
@@ -46,6 +46,8 @@ const (
 )
 
 type FSM struct {
+	peer *Peer
+
 	t           tomb.Tomb
 	stateReason string
 	state       int
@@ -103,8 +105,9 @@ type msgRecvErr struct {
 	con *net.TCPConn
 }
 
-func NewFSM(c config.Peer, rib *locRIB.LocRIB) *FSM {
+func NewFSM(peer *Peer, c config.Peer, rib *locRIB.LocRIB) *FSM {
 	fsm := &FSM{
+		peer:              peer,
 		state:             Idle,
 		passive:           true,
 		connectRetryTime:  5,
@@ -300,6 +303,8 @@ func (fsm *FSM) connect() int {
 }
 
 func (fsm *FSM) connectSendOpen() int {
+	optOpenParams := make([]packet.OptParam, 0)
+
 	err := fsm.sendOpen(fsm.con)
 	if err != nil {
 		stopTimer(fsm.connectRetryTimer)
@@ -860,7 +865,7 @@ func (fsm *FSM) sendOpen(c *net.TCPConn) error {
 		AS:            fsm.localASN,
 		HoldTime:      uint16(fsm.holdTimeConfigured),
 		BGPIdentifier: fsm.routerID,
-		OptParmLen:    0,
+		OptParams:     fsm.peer.optOpenParams,
 	})
 
 	_, err := c.Write(msg)
diff --git a/protocols/bgp/server/peer.go b/protocols/bgp/server/peer.go
index 5c65732b6a3247ecf88b833c1626a2cba96b2f43..e30912906d53f150e26873ebbb8868f0041c3700 100644
--- a/protocols/bgp/server/peer.go
+++ b/protocols/bgp/server/peer.go
@@ -3,26 +3,63 @@ package server
 import (
 	"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"
 
 	"github.com/bio-routing/bio-rd/config"
 )
 
 type Peer struct {
-	addr     net.IP
-	asn      uint32
-	fsm      *FSM
-	rib      *locRIB.LocRIB
-	routerID uint32
+	addr          net.IP
+	asn           uint32
+	fsm           *FSM
+	rib           *locRIB.LocRIB
+	routerID      uint32
+	addPathSend   routingtable.ClientOptions
+	addPathRecv   uint
+	optOpenParams []packet.OptParam
 }
 
 func NewPeer(c config.Peer, rib *locRIB.LocRIB) (*Peer, error) {
 	p := &Peer{
-		addr: c.PeerAddress,
-		asn:  c.PeerAS,
-		fsm:  NewFSM(c, rib),
-		rib:  rib,
+		addr:          c.PeerAddress,
+		asn:           c.PeerAS,
+		rib:           rib,
+		addPathSend:   c.AddPathSend,
+		addPathRecv:   c.AddPathRecv,
+		optOpenParams: make([]packet.OptParam, 0),
 	}
+	p.fsm = NewFSM(p, c, rib)
+
+	caps := make([]packet.Capability, 0)
+
+	addPath := uint8(0)
+	if c.AddPathRecv > 1 {
+		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,
+		})
+	}
+
 	return p, nil
 }
 
diff --git a/routingtable/adjRIBOutAddPath/adj_rib_out_add_path.go b/routingtable/adjRIBOutAddPath/adj_rib_out_add_path.go
new file mode 100644
index 0000000000000000000000000000000000000000..b3e440a8aaa676b836276cceeac6a8e9391a82b5
--- /dev/null
+++ b/routingtable/adjRIBOutAddPath/adj_rib_out_add_path.go
@@ -0,0 +1,100 @@
+package adjRIBOutAddPath
+
+import (
+	"fmt"
+	"sync"
+
+	"github.com/bio-routing/bio-rd/net"
+	"github.com/bio-routing/bio-rd/route"
+	"github.com/bio-routing/bio-rd/routingtable"
+)
+
+// AdjRIBOutAddPath represents an Adjacency RIB Out with BGP add path
+type AdjRIBOutAddPath struct {
+	routingtable.ClientManager
+	rt       *routingtable.RoutingTable
+	neighbor *routingtable.Neighbor
+	mu       sync.RWMutex
+}
+
+// New creates a new Adjacency RIB Out with BGP add path
+func New(neighbor *routingtable.Neighbor) *AdjRIBOutAddPath {
+	a := &AdjRIBOutAddPath{
+		rt:       routingtable.NewRoutingTable(),
+		neighbor: neighbor,
+	}
+	a.ClientManager = routingtable.NewClientManager(a)
+	return a
+}
+
+// UpdateNewClient sends current state to a new client
+func (a *AdjRIBOutAddPath) UpdateNewClient(client routingtable.RouteTableClient) error {
+	return fmt.Errorf("Not supported")
+}
+
+// AddPath adds path p to prefix `pfx`
+func (a *AdjRIBOutAddPath) AddPath(pfx net.Prefix, p *route.Path) error {
+	if a.isOwnPath(p) {
+		return nil
+	}
+
+	a.mu.Lock()
+	defer a.mu.Unlock()
+
+	for _, client := range a.ClientManager.Clients() {
+		client.AddPath(pfx, p)
+	}
+	return nil
+}
+
+// RemovePath removes the path for prefix `pfx`
+func (a *AdjRIBOutAddPath) RemovePath(pfx net.Prefix, p *route.Path) bool {
+	if a.isOwnPath(p) {
+		return false
+	}
+
+	a.mu.Lock()
+	defer a.mu.Unlock()
+
+	r := a.rt.Get(pfx)
+	if r == nil {
+		return false
+	}
+
+	a.rt.RemovePath(pfx, p)
+	a.removePathFromClients(pfx, p)
+	return true
+}
+
+func (a *AdjRIBOutAddPath) isOwnPath(p *route.Path) bool {
+	if p.Type != a.neighbor.Type {
+		return false
+	}
+
+	switch p.Type {
+	case route.BGPPathType:
+		return p.BGPPath.Source == a.neighbor.Address
+	}
+
+	return false
+}
+
+func (a *AdjRIBOutAddPath) removePathFromClients(pfx net.Prefix, path *route.Path) {
+	for _, client := range a.ClientManager.Clients() {
+		client.RemovePath(pfx, path)
+	}
+}
+
+// Print dumps all prefixes in the Adj-RIB
+func (a *AdjRIBOutAddPath) Print() string {
+	a.mu.RLock()
+	defer a.mu.RUnlock()
+
+	ret := fmt.Sprintf("DUMPING ADJ-RIB-OUT:\n")
+	routes := a.rt.Dump()
+	for _, r := range routes {
+		ret += fmt.Sprintf("%s\n", r.Prefix().String())
+	}
+
+	return ret
+}