diff --git a/protocols/bgp/packet/path_attributes.go b/protocols/bgp/packet/path_attributes.go
index 8be484780ee571432d159e63e7b2d4fcf86d2328..e66e834a199abde91d7c5d6d27003977d782c998 100644
--- a/protocols/bgp/packet/path_attributes.go
+++ b/protocols/bgp/packet/path_attributes.go
@@ -342,6 +342,18 @@ func (pa *PathAttribute) setLength(buf *bytes.Buffer) (int, error) {
 	return bytesRead, nil
 }
 
+func (pa *PathAttribute) Copy() *PathAttribute {
+	return &PathAttribute{
+		ExtendedLength: pa.ExtendedLength,
+		Length:         pa.Length,
+		Optional:       pa.Optional,
+		Partial:        pa.Partial,
+		Transitive:     pa.Transitive,
+		TypeCode:       pa.TypeCode,
+		Value:          pa.Value,
+	}
+}
+
 // dumpNBytes is used to dump n bytes of buf. This is useful in case an path attributes
 // length doesn't match a fixed length's attributes length (e.g. ORIGIN is always an octet)
 func dumpNBytes(buf *bytes.Buffer, n uint16) error {
diff --git a/protocols/bgp/server/fsm_established.go b/protocols/bgp/server/fsm_established.go
index e74a660ab859e00b2d70f66175ddc6c750ffd495..f496e859f271c4c24fdee7233257695547dd6ba1 100644
--- a/protocols/bgp/server/fsm_established.go
+++ b/protocols/bgp/server/fsm_established.go
@@ -220,27 +220,51 @@ func (s *establishedState) updates(u *packet.BGPUpdate) {
 			},
 		}
 
