diff --git a/protocols/bgp/packet/mp_reach_nlri.go b/protocols/bgp/packet/mp_reach_nlri.go
index 1aa9e92a1cb8d8f97088145a666ac3553d10e8ac..305ae994d1cdb383ac13a4c1455510d3cce0509d 100644
--- a/protocols/bgp/packet/mp_reach_nlri.go
+++ b/protocols/bgp/packet/mp_reach_nlri.go
@@ -7,6 +7,7 @@ import (
 	"github.com/taktv6/tflow2/convert"
 
 	bnet "github.com/bio-routing/bio-rd/net"
+	"github.com/bio-routing/bio-rd/protocols/bgp/types"
 )
 
 // MultiProtocolReachNLRI represents network layer reachability information for one prefix of an IP address family (rfc4760)
@@ -15,9 +16,10 @@ type MultiProtocolReachNLRI struct {
 	SAFI     uint8
 	NextHop  bnet.IP
 	Prefixes []bnet.Prefix
+	PathID   uint32
 }
 
-func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer) uint16 {
+func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer, opt *types.Options) uint16 {
 	nextHop := n.NextHop.Bytes()
 
 	tempBuf := bytes.NewBuffer(nil)
@@ -27,6 +29,9 @@ func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer) uint16 {
 	tempBuf.Write(nextHop)
 	tempBuf.WriteByte(0) // RESERVED
 	for _, pfx := range n.Prefixes {
+		if opt.AddPathRX {
+			tempBuf.Write(convert.Uint32Byte(n.PathID))
+		}
 		tempBuf.Write(serializePrefix(pfx))
 	}
 
diff --git a/protocols/bgp/packet/mp_reach_nlri_test.go b/protocols/bgp/packet/mp_reach_nlri_test.go
index f16ac3c4a181eb3bd0534f0e831bbb00eb09c8cf..73a52bba8c517f8924e65181cafcf376be3dddb0 100644
--- a/protocols/bgp/packet/mp_reach_nlri_test.go
+++ b/protocols/bgp/packet/mp_reach_nlri_test.go
@@ -5,6 +5,7 @@ import (
 	"testing"
 
 	bnet "github.com/bio-routing/bio-rd/net"
+	"github.com/bio-routing/bio-rd/protocols/bgp/types"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -13,6 +14,7 @@ func TestSerializeMultiProtocolReachNLRI(t *testing.T) {
 		name     string
 		nlri     MultiProtocolReachNLRI
 		expected []byte
+		addPath  bool
 	}{
 		{
 			name: "Simple IPv6 prefix",
@@ -32,12 +34,35 @@ func TestSerializeMultiProtocolReachNLRI(t *testing.T) {
 				0x30, 0x26, 0x00, 0x00, 0x06, 0xff, 0x05, // Prefix
 			},
 		},
+		{
+			name: "IPv6 prefix with ADD-PATH",
+			nlri: MultiProtocolReachNLRI{
+				AFI:     IPv6AFI,
+				SAFI:    UnicastSAFI,
+				NextHop: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 0x2),
+				Prefixes: []bnet.Prefix{
+					bnet.NewPfx(bnet.IPv6FromBlocks(0x2600, 0x6, 0xff05, 0, 0, 0, 0, 0), 48),
+				},
+				PathID: 100,
+			},
+			expected: []byte{
+				0x00, 0x02, // AFI
+				0x01,                                                                                                 // SAFI
+				0x10, 0x20, 0x01, 0x06, 0x78, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, // NextHop
+				0x00,                  // RESERVED
+				0x00, 0x00, 0x00, 100, // PathID
+				0x30, 0x26, 0x00, 0x00, 0x06, 0xff, 0x05, // Prefix
+			},
+			addPath: true,
+		},
 	}
 
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
 			buf := &bytes.Buffer{}
-			test.nlri.serialize(buf)
+			test.nlri.serialize(buf, &types.Options{
+				AddPathRX: test.addPath,
+			})
 			assert.Equal(t, test.expected, buf.Bytes())
 		})
 	}
diff --git a/protocols/bgp/packet/mp_unreach_nlri.go b/protocols/bgp/packet/mp_unreach_nlri.go
index 3a78b00f7701a76a663005c404e4757eb934404c..2e3475425ddb19292a6c4d5f355c8456aeac7b03 100644
--- a/protocols/bgp/packet/mp_unreach_nlri.go
+++ b/protocols/bgp/packet/mp_unreach_nlri.go
@@ -5,6 +5,7 @@ import (
 	"fmt"
 
 	bnet "github.com/bio-routing/bio-rd/net"
+	"github.com/bio-routing/bio-rd/protocols/bgp/types"
 	"github.com/taktv6/tflow2/convert"
 )
 
