diff --git a/protocols/bgp/packet/decode_options.go b/protocols/bgp/packet/decode_options.go
index 9cea580caaccdd2c2176bae4ab5081f281a6f729..fc50c946ed8027f74e6b0ada18eb54387eccd33e 100644
--- a/protocols/bgp/packet/decode_options.go
+++ b/protocols/bgp/packet/decode_options.go
@@ -1,5 +1,7 @@
 package packet
 
+// DecodeOptions represents options for the BGP message decoder
 type DecodeOptions struct {
+	AddPath     bool
 	Use32BitASN bool
 }
diff --git a/protocols/bgp/packet/decoder.go b/protocols/bgp/packet/decoder.go
index a6f226e49150210b4e3b781a30c571d18b191048..736137582bf1d73f5b474297cdaaf3c6cd8ba167 100644
--- a/protocols/bgp/packet/decoder.go
+++ b/protocols/bgp/packet/decoder.go
@@ -49,7 +49,7 @@ func decodeUpdateMsg(buf *bytes.Buffer, l uint16, opt *DecodeOptions) (*BGPUpdat
 		return msg, err
 	}
 
-	msg.WithdrawnRoutes, err = decodeNLRIs(buf, uint16(msg.WithdrawnRoutesLen), IPv4AFI)
+	msg.WithdrawnRoutes, err = decodeNLRIs(buf, uint16(msg.WithdrawnRoutesLen), IPv4AFI, opt.AddPath)
 	if err != nil {
 		return msg, err
 	}
@@ -66,7 +66,7 @@ func decodeUpdateMsg(buf *bytes.Buffer, l uint16, opt *DecodeOptions) (*BGPUpdat
 
 	nlriLen := uint16(l) - 4 - uint16(msg.TotalPathAttrLen) - uint16(msg.WithdrawnRoutesLen)
 	if nlriLen > 0 {
-		msg.NLRI, err = decodeNLRIs(buf, nlriLen, IPv4AFI)
+		msg.NLRI, err = decodeNLRIs(buf, nlriLen, IPv4AFI, opt.AddPath)
 		if err != nil {
 			return msg, err
 		}
diff --git a/protocols/bgp/packet/mp_reach_nlri.go b/protocols/bgp/packet/mp_reach_nlri.go
index 513bf5d40265adcca1e00e4186752139eddcd126..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())
@@ -40,7 +36,7 @@ func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer, opt *EncodeOptions
 	return uint16(tempBuf.Len())
 }
 