-		for pa := u.PathAttributes; pa != nil; pa = pa.Next {
-			switch pa.TypeCode {
-			case packet.OriginAttr:
-				path.BGPPath.Origin = pa.Value.(uint8)
-			case packet.LocalPrefAttr:
-				path.BGPPath.LocalPref = pa.Value.(uint32)
-			case packet.MEDAttr:
-				path.BGPPath.MED = pa.Value.(uint32)
-			case packet.NextHopAttr:
-				path.BGPPath.NextHop = pa.Value.(uint32)
-			case packet.ASPathAttr:
-				path.BGPPath.ASPath = pa.Value.(packet.ASPath)
-				path.BGPPath.ASPathLen = path.BGPPath.ASPath.Length()
-			case packet.CommunitiesAttr:
-				path.BGPPath.Communities = pa.Value.([]uint32)
-			case packet.LargeCommunitiesAttr:
-				path.BGPPath.LargeCommunities = pa.Value.([]packet.LargeCommunity)
+		s.processAttributes(u.PathAttributes, path)
+
+		s.fsm.adjRIBIn.AddPath(pfx, path)
+	}
+}
+
+func (s *establishedState) processAttributes(attrs *packet.PathAttribute, path *route.Path) {
+	var unknownAttributes *packet.PathAttribute
+	var currentUnknown *packet.PathAttribute
+
+	for pa := attrs; pa != nil; pa = pa.Next {
+		switch pa.TypeCode {
+		case packet.OriginAttr:
+			path.BGPPath.Origin = pa.Value.(uint8)
+		case packet.LocalPrefAttr:
+			path.BGPPath.LocalPref = pa.Value.(uint32)
+		case packet.MEDAttr:
+			path.BGPPath.MED = pa.Value.(uint32)
+		case packet.NextHopAttr:
+			path.BGPPath.NextHop = pa.Value.(uint32)
+		case packet.ASPathAttr:
+			path.BGPPath.ASPath = pa.Value.(packet.ASPath)
+			path.BGPPath.ASPathLen = path.BGPPath.ASPath.Length()
+		case packet.CommunitiesAttr:
+			path.BGPPath.Communities = pa.Value.([]uint32)
+		case packet.LargeCommunitiesAttr:
+			path.BGPPath.LargeCommunities = pa.Value.([]packet.LargeCommunity)
+		default:
+			if !pa.Transitive {
+				continue
 			}
+
+			p := pa.Copy()
+			if unknownAttributes == nil {
+				unknownAttributes = p
+				currentUnknown = unknownAttributes
+				continue
+			}
+
+			currentUnknown.Next = p
+			currentUnknown = p
 		}
-		s.fsm.adjRIBIn.AddPath(pfx, path)
 	}
+
+	path.BGPPath.UnknownAttributes = unknownAttributes
 }
 
 func (s *establishedState) keepaliveReceived() (state, string) {
diff --git a/protocols/bgp/server/fsm_established_test.go b/protocols/bgp/server/fsm_established_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..4e92e4eede30ed4b0dfedeb1217e5d11962c6252
--- /dev/null
+++ b/protocols/bgp/server/fsm_established_test.go
@@ -0,0 +1,65 @@
+package server
+
+import (
+	"testing"
+
+	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
+	"github.com/bio-routing/bio-rd/route"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestProcessAttribues(t *testing.T) {
+	unknown3 := &packet.PathAttribute{
+		Transitive: true,
+		TypeCode:   100,
+		Value:      []byte{1, 2, 3, 4},
+		Next:       nil,
+	}
+
+	unknown2 := &packet.PathAttribute{
+		Transitive: false,
+		TypeCode:   150,
+		Value:      []byte{20},
+		Next:       unknown3,
+	}
+
+	unknown1 := &packet.PathAttribute{
+		Transitive: true,
+		TypeCode:   200,
+		Value:      []byte{5, 6},
+		Next:       unknown2,
+	}
+
+	asPath := &packet.PathAttribute{
+		Transitive: true,
+		TypeCode:   packet.ASPathAttr,
+		Value: packet.ASPath{
+			packet.ASPathSegment{
+				Count: 0,
+				Type:  packet.ASSequence,
+				ASNs:  []uint32{},
+			},
+		},
+		Next: unknown1,
+	}
+
+	e := &establishedState{}
+
+	p := &route.Path{
+		BGPPath: &route.BGPPath{},
+	}
+	e.processAttributes(asPath, p)
+
+	expectedCodes := []uint8{200, 100}
+	expectedValues := [][]byte{[]byte{5, 6}, []byte{1, 2, 3, 4}}
+
+	i := 0
+	for attr := p.BGPPath.UnknownAttributes; attr != nil; attr = attr.Next {
+		assert.Equal(t, true, attr.Transitive, "Transitive")
+		assert.Equal(t, expectedCodes[i], attr.TypeCode, "Code")
+		assert.Equal(t, expectedValues[i], attr.Value, "Value")
+		i++
+	}
+
+	assert.Equal(t, i, 2, "Count")
+}
diff --git a/route/bgp_path.go b/route/bgp_path.go
index 0ab7dc4b2a3f6a23d77be1a0613b68515a5d1604..cdb605e42cbc639d36c40c47f528dfda21a67011 100644
--- a/route/bgp_path.go
+++ b/route/bgp_path.go
@@ -11,18 +11,19 @@ import (
 
 // BGPPath represents a set of BGP path attributes
 type BGPPath struct {
-	PathIdentifier   uint32
-	NextHop          uint32
-	LocalPref        uint32
-	ASPath           packet.ASPath
-	ASPathLen        uint16
-	Origin           uint8
-	MED              uint32
-	EBGP             bool
-	BGPIdentifier    uint32
-	Source           uint32
-	Communities      []uint32
-	LargeCommunities []packet.LargeCommunity
+	PathIdentifier    uint32
+	NextHop           uint32
+	LocalPref         uint32
+	ASPath            packet.ASPath
+	ASPathLen         uint16
+	Origin            uint8
+	MED               uint32
+	EBGP              bool
+	BGPIdentifier     uint32
+	Source            uint32
+	Communities       []uint32
+	LargeCommunities  []packet.LargeCommunity
+	UnknownAttributes *packet.PathAttribute
 }
 
 // ECMP determines if routes b and c are euqal in terms of ECMP