@@ -13,13 +14,17 @@ type MultiProtocolUnreachNLRI struct {
 	AFI      uint16
 	SAFI     uint8
 	Prefixes []bnet.Prefix
+	PathID   uint32
 }
 
-func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer) uint16 {
+func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer, opt *types.Options) uint16 {
 	tempBuf := bytes.NewBuffer(nil)
 	tempBuf.Write(convert.Uint16Byte(n.AFI))
 	tempBuf.WriteByte(n.SAFI)
 	for _, pfx := range n.Prefixes {
+		if opt.AddPathRX {
+			tempBuf.Write(convert.Uint32Byte(n.PathID))
+		}
 		tempBuf.Write(serializePrefix(pfx))
 	}
 
diff --git a/protocols/bgp/packet/mp_unreach_nlri_test.go b/protocols/bgp/packet/mp_unreach_nlri_test.go
index 02e1b00fff6d161b37509e1748d20bd04dcb3d35..c4484f97f71d182a8886854063368b9127154a8f 100644
--- a/protocols/bgp/packet/mp_unreach_nlri_test.go
+++ b/protocols/bgp/packet/mp_unreach_nlri_test.go
@@ -5,6 +5,7 @@ import (
 	"testing"
 
 	bnet "github.com/bio-routing/bio-rd/net"
+	"github.com/bio-routing/bio-rd/protocols/bgp/types"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -13,6 +14,7 @@ func TestSerializeMultiProtocolUnreachNLRI(t *testing.T) {
 		name     string
 		nlri     MultiProtocolUnreachNLRI
 		expected []byte
+		addPath  bool
 	}{
 		{
 			name: "Simple IPv6 prefix",
@@ -29,12 +31,32 @@ func TestSerializeMultiProtocolUnreachNLRI(t *testing.T) {
 				0x2c, 0x26, 0x20, 0x01, 0x10, 0x90, 0x00, // Prefix
 			},
 		},
+		{
+			name: "IPv6 prefix with ADD-PATH",
+			nlri: MultiProtocolUnreachNLRI{
+				AFI:  IPv6AFI,
+				SAFI: UnicastSAFI,
+				Prefixes: []bnet.Prefix{
+					bnet.NewPfx(bnet.IPv6FromBlocks(0x2620, 0x110, 0x9000, 0, 0, 0, 0, 0), 44),
+				},
+				PathID: 100,
+			},
+			expected: []byte{
+				0x00, 0x02, // AFI
+				0x01,                  // SAFI
+				0x00, 0x00, 0x00, 100, // PathID
+				0x2c, 0x26, 0x20, 0x01, 0x10, 0x90, 0x00, // Prefix
+			},
+			addPath: true,
+		},
 	}
 
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
 			buf := &bytes.Buffer{}
-			test.nlri.serialize(buf)
+			test.nlri.serialize(buf, &types.Options{
+				AddPathRX: test.addPath,
+			})
 			assert.Equal(t, test.expected, buf.Bytes())
 		})
 	}
diff --git a/protocols/bgp/packet/path_attributes.go b/protocols/bgp/packet/path_attributes.go
index 22ea8a8c3e1c0ba253e98c87296a7bdde0b92f02..5b5af4ecd816650ed5575dd16ede7f529fc349aa 100644
--- a/protocols/bgp/packet/path_attributes.go
+++ b/protocols/bgp/packet/path_attributes.go
@@ -468,9 +468,9 @@ func (pa *PathAttribute) Serialize(buf *bytes.Buffer, opt *types.Options) uint16
 	case LargeCommunitiesAttr:
 		pathAttrLen = uint16(pa.serializeLargeCommunities(buf))
 	case MultiProtocolReachNLRICode:
-		pathAttrLen = pa.serializeMultiProtocolReachNLRI(buf)
+		pathAttrLen = pa.serializeMultiProtocolReachNLRI(buf, opt)
 	case MultiProtocolUnreachNLRICode:
-		pathAttrLen = pa.serializeMultiProtocolUnreachNLRI(buf)
+		pathAttrLen = pa.serializeMultiProtocolUnreachNLRI(buf, opt)
 	case OriginatorIDAttr:
 		pathAttrLen = uint16(pa.serializeOriginatorID(buf))
 	case ClusterListAttr:
@@ -695,22 +695,22 @@ func (pa *PathAttribute) serializeUnknownAttribute(buf *bytes.Buffer) uint16 {
 	return uint16(len(b) + 2)
 }
 
-func (pa *PathAttribute) serializeMultiProtocolReachNLRI(buf *bytes.Buffer) uint16 {
+func (pa *PathAttribute) serializeMultiProtocolReachNLRI(buf *bytes.Buffer, opt *types.Options) uint16 {
 	v := pa.Value.(MultiProtocolReachNLRI)
 	pa.Optional = true
 
 	tempBuf := bytes.NewBuffer(nil)
-	v.serialize(tempBuf)
+	v.serialize(tempBuf, opt)
 
 	return pa.serializeGeneric(tempBuf.Bytes(), buf)
 }
 
-func (pa *PathAttribute) serializeMultiProtocolUnreachNLRI(buf *bytes.Buffer) uint16 {
+func (pa *PathAttribute) serializeMultiProtocolUnreachNLRI(buf *bytes.Buffer, opt *types.Options) uint16 {
 	v := pa.Value.(MultiProtocolUnreachNLRI)
 	pa.Optional = true
 
 	tempBuf := bytes.NewBuffer(nil)
-	v.serialize(tempBuf)
+	v.serialize(tempBuf, opt)
 
 	return pa.serializeGeneric(tempBuf.Bytes(), buf)
 }
diff --git a/protocols/bgp/server/fsm_open_sent.go b/protocols/bgp/server/fsm_open_sent.go
index 3ece04475f645340a60e814e3452110ce56ab5ff..5ac4e09aa72251641c3e6268badabf90ddcf7792 100644
--- a/protocols/bgp/server/fsm_open_sent.go
+++ b/protocols/bgp/server/fsm_open_sent.go
@@ -179,10 +179,7 @@ func (s *openSentState) processMultiProtocolCapability(cap packet.MultiProtocolC
 }
 
 func (s *openSentState) processAddPathCapability(addPathCap packet.AddPathCapability) {
-	if addPathCap.AFI != 1 {
-		return
-	}
-	if addPathCap.SAFI != 1 {
+	if addPathCap.SAFI != packet.UnicastSAFI {
 		return
 	}
 
diff --git a/protocols/bgp/server/peer.go b/protocols/bgp/server/peer.go
index 02cf053bf000c5d1dd232c2243b7b617062a8fcf..6cb5da02fb20ce1d5e8772dd8fdeab9e210e5886 100644
--- a/protocols/bgp/server/peer.go
+++ b/protocols/bgp/server/peer.go
@@ -136,10 +136,7 @@ func newPeer(c config.Peer, rib *locRIB.LocRIB, server *bgpServer) (*peer, error
 
 	caps := make(packet.Capabilities, 0)
 
-	addPathEnabled, addPathCap := handleAddPathCapability(c)
-	if addPathEnabled {
-		caps = append(caps, addPathCap)
-	}
+	caps = append(caps, addPathCapabilities(c)...)
 
 	caps = append(caps, asn4Capability(c))
 
@@ -174,7 +171,9 @@ func multiProtocolCapability(afi uint16) packet.Capability {
 	}
 }
 
-func handleAddPathCapability(c config.Peer) (bool, packet.Capability) {
+func addPathCapabilities(c config.Peer) []packet.Capability {
+	caps := make([]packet.Capability, 0)
+
 	addPath := uint8(0)
 	if c.AddPathRecv {
 		addPath += packet.AddPathReceive
@@ -184,17 +183,30 @@ func handleAddPathCapability(c config.Peer) (bool, packet.Capability) {
 	}
 
 	if addPath == 0 {
-		return false, packet.Capability{}
+		return caps
 	}
 
-	return true, packet.Capability{
+	caps = append(caps, packet.Capability{
 		Code: packet.AddPathCapabilityCode,
 		Value: packet.AddPathCapability{
 			AFI:         packet.IPv4AFI,
 			SAFI:        packet.UnicastSAFI,
 			SendReceive: addPath,
 		},
+	})
+
+	if c.IPv6 {
+		caps = append(caps, packet.Capability{
+			Code: packet.AddPathCapabilityCode,
+			Value: packet.AddPathCapability{
+				AFI:         packet.IPv6AFI,
+				SAFI:        packet.UnicastSAFI,
+				SendReceive: addPath,
+			},
+		})
 	}
+
+	return caps
 }
 
 func filterOrDefault(f *filter.Filter) *filter.Filter {
diff --git a/protocols/bgp/server/update_sender.go b/protocols/bgp/server/update_sender.go
index 478e9a08b137bf306ddbab0453b42ad869636411..f154cab7bcdac3ef38a054d23bb2d6b1e03419cd 100644
--- a/protocols/bgp/server/update_sender.go
+++ b/protocols/bgp/server/update_sender.go
@@ -102,6 +102,10 @@ func (u *UpdateSender) sender(aggrTime time.Duration) {
 			for _, pfx := range pathNLRIs.pfxs {
 				budget -= int(packet.BytesInAddr(pfx.Pfxlen())) + 1
 
+				if u.fsm.options.AddPathRX {
+					budget -= 4
+				}
+
 				if budget < 0 {
 					updatesPrefixes = append(updatesPrefixes, prefixes)
 					prefixes = make([]bnet.Prefix, 0, 1)
@@ -183,6 +187,7 @@ func (u *UpdateSender) bgpUpdateMultiProtocol(pfxs []bnet.Prefix, pa *packet.Pat
 			SAFI:     packet.UnicastSAFI,
 			NextHop:  nextHop,
 			Prefixes: pfxs,
+			PathID:   pathID,
 		},
 	}
 	attrs.Next = pa
@@ -224,7 +229,7 @@ func (u *UpdateSender) RemovePath(pfx bnet.Prefix, p *route.Path) bool {
 
 func (u *UpdateSender) withdrawPrefix(pfx bnet.Prefix, p *route.Path) error {
 	if u.fsm.options.SupportsMultiProtocol {
-		return withDrawPrefixesMultiProtocol(u.fsm.con, u.fsm.options, pfx)
+		return withDrawPrefixesMultiProtocol(u.fsm.con, u.fsm.options, pfx, p)
 	}
 
 	return withDrawPrefixesAddPath(u.fsm.con, u.fsm.options, pfx, p)
diff --git a/protocols/bgp/server/withdraw.go b/protocols/bgp/server/withdraw.go
index 013f6ce33c5b247d6021292c3b611f3c325f24f5..c3793bf7c86016413651f7747ff303cc3532d912 100644
--- a/protocols/bgp/server/withdraw.go
+++ b/protocols/bgp/server/withdraw.go
@@ -59,7 +59,12 @@ func withDrawPrefixesAddPath(out io.Writer, opt *types.Options, pfx net.Prefix,
 	return serializeAndSendUpdate(out, update, opt)
 }
 
-func withDrawPrefixesMultiProtocol(out io.Writer, opt *types.Options, pfx net.Prefix) error {
+func withDrawPrefixesMultiProtocol(out io.Writer, opt *types.Options, pfx net.Prefix, p *route.Path) error {
+	pathID := uint32(0)
+	if p.BGPPath != nil {
+		pathID = p.BGPPath.PathIdentifier
+	}
+
 	update := &packet.BGPUpdate{
 		PathAttributes: &packet.PathAttribute{
 			TypeCode: packet.MultiProtocolUnreachNLRICode,
@@ -67,8 +72,10 @@ func withDrawPrefixesMultiProtocol(out io.Writer, opt *types.Options, pfx net.Pr
 				AFI:      packet.IPv6AFI,
 				SAFI:     packet.UnicastSAFI,
 				Prefixes: []net.Prefix{pfx},
+				PathID:   pathID,
 			},
 		},
 	}
+
 	return serializeAndSendUpdate(out, update, opt)
 }
diff --git a/protocols/bgp/server/withdraw_test.go b/protocols/bgp/server/withdraw_test.go
index 393be032dcd178b2cef772f576b24e1c5b2d29e4..59fc61780bde64a90bfe3c1f46d43b9b0774ad28 100644
--- a/protocols/bgp/server/withdraw_test.go
+++ b/protocols/bgp/server/withdraw_test.go
@@ -91,7 +91,7 @@ func TestWithDrawPrefixesMultiProtocol(t *testing.T) {
 			opt := &types.Options{
 				AddPathRX: false,
 			}
-			err := withDrawPrefixesMultiProtocol(buf, opt, test.Prefix)
+			err := withDrawPrefixesMultiProtocol(buf, opt, test.Prefix, &route.Path{})
 			if err != nil {
 				t.Fatalf("unexpected error: %v", err)
 			}