-func deserializeMultiProtocolReachNLRI(b []byte) (MultiProtocolReachNLRI, error) {
+func deserializeMultiProtocolReachNLRI(b []byte, addPath bool) (MultiProtocolReachNLRI, error) {
 	n := MultiProtocolReachNLRI{}
 	nextHopLength := uint8(0)
 
@@ -80,7 +76,7 @@ func deserializeMultiProtocolReachNLRI(b []byte) (MultiProtocolReachNLRI, error)
 	variable = variable[1+nextHopLength:] // 1 <- RESERVED field
 
 	buf := bytes.NewBuffer(variable)
-	nlri, err := decodeNLRIs(buf, uint16(buf.Len()), n.AFI)
+	nlri, err := decodeNLRIs(buf, uint16(buf.Len()), n.AFI, addPath)
 	if err != nil {
 		return MultiProtocolReachNLRI{}, err
 	}
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 9406c776d2dcadd66f96a4bd71220a6466d2ce31..1f4f7f6e4293771349b60d1e581e697f5fa085d4 100644
--- a/protocols/bgp/packet/nlri.go
+++ b/protocols/bgp/packet/nlri.go
@@ -6,16 +6,22 @@ import (
 	"math"
 
 	bnet "github.com/bio-routing/bio-rd/net"
+	"github.com/bio-routing/bio-rd/util/decode"
 	"github.com/taktv6/tflow2/convert"
 )
 
+const (
+	pathIdentifierLen = 4
+)
+
+// NLRI represents a Network Layer Reachability Information
 type NLRI struct {
 	PathIdentifier uint32
 	Prefix         bnet.Prefix
 	Next           *NLRI
 }
 
-func decodeNLRIs(buf *bytes.Buffer, length uint16, afi uint16) (*NLRI, error) {
+func decodeNLRIs(buf *bytes.Buffer, length uint16, afi uint16, addPath bool) (*NLRI, error) {
 	var ret *NLRI
 	var eol *NLRI
 	var nlri *NLRI
@@ -24,7 +30,7 @@ func decodeNLRIs(buf *bytes.Buffer, length uint16, afi uint16) (*NLRI, error) {
 	p := uint16(0)
 
 	for p < length {
-		nlri, consumed, err = decodeNLRI(buf, afi)
+		nlri, consumed, err = decodeNLRI(buf, afi, addPath)
 		if err != nil {
 			return nil, fmt.Errorf("Unable to decode NLRI: %v", err)
 		}
@@ -43,10 +49,22 @@ func decodeNLRIs(buf *bytes.Buffer, length uint16, afi uint16) (*NLRI, error) {
 	return ret, nil
 }
 
-func decodeNLRI(buf *bytes.Buffer, afi uint16) (*NLRI, uint8, error) {
+func decodeNLRI(buf *bytes.Buffer, afi uint16, addPath bool) (*NLRI, uint8, error) {
 	nlri := &NLRI{}
 
 	consumed := uint8(0)
+
+	if addPath {
+		err := decode.Decode(buf, []interface{}{
+			&nlri.PathIdentifier,
+		})
+		if err != nil {
+			return nil, consumed, fmt.Errorf("Unable to decode path identifier: %v", err)
+		}
+
+		consumed += pathIdentifierLen
+	}
+
 	pfxLen, err := buf.ReadByte()
 	if err != nil {
 		return nil, consumed, err
@@ -71,20 +89,22 @@ func decodeNLRI(buf *bytes.Buffer, afi uint16) (*NLRI, uint8, error) {
 	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 bd4f6653c5e18b905abdb67b0d4ac176b6677a16..1efb81eaf44e758685923c2e553d3890a92c5592 100644
--- a/protocols/bgp/packet/nlri_test.go
+++ b/protocols/bgp/packet/nlri_test.go
@@ -46,7 +46,7 @@ func TestDecodeNLRIs(t *testing.T) {
 
 	for _, test := range tests {
 		buf := bytes.NewBuffer(test.input)
-		res, err := decodeNLRIs(buf, uint16(len(test.input)), IPv4AFI)
+		res, err := decodeNLRIs(buf, uint16(len(test.input)), IPv4AFI, false)
 
 		if test.wantFail && err == nil {
 			t.Errorf("Expected error did not happen for test %q", test.name)
@@ -64,6 +64,7 @@ func TestDecodeNLRI(t *testing.T) {
 	tests := []struct {
 		name     string
 		input    []byte
+		addPath  bool
 		wantFail bool
 		expected *NLRI
 	}{
@@ -101,6 +102,56 @@ func TestDecodeNLRI(t *testing.T) {
 			},
 			wantFail: true,
 		},
+
+		{
+			name: "Valid NRLI #1 add path",
+			input: []byte{
+				0, 0, 0, 10, 24, 192, 168, 0,
+			},
+			addPath:  true,
+			wantFail: false,
+			expected: &NLRI{
+				PathIdentifier: 10,
+				Prefix:         bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 24),
+			},
+		},
+		{
+			name: "Valid NRLI #2 add path",
+			input: []byte{
+				0, 0, 1, 0, 25, 192, 168, 0, 128,
+			},
+			addPath:  true,
+			wantFail: false,
+			expected: &NLRI{
+				PathIdentifier: 256,
+				Prefix:         bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 128), 25),
+			},
+		},
+		{
+			name: "Incomplete path Identifier",
+			input: []byte{
+				0, 0, 0,
+			},
+			addPath:  true,
+			wantFail: true,
+		},
+		{
+			name: "Incomplete NLRI #1  add path",
+			input: []byte{
+				0, 0, 1, 0, 25, 192, 168, 0,
+			},
+			addPath:  true,
+			wantFail: true,
+		},
+		{
+			name: "Incomplete NLRI #2  add path",
+			input: []byte{
+				0, 0, 1, 0, 25,
+			},
+			addPath:  true,
+			wantFail: true,
+		},
+
 		{
 			name:     "Empty input",
 			input:    []byte{},
@@ -110,7 +161,7 @@ func TestDecodeNLRI(t *testing.T) {
 
 	for _, test := range tests {
 		buf := bytes.NewBuffer(test.input)
-		res, _, err := decodeNLRI(buf, IPv4AFI)
+		res, _, err := decodeNLRI(buf, IPv4AFI, test.addPath)
 
 		if test.wantFail && err == nil {
 			t.Errorf("Expected error did not happen for test %q", test.name)
@@ -169,6 +220,7 @@ func TestNLRISerialize(t *testing.T) {
 	tests := []struct {
 		name     string
 		nlri     *NLRI
+		addPath  bool
 		expected []byte
 	}{
 		{
@@ -192,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 ae81d961753c15059925ef26711c5cc99234ff23..a09a3e2c81a5e130c4f59fe769f6ed4432db87f1 100644
--- a/protocols/bgp/packet/path_attributes.go
+++ b/protocols/bgp/packet/path_attributes.go
@@ -110,11 +110,11 @@ func decodePathAttr(buf *bytes.Buffer, opt *DecodeOptions) (pa *PathAttribute, c
 			return nil, consumed, fmt.Errorf("Failed to decode OriginatorID: %v", err)
 		}
 	case MultiProtocolReachNLRICode:
-		if err := pa.decodeMultiProtocolReachNLRI(buf); err != nil {
+		if err := pa.decodeMultiProtocolReachNLRI(buf, opt.AddPath); err != nil {
 			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:
@@ -134,7 +134,7 @@ func decodePathAttr(buf *bytes.Buffer, opt *DecodeOptions) (pa *PathAttribute, c
 	return pa, consumed + pa.Length, nil
 }
 
-func (pa *PathAttribute) decodeMultiProtocolReachNLRI(buf *bytes.Buffer) error {
+func (pa *PathAttribute) decodeMultiProtocolReachNLRI(buf *bytes.Buffer, addPath bool) error {
 	b := make([]byte, pa.Length)
 	n, err := buf.Read(b)
 	if err != nil {
@@ -144,7 +144,7 @@ func (pa *PathAttribute) decodeMultiProtocolReachNLRI(buf *bytes.Buffer) error {
 		return fmt.Errorf("Unable to read %d bytes from buffer, only got %d bytes", pa.Length, n)
 	}
 
-	nlri, err := deserializeMultiProtocolReachNLRI(b)
+	nlri, err := deserializeMultiProtocolReachNLRI(b, addPath)
 	if err != nil {
 		return fmt.Errorf("Unable to decode MP_REACH_NLRI: %v", err)
 	}
@@ -153,7 +153,7 @@ func (pa *PathAttribute) decodeMultiProtocolReachNLRI(buf *bytes.Buffer) error {
 	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 2ddc92834c5592ab5ac30d5274712a389f543be4..07fff30276f065d4f132b84a84f72f1c8593b43f 100644
--- a/protocols/bgp/packet/path_attributes_test.go
+++ b/protocols/bgp/packet/path_attributes_test.go
@@ -903,6 +903,7 @@ func TestDecodeMultiProtocolReachNLRI(t *testing.T) {
 	tests := []struct {
 		name           string
 		input          []byte
+		addPath        bool
 		wantFail       bool
 		explicitLength uint16
 		expected       *PathAttribute
@@ -992,7 +993,7 @@ func TestDecodeMultiProtocolReachNLRI(t *testing.T) {
 			pa := &PathAttribute{
 				Length: l,
 			}
-			err := pa.decodeMultiProtocolReachNLRI(bytes.NewBuffer(test.input))
+			err := pa.decodeMultiProtocolReachNLRI(bytes.NewBuffer(test.input), test.addPath)
 
 			if test.wantFail {
 				if err != nil {
@@ -1036,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),
 					},
 				},
 			},
@@ -1072,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,
+				},
 			},
 		},
 	}