diff --git a/protocols/bgp/packet/mp_reach_nlri.go b/protocols/bgp/packet/mp_reach_nlri.go
index e83482e5865dcf0b0084a0aa056c838ae075ed78..b714dc19b03333930e6b9b60d53093e15f957314 100644
--- a/protocols/bgp/packet/mp_reach_nlri.go
+++ b/protocols/bgp/packet/mp_reach_nlri.go
@@ -28,11 +28,7 @@ func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer, opt *EncodeOptions
 	tempBuf.WriteByte(0) // RESERVED
 
 	for cur := n.NLRI; cur != nil; cur = cur.Next {
-		if opt.UseAddPath {
-			n.NLRI.serializeAddPath(tempBuf)
-		} else {
-			n.NLRI.serialize(tempBuf)
-		}
+		cur.serialize(tempBuf, opt.UseAddPath)
 	}
 
 	buf.Write(tempBuf.Bytes())
diff --git a/protocols/bgp/packet/mp_unreach_nlri.go b/protocols/bgp/packet/mp_unreach_nlri.go
index f6c365bb220fb4d76165bcbb8fc207a9b77ae3de..ed2c863d1af21b201695dc11b9eebef08c91ed9f 100644
--- a/protocols/bgp/packet/mp_unreach_nlri.go
+++ b/protocols/bgp/packet/mp_unreach_nlri.go
@@ -4,28 +4,24 @@ import (
 	"bytes"
 	"fmt"
 
-	bnet "github.com/bio-routing/bio-rd/net"
 	"github.com/bio-routing/bio-rd/util/decode"
 	"github.com/taktv6/tflow2/convert"
 )
 
 // MultiProtocolUnreachNLRI represents network layer withdraw information for one prefix of an IP address family (rfc4760)
 type MultiProtocolUnreachNLRI struct {
-	AFI      uint16
-	SAFI     uint8
-	Prefixes []bnet.Prefix
-	PathID   uint32
+	AFI  uint16
+	SAFI uint8
+	NLRI *NLRI
 }
 
 func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer, opt *EncodeOptions) uint16 {
 	tempBuf := bytes.NewBuffer(nil)
 	tempBuf.Write(convert.Uint16Byte(n.AFI))
 	tempBuf.WriteByte(n.SAFI)
-	for _, pfx := range n.Prefixes {
-		if opt.UseAddPath {
-			tempBuf.Write(convert.Uint32Byte(n.PathID))
-		}
-		tempBuf.Write(serializePrefix(pfx))
+
+	for cur := n.NLRI; cur != nil; cur = cur.Next {
+		cur.serialize(tempBuf, opt.UseAddPath)
 	}
 
 	buf.Write(tempBuf.Bytes())
@@ -33,7 +29,7 @@ func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer, opt *EncodeOptio
 	return uint16(tempBuf.Len())
 }
 
-func deserializeMultiProtocolUnreachNLRI(b []byte) (MultiProtocolUnreachNLRI, error) {
+func deserializeMultiProtocolUnreachNLRI(b []byte, addPath bool) (MultiProtocolUnreachNLRI, error) {
 	n := MultiProtocolUnreachNLRI{}
 
 	prefixesLength := len(b) - 3 // 3 <- AFI + SAFI
@@ -41,42 +37,27 @@ func deserializeMultiProtocolUnreachNLRI(b []byte) (MultiProtocolUnreachNLRI, er
 		return n, fmt.Errorf("Invalid length of MP_UNREACH_NLRI: expected more than 3 bytes but got %d", len(b))
 	}
 
-	prefixes := make([]byte, prefixesLength)
+	nlris := make([]byte, prefixesLength)
 	fields := []interface{}{
 		&n.AFI,
 		&n.SAFI,
-		&prefixes,
+		&nlris,
 	}
 	err := decode.Decode(bytes.NewBuffer(b), fields)
 	if err != nil {
 		return MultiProtocolUnreachNLRI{}, err
 	}
 
-	if len(prefixes) == 0 {
+	if len(nlris) == 0 {
 		return n, nil
 	}
 
-	idx := uint16(0)
-	for idx < uint16(len(prefixes)) {
-		pfxLen := prefixes[idx]
-		numBytes := uint16(BytesInAddr(pfxLen))
-		idx++
-
-		r := uint16(len(prefixes)) - idx
-		if r < numBytes {
-			return MultiProtocolUnreachNLRI{}, fmt.Errorf("expected %d bytes for NLRI, only %d remaining", numBytes, r)
-		}
-
-		start := idx
-		end := idx + numBytes
-		pfx, err := deserializePrefix(prefixes[start:end], pfxLen, n.AFI)
-		if err != nil {
-			return MultiProtocolUnreachNLRI{}, err
-		}
-		n.Prefixes = append(n.Prefixes, pfx)
-
-		idx = idx + numBytes
+	buf := bytes.NewBuffer(nlris)
+	nlri, err := decodeNLRIs(buf, uint16(buf.Len()), n.AFI, addPath)
+	if err != nil {
+		return MultiProtocolUnreachNLRI{}, err
 	}
+	n.NLRI = nlri
 
 	return n, nil
 }
diff --git a/protocols/bgp/packet/mp_unreach_nlri_test.go b/protocols/bgp/packet/mp_unreach_nlri_test.go
index 467b19e030dd208f5e1103d81465107f531591ec..a550f3b3a02f5314c5430e000263a061af680385 100644
--- a/protocols/bgp/packet/mp_unreach_nlri_test.go
+++ b/protocols/bgp/packet/mp_unreach_nlri_test.go
@@ -20,8 +20,8 @@ func TestSerializeMultiProtocolUnreachNLRI(t *testing.T) {
 			nlri: MultiProtocolUnreachNLRI{
 				AFI:  IPv6AFI,
 				SAFI: UnicastSAFI,
-				Prefixes: []bnet.Prefix{
-					bnet.NewPfx(bnet.IPv6FromBlocks(0x2620, 0x110, 0x9000, 0, 0, 0, 0, 0), 44),
+				NLRI: &NLRI{
+					Prefix: bnet.NewPfx(bnet.IPv6FromBlocks(0x2620, 0x110, 0x9000, 0, 0, 0, 0, 0), 44),
 				},
 			},
 			expected: []byte{
@@ -35,10 +35,10 @@ func TestSerializeMultiProtocolUnreachNLRI(t *testing.T) {
 			nlri: MultiProtocolUnreachNLRI{
 				AFI:  IPv6AFI,
 				SAFI: UnicastSAFI,
-				Prefixes: []bnet.Prefix{
-					bnet.NewPfx(bnet.IPv6FromBlocks(0x2620, 0x110, 0x9000, 0, 0, 0, 0, 0), 44),
+				NLRI: &NLRI{
+					PathIdentifier: 100,
+					Prefix:         bnet.NewPfx(bnet.IPv6FromBlocks(0x2620, 0x110, 0x9000, 0, 0, 0, 0, 0), 44),
 				},
-				PathID: 100,
 			},
 			expected: []byte{
 				0x00, 0x02, // AFI
diff --git a/protocols/bgp/packet/nlri.go b/protocols/bgp/packet/nlri.go
index b5878b56fbe94354811ef0b685d153af9b4b6c0c..1f4f7f6e4293771349b60d1e581e697f5fa085d4 100644
--- a/protocols/bgp/packet/nlri.go
+++ b/protocols/bgp/packet/nlri.go
@@ -89,20 +89,22 @@ func decodeNLRI(buf *bytes.Buffer, afi uint16, addPath bool) (*NLRI, uint8, erro
 	return nlri, consumed, nil
 }
 
-func (n *NLRI) serialize(buf *bytes.Buffer) uint8 {
-	buf.WriteByte(n.Prefix.Pfxlen())
-	b := n.Prefix.Addr().Bytes()
+func (n *NLRI) serialize(buf *bytes.Buffer, addPath bool) uint8 {
+	numBytes := uint8(0)
 
-	nBytes := BytesInAddr(n.Prefix.Pfxlen())
-	buf.Write(b[:nBytes])
+	if addPath {
+		buf.Write(convert.Uint32Byte(n.PathIdentifier))
+		numBytes += 4
+	}
 
-	return nBytes + 1
-}
+	buf.WriteByte(n.Prefix.Pfxlen())
+	numBytes++
 
-func (n *NLRI) serializeAddPath(buf *bytes.Buffer) uint8 {
-	buf.Write(convert.Uint32Byte(n.PathIdentifier))
+	pfxNumBytes := BytesInAddr(n.Prefix.Pfxlen())
+	buf.Write(n.Prefix.Addr().Bytes()[:pfxNumBytes])
+	numBytes += pfxNumBytes
 
-	return uint8(n.serialize(buf) + 4)
+	return numBytes
 }
 
 // BytesInAddr gets the amount of bytes needed to encode an NLRI of prefix length pfxlen
diff --git a/protocols/bgp/packet/nlri_test.go b/protocols/bgp/packet/nlri_test.go
index ddbc8d85ae8a61d1a0c10c6243f98b22cea98443..1efb81eaf44e758685923c2e553d3890a92c5592 100644
--- a/protocols/bgp/packet/nlri_test.go
+++ b/protocols/bgp/packet/nlri_test.go
@@ -220,6 +220,7 @@ func TestNLRISerialize(t *testing.T) {
 	tests := []struct {
 		name     string
 		nlri     *NLRI
+		addPath  bool
 		expected []byte
 	}{
 		{
@@ -243,51 +244,38 @@ func TestNLRISerialize(t *testing.T) {
 			},
 			expected: []byte{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)
-	}
-}
-
-func TestNLRIAddPathSerialize(t *testing.T) {
-	tests := []struct {
-		name     string
-		nlri     *NLRI
-		expected []byte
-	}{
 		{
-			name: "Test #1",
+			name: "with add-path #1",
 			nlri: &NLRI{
 				PathIdentifier: 100,
 				Prefix:         bnet.NewPfx(bnet.IPv4FromOctets(1, 2, 3, 0), 25),
 			},
+			addPath:  true,
 			expected: []byte{0, 0, 0, 100, 25, 1, 2, 3, 0},
 		},
 		{
-			name: "Test #2",
+			name: "with add-path #2",
 			nlri: &NLRI{
 				PathIdentifier: 100,
 				Prefix:         bnet.NewPfx(bnet.IPv4FromOctets(1, 2, 3, 0), 24),
 			},
+			addPath:  true,
 			expected: []byte{0, 0, 0, 100, 24, 1, 2, 3},
 		},
 		{
-			name: "Test #3",
+			name: "with add-path #3",
 			nlri: &NLRI{
 				PathIdentifier: 100,
 				Prefix:         bnet.NewPfx(bnet.IPv4FromOctets(100, 200, 128, 0), 17),
 			},
+			addPath:  true,
 			expected: []byte{0, 0, 0, 100, 17, 100, 200, 128},
 		},
 	}
 
 	for _, test := range tests {
 		buf := bytes.NewBuffer(nil)
-		test.nlri.serializeAddPath(buf)
+		test.nlri.serialize(buf, test.addPath)
 		res := buf.Bytes()
 		assert.Equal(t, test.expected, res)
 	}
diff --git a/protocols/bgp/packet/path_attributes.go b/protocols/bgp/packet/path_attributes.go
index f162e277801410660406c187d9216400fe294fa3..a09a3e2c81a5e130c4f59fe769f6ed4432db87f1 100644
--- a/protocols/bgp/packet/path_attributes.go
+++ b/protocols/bgp/packet/path_attributes.go
@@ -114,7 +114,7 @@ func decodePathAttr(buf *bytes.Buffer, opt *DecodeOptions) (pa *PathAttribute, c
 			return nil, consumed, fmt.Errorf("Failed to multi protocol reachable NLRI: %v", err)
 		}
 	case MultiProtocolUnreachNLRICode:
-		if err := pa.decodeMultiProtocolUnreachNLRI(buf); err != nil {
+		if err := pa.decodeMultiProtocolUnreachNLRI(buf, opt.AddPath); err != nil {
 			return nil, consumed, fmt.Errorf("Failed to multi protocol unreachable NLRI: %v", err)
 		}
 	case AS4AggregatorAttr:
@@ -153,7 +153,7 @@ func (pa *PathAttribute) decodeMultiProtocolReachNLRI(buf *bytes.Buffer, addPath
 	return nil
 }
 
-func (pa *PathAttribute) decodeMultiProtocolUnreachNLRI(buf *bytes.Buffer) error {
+func (pa *PathAttribute) decodeMultiProtocolUnreachNLRI(buf *bytes.Buffer, addPath bool) error {
 	b := make([]byte, pa.Length)
 	n, err := buf.Read(b)
 	if err != nil {
@@ -163,7 +163,7 @@ func (pa *PathAttribute) decodeMultiProtocolUnreachNLRI(buf *bytes.Buffer) error
 		return fmt.Errorf("Unable to read %d bytes from buffer, only got %d bytes", pa.Length, n)
 	}
 
-	nlri, err := deserializeMultiProtocolUnreachNLRI(b)
+	nlri, err := deserializeMultiProtocolUnreachNLRI(b, addPath)
 	if err != nil {
 		return fmt.Errorf("Unable to decode MP_UNREACH_NLRI: %v", err)
 	}
diff --git a/protocols/bgp/packet/path_attributes_test.go b/protocols/bgp/packet/path_attributes_test.go
index 1513fecf0352ad76f1bbafa6e29c75385d1bbf80..07fff30276f065d4f132b84a84f72f1c8593b43f 100644
--- a/protocols/bgp/packet/path_attributes_test.go
+++ b/protocols/bgp/packet/path_attributes_test.go
@@ -1037,8 +1037,8 @@ func TestDecodeMultiProtocolUnreachNLRI(t *testing.T) {
 				Value: MultiProtocolUnreachNLRI{
 					AFI:  IPv6AFI,
 					SAFI: UnicastSAFI,
-					Prefixes: []bnet.Prefix{
-						bnet.NewPfx(bnet.IPv6FromBlocks(0x2620, 0x110, 0x9000, 0, 0, 0, 0, 0), 44),
+					NLRI: &NLRI{
+						Prefix: bnet.NewPfx(bnet.IPv6FromBlocks(0x2620, 0x110, 0x9000, 0, 0, 0, 0, 0), 44),
 					},
 				},
 			},
@@ -1073,7 +1073,7 @@ func TestDecodeMultiProtocolUnreachNLRI(t *testing.T) {
 			pa := &PathAttribute{
 				Length: l,
 			}
-			err := pa.decodeMultiProtocolUnreachNLRI(bytes.NewBuffer(test.input))
+			err := pa.decodeMultiProtocolUnreachNLRI(bytes.NewBuffer(test.input), false)
 
 			if test.wantFail {
 				if err != nil {
diff --git a/protocols/bgp/packet/update.go b/protocols/bgp/packet/update.go
index 167439ab06b77d669c5de258a252b5c2105794a6..8d142fdfc08a43480ed7a3789678f99da4a14f4d 100644
--- a/protocols/bgp/packet/update.go
+++ b/protocols/bgp/packet/update.go
@@ -18,18 +18,11 @@ type BGPUpdate struct {
 // SerializeUpdate serializes an BGPUpdate to wire format
 func (b *BGPUpdate) SerializeUpdate(opt *EncodeOptions) ([]byte, error) {
 	budget := MaxLen - MinLen
-	nlriLen := 0
 	buf := bytes.NewBuffer(nil)
 
 	withdrawBuf := bytes.NewBuffer(nil)
 	for withdraw := b.WithdrawnRoutes; withdraw != nil; withdraw = withdraw.Next {
-		if opt.UseAddPath {
-			nlriLen = int(withdraw.serializeAddPath(withdrawBuf))
-		} else {
-			nlriLen = int(withdraw.serialize(withdrawBuf))
-		}
-
-		budget -= nlriLen
+		budget -= int(withdraw.serialize(withdrawBuf, opt.UseAddPath))
 		if budget < 0 {
 			return nil, fmt.Errorf("update too long")
 		}
@@ -46,13 +39,7 @@ func (b *BGPUpdate) SerializeUpdate(opt *EncodeOptions) ([]byte, error) {
 
 	nlriBuf := bytes.NewBuffer(nil)
 	for nlri := b.NLRI; nlri != nil; nlri = nlri.Next {
-		if opt.UseAddPath {
-			nlriLen = int(nlri.serializeAddPath(nlriBuf))
-		} else {
-			nlriLen = int(nlri.serialize(nlriBuf))
-		}
-
-		budget -= nlriLen
+		budget -= int(nlri.serialize(nlriBuf, opt.UseAddPath))
 		if budget < 0 {
 			return nil, fmt.Errorf("update too long")
 		}
@@ -92,8 +79,7 @@ func (b *BGPUpdate) SerializeUpdateAddPath(opt *EncodeOptions) ([]byte, error) {
 
 	withdrawBuf := bytes.NewBuffer(nil)
 	for withdraw := b.WithdrawnRoutes; withdraw != nil; withdraw = withdraw.Next {
-		nlriLen := int(withdraw.serialize(withdrawBuf))
-		budget -= nlriLen
+		budget -= int(withdraw.serialize(withdrawBuf, opt.UseAddPath))
 		if budget < 0 {
 			return nil, fmt.Errorf("update too long")
 		}
@@ -110,8 +96,7 @@ func (b *BGPUpdate) SerializeUpdateAddPath(opt *EncodeOptions) ([]byte, error) {
 
 	nlriBuf := bytes.NewBuffer(nil)
 	for nlri := b.NLRI; nlri != nil; nlri = nlri.Next {
-		nlriLen := int(nlri.serialize(nlriBuf))
-		budget -= nlriLen
+		budget -= int(nlri.serialize(nlriBuf, opt.UseAddPath))
 		if budget < 0 {
 			return nil, fmt.Errorf("update too long")
 		}
diff --git a/protocols/bgp/server/fsm_address_family.go b/protocols/bgp/server/fsm_address_family.go
index 04aa26ab9ed70662bd854cbbbea6a3425d9929d7..772a2dbf436cf1256ce965f16f0cb7ac5a2e1647 100644
--- a/protocols/bgp/server/fsm_address_family.go
+++ b/protocols/bgp/server/fsm_address_family.go
@@ -161,8 +161,8 @@ func (f *fsmAddressFamily) multiProtocolWithdraw(path *route.Path, nlri packet.M
 		return
 	}
 
-	for _, pfx := range nlri.Prefixes {
-		f.adjRIBIn.RemovePath(pfx, path)
+	for cur := nlri.NLRI; cur != nil; cur = cur.Next {
+		f.adjRIBIn.RemovePath(cur.Prefix, path)
 	}
 }
 
diff --git a/protocols/bgp/server/update_sender.go b/protocols/bgp/server/update_sender.go
index 87e999caca45a87a124ee1f2269db7169d0eae80..17b021a55504af3e6cba17285da7a33ba9d0a360 100644
--- a/protocols/bgp/server/update_sender.go
+++ b/protocols/bgp/server/update_sender.go
@@ -311,10 +311,12 @@ func (u *UpdateSender) withdrawPrefixMultiProtocol(out io.Writer, pfx bnet.Prefi
 		PathAttributes: &packet.PathAttribute{
 			TypeCode: packet.MultiProtocolUnreachNLRICode,
 			Value: packet.MultiProtocolUnreachNLRI{
-				AFI:      u.addressFamily.afi,
-				SAFI:     u.addressFamily.safi,
-				Prefixes: []bnet.Prefix{pfx},
-				PathID:   pathID,
+				AFI:  u.addressFamily.afi,
+				SAFI: u.addressFamily.safi,
+				NLRI: &packet.NLRI{
+					PathIdentifier: pathID,
+					Prefix:         pfx,
+				},
 			},
 		},
 	}