diff --git a/.travis.yml b/.travis.yml
index 8b3da873949238d178b63a41de0c020068d6618e..ebeb4b25556a1350a221f804040b1d63c3125b82 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,10 @@
 language: go
 go:
-  - "1.10"
+- "1.9.2"
+- master
+before_install:
+- mkdir -p $GOPATH/src/github.com/bio-routing
+- ln -s $TRAVIS_BUILD_DIR $HOME/gopath/src/github.com/bio-routing/ || true
+- go get github.com/mattn/goveralls
+script:
+- goveralls -v
diff --git a/README.md b/README.md
index dda57a6bb1510dc391b35056865daa93632d5886..8d1dc734f69d0e083e2147bb37d790a81fd21435 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
 # bio-rd
 
 [![Build Status](https://travis-ci.org/bio-routing/bio-rd.svg?branch=master)](https://travis-ci.org/bio-routing/bio-rd)
-[![Go ReportCard](http://goreportcard.com/badge/bio-routing/bio-rd)](http://goreportcard.com/report/bio-routing/bio-rd)
\ No newline at end of file
+[![Coverage Status](https://coveralls.io/repos/bio-routing/bio-rd/badge.svg?branch=master&service=github)](https://coveralls.io/github/bio-routing/bio-rd?branch=master)
+[![Go ReportCard](http://goreportcard.com/badge/bio-routing/bio-rd)](http://goreportcard.com/report/bio-routing/bio-rd)
diff --git a/config/peer.go b/config/peer.go
index 8f7692b085e39fae5b1ec998233bf2d174a84581..9e057b9da60f6a33632a55bf7a3181c4a850ba70 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  bool
 }
diff --git a/main.go b/main.go
index 78171d7c20df8a77c4cdb95553591b4b19381c92..7e19a5aa8d1e0d982435fe12dd8229eecfbb1a35 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"
 )
 
@@ -36,9 +37,12 @@ func main() {
 		KeepAlive:    30,
 		Passive:      true,
 		RouterID:     b.RouterID(),
+		AddPathSend: routingtable.ClientOptions{
+			MaxPaths: 10,
+		},
 	}, rib)
 
-	time.Sleep(time.Second * 30)
+	time.Sleep(time.Second * 15)
 
 	b.AddPeer(config.Peer{
 		AdminEnabled: true,
@@ -50,6 +54,10 @@ func main() {
 		KeepAlive:    30,
 		Passive:      true,
 		RouterID:     b.RouterID(),
+		AddPathSend: routingtable.ClientOptions{
+			MaxPaths: 10,
+		},
+		AddPathRecv: true,
 	}, rib)
 
 	go func() {
diff --git a/net/helper.go b/net/helper.go
index efb6759637fab4d13a08b43908057226e723d511..4f7319cddfd92ef975819b143e4c03488ec22fb8 100644
--- a/net/helper.go
+++ b/net/helper.go
@@ -4,5 +4,5 @@ import "net"
 
 // IPv4ToUint32 converts an `net.IP` to an uint32 interpretation
 func IPv4ToUint32(ip net.IP) uint32 {
-	return uint32(ip[0]) + uint32(ip[1])<<8 + uint32(ip[2])<<16 + uint32(ip[3])<<24
+	return uint32(ip[3]) + uint32(ip[2])<<8 + uint32(ip[1])<<16 + uint32(ip[0])<<24
 }
diff --git a/net/helper_test.go b/net/helper_test.go
index 7503a6854d951e6a97bb0674945416b5bc52bc94..7a267c3c9e26715bd9b14e3579265e2057aac8db 100644
--- a/net/helper_test.go
+++ b/net/helper_test.go
@@ -6,7 +6,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func IPv4ToUint32Test(t *testing.T) {
+func TestIPv4ToUint32(t *testing.T) {
 	tests := []struct {
 		input    []byte
 		expected uint32
diff --git a/protocols/bgp/packet/bgp.go b/protocols/bgp/packet/bgp.go
index ba1d3d32206fe90680798ec1bf7338a9ee6fee22..41a2113f8e6cb85cb0250d0333908071dc03fd79 100644
--- a/protocols/bgp/packet/bgp.go
+++ b/protocols/bgp/packet/bgp.go
@@ -4,6 +4,7 @@ const (
 	OctetLen       = 8
 	MaxASNsSegment = 255
 	BGP4Version    = 4
+	MinOpenLen     = 29
 
 	MarkerLen  = 16
 	HeaderLen  = 19
@@ -76,6 +77,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 +113,7 @@ type BGPOpen struct {
 	HoldTime      uint16
 	BGPIdentifier uint32
 	OptParmLen    uint8
+	OptParams     []OptParam
 }
 
 type BGPNotification struct {
@@ -119,6 +129,14 @@ type BGPUpdate struct {
 	NLRI               *NLRI
 }
 
+type BGPUpdateAddPath struct {
+	WithdrawnRoutesLen uint16
+	WithdrawnRoutes    *NLRIAddPath
+	TotalPathAttrLen   uint16
+	PathAttributes     *PathAttribute
+	NLRI               *NLRIAddPath
+}
+
 type PathAttribute struct {
 	Length         uint16
 	Optional       bool
@@ -136,6 +154,13 @@ type NLRI struct {
 	Next   *NLRI
 }
 
+type NLRIAddPath struct {
+	PathIdentifier uint32
+	IP             uint32
+	Pfxlen         uint8
+	Next           *NLRIAddPath
+}
+
 type ASPath []ASPathSegment
 type ASPathSegment struct {
 	Type  uint8
@@ -144,6 +169,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..961789b3cfdd43b0aae606e2a693ceef88a315b9 100644
--- a/protocols/bgp/packet/decoder.go
+++ b/protocols/bgp/packet/decoder.go
@@ -130,6 +130,9 @@ func invalidErrCode(n *BGPNotification) (*BGPNotification, error) {
 
 func decodeOpenMsg(buf *bytes.Buffer) (*BGPOpen, error) {
 	msg, err := _decodeOpenMsg(buf)
+	if err != nil {
+		return nil, fmt.Errorf("Unable to decode OPEN message: %v", err)
+	}
 	return msg.(*BGPOpen), err
 }
 
@@ -154,9 +157,115 @@ 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
+
+		switch o.Type {
+		case CapabilitiesParamType:
+			caps, err := decodeCapabilities(buf, o.Length)
+			if err != nil {
+				return nil, fmt.Errorf("Unable to decode capabilites: %v", err)
+			}
+
+			o.Value = caps
+			optParams = append(optParams, o)
+			for _, cap := range caps {
+				read += cap.Length + 2
+			}
+		default:
+			return nil, fmt.Errorf("Unrecognized option: %d", o.Type)
+		}
+
+	}
+
+	return optParams, nil
+}
+
+func decodeCapabilities(buf *bytes.Buffer, length uint8) (Capabilities, error) {
+	ret := make(Capabilities, 0)
+	read := uint8(0)
+	for read < length {
+		cap, err := decodeCapability(buf)
+		if err != nil {
+			return nil, fmt.Errorf("Unable to decode capability: %v", err)
+		}
+
+		ret = append(ret, cap)
+		read += cap.Length + 2
+	}
+
+	return ret, 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:
+		for i := uint8(0); i < cap.Length; i++ {
+			_, err := buf.ReadByte()
+			if err != nil {
+				return cap, fmt.Errorf("Read failed: %v", err)
+			}
+		}
+	}
+
+	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..01d4e01596040cdab68d7cd5abdfb30b846fe3fa 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,159 @@ 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: Capabilities{
+						{
+							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..ea87d1ff64cfc946688e738ae9f7ffa372cf10c7 100644
--- a/protocols/bgp/packet/encoder.go
+++ b/protocols/bgp/packet/encoder.go
@@ -26,7 +26,11 @@ func SerializeNotificationMsg(msg *BGPNotification) []byte {
 }
 
 func SerializeOpenMsg(msg *BGPOpen) []byte {
-	openLen := uint16(29)
+	optParmsBuf := bytes.NewBuffer(make([]byte, 0))
+	serializeOptParams(optParmsBuf, msg.OptParams)
+	optParms := optParmsBuf.Bytes()
+	openLen := uint16(len(optParms) + MinOpenLen)
+
 	buf := bytes.NewBuffer(make([]byte, 0, openLen))
 	serializeHeader(buf, openLen, OpenMsg)
 
@@ -34,17 +38,90 @@ 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))
+
+	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))
 	buf.WriteByte(typ)
 }
 
+func (b *BGPUpdateAddPath) SerializeUpdate() ([]byte, error) {
+	budget := MaxLen - MinLen
+	buf := bytes.NewBuffer(nil)
+
+	withdrawBuf := bytes.NewBuffer(nil)
+	for withdraw := b.WithdrawnRoutes; withdraw != nil; withdraw = withdraw.Next {
+		nlriLen := int(withdraw.serialize(withdrawBuf))
+		budget -= nlriLen
+		if budget < 0 {
+			return nil, fmt.Errorf("update too long")
+		}
+	}
+
+	pathAttributesBuf := bytes.NewBuffer(nil)
+	for pa := b.PathAttributes; pa != nil; pa = pa.Next {
+		paLen := int(pa.serialize(pathAttributesBuf))
+		budget -= paLen
+		if budget < 0 {
+			return nil, fmt.Errorf("update too long")
+		}
+	}
+
+	nlriBuf := bytes.NewBuffer(nil)
+	for nlri := b.NLRI; nlri != nil; nlri = nlri.Next {
+		nlriLen := int(nlri.serialize(nlriBuf))
+		budget -= nlriLen
+		if budget < 0 {
+			return nil, fmt.Errorf("update too long")
+		}
+	}
+
+	withdrawnRoutesLen := withdrawBuf.Len()
+	if withdrawnRoutesLen > 65535 {
+		return nil, fmt.Errorf("Invalid Withdrawn Routes Length: %d", withdrawnRoutesLen)
+	}
+
+	totalPathAttributesLen := pathAttributesBuf.Len()
+	if totalPathAttributesLen > 65535 {
+		return nil, fmt.Errorf("Invalid Total Path Attribute Length: %d", totalPathAttributesLen)
+	}
+
+	totalLength := 2 + withdrawnRoutesLen + totalPathAttributesLen + 2 + nlriBuf.Len() + 19
+	if totalLength > 4096 {
+		return nil, fmt.Errorf("Update too long: %d bytes", totalLength)
+	}
+
+	serializeHeader(buf, uint16(totalLength), UpdateMsg)
+
+	buf.Write(convert.Uint16Byte(uint16(withdrawnRoutesLen)))
+	buf.Write(withdrawBuf.Bytes())
+
+	buf.Write(convert.Uint16Byte(uint16(totalPathAttributesLen)))
+	buf.Write(pathAttributesBuf.Bytes())
+
+	buf.Write(nlriBuf.Bytes())
+
+	return buf.Bytes(), nil
+}
+
 func (b *BGPUpdate) SerializeUpdate() ([]byte, error) {
 	budget := MaxLen - MinLen
 	buf := bytes.NewBuffer(nil)
diff --git a/protocols/bgp/packet/encoder_test.go b/protocols/bgp/packet/encoder_test.go
index eccfdfdcace6be4eeac998bdbcaa29749d0a2581..0d4f70a3483dabd8f7332dd148c72b09df626dee 100644
--- a/protocols/bgp/packet/encoder_test.go
+++ b/protocols/bgp/packet/encoder_test.go
@@ -94,6 +94,45 @@ 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:   2,
+					Length: 6,
+					Value: Capability{
+						Code:   69,
+						Length: 4,
+						Value: AddPathCapability{
+							AFI:         1,
+							SAFI:        1,
+							SendReceive: 3,
+						},
+					},
+				},
+			},
+			expected: []byte{2, 6, 69, 4, 0, 1, 1, 3},
+		},
+	}
+
+	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/nlri.go b/protocols/bgp/packet/nlri.go
index 05fecbff1a4ccf8441306ae340d88ed170cdb409..6de92a6cd59ff167d87efbaf5d197fb46c00aaca 100644
--- a/protocols/bgp/packet/nlri.go
+++ b/protocols/bgp/packet/nlri.go
@@ -73,6 +73,19 @@ func (n *NLRI) serialize(buf *bytes.Buffer) uint8 {
 	return nBytes + 1
 }
 
+func (n *NLRIAddPath) serialize(buf *bytes.Buffer) uint8 {
+	a := convert.Uint32Byte(n.IP)
+
+	addr := [4]byte{a[0], a[1], a[2], a[3]}
+	nBytes := bytesInAddr(n.Pfxlen)
+
+	buf.Write(convert.Uint32Byte(n.PathIdentifier))
+	buf.WriteByte(n.Pfxlen)
+	buf.Write(addr[:nBytes])
+
+	return nBytes + 1
+}
+
 func bytesInAddr(pfxlen uint8) uint8 {
 	return uint8(math.Ceil(float64(pfxlen) / 8))
 }
diff --git a/protocols/bgp/packet/nlri_test.go b/protocols/bgp/packet/nlri_test.go
index b97509b87325ccfe13c04fbb9caacaf76b080491..17a17dd3bf5ae997fa4676de27a5db5a4376907b 100644
--- a/protocols/bgp/packet/nlri_test.go
+++ b/protocols/bgp/packet/nlri_test.go
@@ -208,3 +208,46 @@ func TestNLRISerialize(t *testing.T) {
 		assert.Equal(t, test.expected, res)
 	}
 }
+
+func TestNLRIAddPathSerialize(t *testing.T) {
+	tests := []struct {
+		name     string
+		nlri     *NLRIAddPath
+		expected []byte
+	}{
+		{
+			name: "Test #1",
+			nlri: &NLRIAddPath{
+				PathIdentifier: 100,
+				IP:             strAddr("1.2.3.0"),
+				Pfxlen:         25,
+			},
+			expected: []byte{0, 0, 0, 100, 25, 1, 2, 3, 0},
+		},
+		{
+			name: "Test #2",
+			nlri: &NLRIAddPath{
+				PathIdentifier: 100,
+				IP:             strAddr("1.2.3.0"),
+				Pfxlen:         24,
+			},
+			expected: []byte{0, 0, 0, 100, 24, 1, 2, 3},
+		},
+		{
+			name: "Test #3",
+			nlri: &NLRIAddPath{
+				PathIdentifier: 100,
+				IP:             strAddr("100.200.128.0"),
+				Pfxlen:         17,
+			},
+			expected: []byte{0, 0, 0, 100, 17, 100, 200, 128},
+		},
+	}
+
+	for _, test := range tests {
+		buf := bytes.NewBuffer(nil)
+		test.nlri.serialize(buf)
+		res := buf.Bytes()
+		assert.Equal(t, test.expected, res)
+	}
+}
diff --git a/protocols/bgp/packet/parameters.go b/protocols/bgp/packet/parameters.go
new file mode 100644
index 0000000000000000000000000000000000000000..8edf42fc58e05bb3b73cacd4272012844bedcd45
--- /dev/null
+++ b/protocols/bgp/packet/parameters.go
@@ -0,0 +1,54 @@
+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 Capabilities []Capability
+
+type Capability struct {
+	Code   uint8
+	Length uint8
+	Value  Serializable
+}
+
+func (c Capabilities) serialize(buf *bytes.Buffer) {
+	tmpBuf := bytes.NewBuffer(make([]byte, 0))
+	for _, cap := range c {
+		cap.serialize(tmpBuf)
+	}
+}
+
+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..15f78fe39a763b86eb31281cbee5e30e54a84585 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.Equalf(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..c53696fb5e6895c165e56f75d38a3e441fd9449e 100644
--- a/protocols/bgp/server/fsm.go
+++ b/protocols/bgp/server/fsm.go
@@ -15,6 +15,7 @@ import (
 	"github.com/bio-routing/bio-rd/route"
 	"github.com/bio-routing/bio-rd/routingtable/adjRIBIn"
 	"github.com/bio-routing/bio-rd/routingtable/adjRIBOut"
+	"github.com/bio-routing/bio-rd/routingtable/adjRIBOutAddPath"
 	"github.com/bio-routing/bio-rd/routingtable/locRIB"
 	log "github.com/sirupsen/logrus"
 	tomb "gopkg.in/tomb.v2"
@@ -46,6 +47,8 @@ const (
 )
 
 type FSM struct {
+	peer *Peer
+
 	t           tomb.Tomb
 	stateReason string
 	state       int
@@ -88,9 +91,12 @@ type FSM struct {
 	stopMsgRecvCh chan struct{}
 
 	adjRIBIn     *adjRIBIn.AdjRIBIn
-	adjRIBOut    *adjRIBOut.AdjRIBOut
+	adjRIBOut    routingtable.RouteTableClient
 	rib          *locRIB.LocRIB
-	updateSender *UpdateSender
+	updateSender routingtable.RouteTableClient
+
+	capAddPathSend bool
+	capAddPathRecv bool
 }
 
 type msgRecvMsg struct {
@@ -103,8 +109,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,
@@ -131,7 +138,6 @@ func NewFSM(c config.Peer, rib *locRIB.LocRIB) *FSM {
 		rib: rib,
 	}
 
-	fsm.updateSender = newUpdateSender(fsm)
 	return fsm
 }
 
@@ -454,6 +460,9 @@ func (fsm *FSM) openSent() int {
 					fsm.keepaliveTime = fsm.holdTime / 3
 					fsm.keepaliveTimer.Reset(time.Second * fsm.keepaliveTime)
 				}
+
+				fsm.processOpenOptions(openMsg.OptParams)
+
 				return fsm.changeState(OpenConfirm, "Received OPEN message")
 			default:
 				sendNotification(fsm.con, packet.FiniteStateMachineError, 0)
@@ -480,6 +489,56 @@ func (fsm *FSM) openSent() int {
 	}
 }
 
+func (fsm *FSM) processOpenOptions(optParams []packet.OptParam) {
+	for _, optParam := range optParams {
+		if optParam.Type != packet.CapabilitiesParamType {
+			continue
+		}
+
+		fsm.processCapabilities(optParam.Value.(packet.Capabilities))
+	}
+}
+
+func (fsm *FSM) processCapabilities(caps packet.Capabilities) {
+	for _, cap := range caps {
+		fsm.processCapability(cap)
+	}
+}
+
+func (fsm *FSM) processCapability(cap packet.Capability) {
+	switch cap.Code {
+	case packet.AddPathCapabilityCode:
+		fsm.processAddPathCapability(cap.Value.(packet.AddPathCapability))
+
+	}
+}
+
+func (fsm *FSM) processAddPathCapability(addPathCap packet.AddPathCapability) {
+	if addPathCap.AFI != 1 {
+		return
+	}
+	if addPathCap.SAFI != 1 {
+		return
+	}
+	switch addPathCap.SendReceive {
+	case packet.AddPathReceive:
+		if !fsm.peer.addPathSend.BestOnly {
+			fsm.capAddPathSend = true
+		}
+	case packet.AddPathSend:
+		if fsm.peer.addPathRecv {
+			fsm.capAddPathRecv = true
+		}
+	case packet.AddPathSendReceive:
+		if !fsm.peer.addPathSend.BestOnly {
+			fsm.capAddPathSend = true
+		}
+		if fsm.peer.addPathRecv {
+			fsm.capAddPathRecv = true
+		}
+	}
+}
+
 func (fsm *FSM) openSentTCPFail(err error) int {
 	fsm.con.Close()
 	fsm.resetConnectRetryTimer()
@@ -602,7 +661,7 @@ func (fsm *FSM) openConfirm() int {
 
 			switch msg.Header.Type {
 			case packet.NotificationMsg:
-				nMsg := msg.Body.(packet.BGPNotification)
+				nMsg := msg.Body.(*packet.BGPNotification)
 				if nMsg.ErrorCode == packet.UnsupportedVersionNumber {
 					stopTimer(fsm.connectRetryTimer)
 					fsm.con.Close()
@@ -664,18 +723,30 @@ func (fsm *FSM) established() int {
 		Type:    route.BGPPathType,
 		Address: tnet.IPv4ToUint32(fsm.remote),
 	}
-	fsm.adjRIBOut = adjRIBOut.New(n)
-	fsm.adjRIBOut.Register(fsm.updateSender)
 
-	fsm.rib.RegisterWithOptions(fsm.adjRIBOut, routingtable.ClientOptions{BestOnly: true})
+	clientOptions := routingtable.ClientOptions{}
+	if fsm.capAddPathSend {
+		fsm.updateSender = newUpdateSenderAddPath(fsm)
+		fsm.adjRIBOut = adjRIBOutAddPath.New(n)
+		clientOptions = fsm.peer.addPathSend
+	} else {
+		fsm.updateSender = newUpdateSender(fsm)
+		fsm.adjRIBOut = adjRIBOut.New(n)
+	}
+
+	fsm.adjRIBOut.Register(fsm.updateSender)
+	fsm.rib.RegisterWithOptions(fsm.adjRIBOut, clientOptions)
 
-	go func() {
+	/*go func() {
 		for {
+			if fsm.adjRIBOut == nil {
+				return
+			}
 			fmt.Printf("ADJ-RIB-OUT: %s\n", fsm.remote.String())
 			fmt.Print(fsm.adjRIBOut.Print())
 			time.Sleep(time.Second * 11)
 		}
-	}()
+	}()*/
 
 	for {
 		select {
@@ -751,8 +822,10 @@ func (fsm *FSM) established() int {
 					fmt.Printf("LPM: Adding prefix %s\n", pfx.String())
 
 					path := &route.Path{
-						Type:    route.BGPPathType,
-						BGPPath: &route.BGPPath{},
+						Type: route.BGPPathType,
+						BGPPath: &route.BGPPath{
+							Source: tnet.IPv4ToUint32(fsm.remote),
+						},
 					}
 
 					for pa := u.PathAttributes; pa != nil; pa = pa.Next {
@@ -860,7 +933,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..7bfcbc560181663fec221f76ada98d00ef29e517 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   bool
+	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 {
+		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/protocols/bgp/server/update_sender.go b/protocols/bgp/server/update_sender.go
index 329e97138f449f1859c5b691f9add50392880dc1..95dded6f74ce1c095301026a7b00c2b48f99beb9 100644
--- a/protocols/bgp/server/update_sender.go
+++ b/protocols/bgp/server/update_sender.go
@@ -11,7 +11,9 @@ import (
 	"github.com/bio-routing/bio-rd/routingtable"
 )
 
+// UpdateSender converts table changes into BGP update messages
 type UpdateSender struct {
+	routingtable.ClientManager
 	fsm *FSM
 }
 
@@ -21,8 +23,8 @@ func newUpdateSender(fsm *FSM) *UpdateSender {
 	}
 }
 
+// AddPath serializes a new path and sends out a BGP update message
 func (u *UpdateSender) AddPath(pfx net.Prefix, p *route.Path) error {
-	fmt.Printf("SENDING AN BGP UPDATE\n")
 	asPathPA, err := packet.ParseASPathStr(fmt.Sprintf("%d %s", u.fsm.localASN, p.BGPPath.ASPath))
 	if err != nil {
 		return fmt.Errorf("Unable to parse AS path: %v", err)
@@ -52,7 +54,7 @@ func (u *UpdateSender) AddPath(pfx net.Prefix, p *route.Path) error {
 		log.Errorf("Unable to serialize BGP Update: %v", err)
 		return nil
 	}
-	fmt.Printf("Sending Update: %v\n", updateBytes)
+
 	_, err = u.fsm.con.Write(updateBytes)
 	if err != nil {
 		return fmt.Errorf("Failed sending Update: %v", err)
@@ -60,12 +62,14 @@ func (u *UpdateSender) AddPath(pfx net.Prefix, p *route.Path) error {
 	return nil
 }
 
+// RemovePath withdraws prefix `pfx` from a peer
 func (u *UpdateSender) RemovePath(pfx net.Prefix, p *route.Path) bool {
 	log.Warningf("BGP Update Sender: RemovePath not implemented")
 	return false
 }
 
+// UpdateNewClient does nothing
 func (u *UpdateSender) UpdateNewClient(client routingtable.RouteTableClient) error {
-	log.Warningf("BGP Update Sender: RemovePath not implemented")
+	log.Warningf("BGP Update Sender: UpdateNewClient() not supported")
 	return nil
 }
diff --git a/protocols/bgp/server/update_sender_add_path.go b/protocols/bgp/server/update_sender_add_path.go
new file mode 100644
index 0000000000000000000000000000000000000000..c4fe7de5f145a256eedab2c980e3ee82418b1898
--- /dev/null
+++ b/protocols/bgp/server/update_sender_add_path.go
@@ -0,0 +1,76 @@
+package server
+
+import (
+	"fmt"
+
+	log "github.com/sirupsen/logrus"
+
+	"github.com/bio-routing/bio-rd/net"
+	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
+	"github.com/bio-routing/bio-rd/route"
+	"github.com/bio-routing/bio-rd/routingtable"
+)
+
+// UpdateSenderAddPath converts table changes into BGP update messages with add path
+type UpdateSenderAddPath struct {
+	routingtable.ClientManager
+	fsm *FSM
+}
+
+func newUpdateSenderAddPath(fsm *FSM) *UpdateSenderAddPath {
+	return &UpdateSenderAddPath{
+		fsm: fsm,
+	}
+}
+
+// AddPath serializes a new path and sends out a BGP update message
+func (u *UpdateSenderAddPath) AddPath(pfx net.Prefix, p *route.Path) error {
+	asPathPA, err := packet.ParseASPathStr(fmt.Sprintf("%d %s", u.fsm.localASN, p.BGPPath.ASPath))
+	if err != nil {
+		return fmt.Errorf("Unable to parse AS path: %v", err)
+	}
+
+	update := &packet.BGPUpdateAddPath{
+		PathAttributes: &packet.PathAttribute{
+			TypeCode: packet.OriginAttr,
+			Value:    p.BGPPath.Origin,
+			Next: &packet.PathAttribute{
+				TypeCode: packet.ASPathAttr,
+				Value:    asPathPA.Value,
+				Next: &packet.PathAttribute{
+					TypeCode: packet.NextHopAttr,
+					Value:    p.BGPPath.NextHop,
+				},
+			},
+		},
+		NLRI: &packet.NLRIAddPath{
+			PathIdentifier: p.BGPPath.PathIdentifier,
+			IP:             pfx.Addr(),
+			Pfxlen:         pfx.Pfxlen(),
+		},
+	}
+
+	updateBytes, err := update.SerializeUpdate()
+	if err != nil {
+		log.Errorf("Unable to serialize BGP Update: %v", err)
+		return nil
+	}
+
+	_, err = u.fsm.con.Write(updateBytes)
+	if err != nil {
+		return fmt.Errorf("Failed sending Update: %v", err)
+	}
+	return nil
+}
+
+// RemovePath withdraws prefix `pfx` from a peer
+func (u *UpdateSenderAddPath) RemovePath(pfx net.Prefix, p *route.Path) bool {
+	log.Warningf("BGP Update Sender: RemovePath not implemented")
+	return false
+}
+
+// UpdateNewClient does nothing
+func (u *UpdateSenderAddPath) UpdateNewClient(client routingtable.RouteTableClient) error {
+	log.Warningf("BGP Update Sender: RemovePath not implemented")
+	return nil
+}
diff --git a/routingtable/adjRIBIn/adj_rib_in_test.go b/routingtable/adjRIBIn/adj_rib_in_test.go
index a458dc780c9320e2c5d57676ec272489b1dcddd5..5659ab805f73b3bf888a08fa8ff6a7dbe8185bdf 100644
--- a/routingtable/adjRIBIn/adj_rib_in_test.go
+++ b/routingtable/adjRIBIn/adj_rib_in_test.go
@@ -30,6 +30,14 @@ func (m *RTMockClient) UpdateNewClient(client routingtable.RouteTableClient) err
 	return fmt.Errorf("Not implemented")
 }
 
+func (m *RTMockClient) Register(routingtable.RouteTableClient) {
+	return
+}
+
+func (m *RTMockClient) Unregister(routingtable.RouteTableClient) {
+	return
+}
+
 // RemovePath removes the path for prefix `pfx`
 func (m *RTMockClient) RemovePath(pfx net.Prefix, p *route.Path) bool {
 	m.removePathParams.pfx = pfx
diff --git a/routingtable/adjRIBOut/adj_rib_out.go b/routingtable/adjRIBOut/adj_rib_out.go
index 8691c5ac87f473946225a35a5fce4823a482c6a0..1ddd93c6e05b835c9952b6e86ba5fe57545ed5e4 100644
--- a/routingtable/adjRIBOut/adj_rib_out.go
+++ b/routingtable/adjRIBOut/adj_rib_out.go
@@ -29,7 +29,7 @@ func New(neighbor *routingtable.Neighbor) *AdjRIBOut {
 
 // UpdateNewClient sends current state to a new client
 func (a *AdjRIBOut) UpdateNewClient(client routingtable.RouteTableClient) error {
-	return fmt.Errorf("Not supported")
+	return nil
 }
 
 // AddPath replaces the path for prefix `pfx`. If the prefix doesn't exist it is added.
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..07b702db3360040de4c4d190a16fc4cabfdb2a38
--- /dev/null
+++ b/routingtable/adjRIBOutAddPath/adj_rib_out_add_path.go
@@ -0,0 +1,104 @@
+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 nil
+}
+
+// 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()
+
+	p.BGPPath.PathIdentifier = 7
+
+	a.rt.AddPath(pfx, p)
+
+	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
+}
diff --git a/routingtable/client_interface.go b/routingtable/client_interface.go
index 63ba81e8d5afa4fb73b0989b2ae519000e56a6b5..0800ceec8db1cb3b758b74b3a1d3c8b7aef62acb 100644
--- a/routingtable/client_interface.go
+++ b/routingtable/client_interface.go
@@ -10,4 +10,6 @@ type RouteTableClient interface {
 	AddPath(net.Prefix, *route.Path) error
 	RemovePath(net.Prefix, *route.Path) bool
 	UpdateNewClient(RouteTableClient) error
+	Register(RouteTableClient)
+	Unregister(RouteTableClient)
 }
diff --git a/routingtable/client_manager_test.go b/routingtable/client_manager_test.go
index 674a9a4ebd8ed8b0a691db6613eb4a931a606838..af2507855bfac8a5d09551b105d7bfc4ae93dd79 100644
--- a/routingtable/client_manager_test.go
+++ b/routingtable/client_manager_test.go
@@ -22,6 +22,12 @@ func (m MockClient) RemovePath(net.Prefix, *route.Path) bool {
 func (m MockClient) UpdateNewClient(RouteTableClient) error {
 	return nil
 }
+func (m MockClient) Register(RouteTableClient) {
+	return
+}
+func (m MockClient) Unregister(RouteTableClient) {
+	return
+}
 
 func TestClients(t *testing.T) {
 	tests := []struct {
@@ -61,7 +67,19 @@ func TestClients(t *testing.T) {
 			cm.Register(client)
 		}
 		ret := cm.Clients()
-		assert.Equal(t, test.expected, ret)
+
+		for _, exp := range test.expected {
+			found := false
+			for _, client := range ret {
+				if exp == client {
+					found = true
+					continue
+				}
+			}
+			if !found {
+				t.Errorf("Test %q failed: Client %v not found in result: %v", test.name, exp, ret)
+			}
+		}
 	}
 }
 
diff --git a/routingtable/locRIB/loc_rib.go b/routingtable/locRIB/loc_rib.go
index 6e030de30ac6cdb3fc51b942b8b2fb68997862c7..dd06e10069108809feb7da2118188a0fbe1bb4a9 100644
--- a/routingtable/locRIB/loc_rib.go
+++ b/routingtable/locRIB/loc_rib.go
@@ -51,7 +51,7 @@ func (a *LocRIB) AddPath(pfx net.Prefix, p *route.Path) error {
 		oldRoute = r.Copy()
 		routeExisted = true
 	}
-	
+
 	// FIXME: in AddPath() we assume that the same reference of route (r) is modified (not responsibility of locRIB). If this implementation changes in the future this code will break.
 	a.rt.AddPath(pfx, p)
 	if !routeExisted {
@@ -59,12 +59,8 @@ func (a *LocRIB) AddPath(pfx net.Prefix, p *route.Path) error {
 	}
 
 	r.PathSelection()
-
 	newRoute := r.Copy()
 
-	fmt.Printf("NEW: %v\n", newRoute.Paths())
-	fmt.Printf("OLD: %v\n", oldRoute.Paths())
-
 	a.propagateChanges(oldRoute, newRoute)
 	return nil
 }
@@ -86,9 +82,6 @@ func (a *LocRIB) RemovePath(pfx net.Prefix, p *route.Path) bool {
 	r = a.rt.Get(pfx)
 	newRoute := r.Copy()
 
-	fmt.Printf("NEW: %v\n", newRoute.Paths())
-	fmt.Printf("OLD: %v\n", oldRoute.Paths())
-
 	a.propagateChanges(oldRoute, newRoute)
 	return true
 }
@@ -108,7 +101,6 @@ func (a *LocRIB) addPathsToClients(oldRoute *route.Route, newRoute *route.Route)
 		newPathsLimit := int(math.Min(float64(newMaxPaths), float64(len(newRoute.Paths()))))
 
 		advertise := route.PathsDiff(newRoute.Paths()[0:newPathsLimit], oldRoute.Paths()[0:oldPathsLimit])
-		fmt.Printf("ADVERTISING PATHS %v TO CLIENTS\n", advertise)
 
 		for _, p := range advertise {
 			client.AddPath(newRoute.Prefix(), p)