diff --git a/protocols/isis/packet/header_test.go b/protocols/isis/packet/header_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..2d39eb688a0fcab0f9d5be0c55b463a7761b6340
--- /dev/null
+++ b/protocols/isis/packet/header_test.go
@@ -0,0 +1,46 @@
+package packet
+
+import (
+	"bytes"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestHeaderEncode(t *testing.T) {
+	tests := []struct {
+		name     string
+		input    *ISISHeader
+		expected []byte
+	}{
+		{
+			name: "Test #1",
+			input: &ISISHeader{
+				ProtoDiscriminator:  0x83,
+				LengthIndicator:     27,
+				ProtocolIDExtension: 0,
+				IDLength:            0,
+				PDUType:             16,
+				Version:             1,
+				MaxAreaAddresses:    0,
+			},
+			expected: []byte{
+				0x83,
+				27,
+				0,
+				0,
+				16,
+				1,
+				0,
+				0,
+			},
+		},
+	}
+
+	for _, test := range tests {
+		buf := bytes.NewBuffer(nil)
+		test.input.Serialize(buf)
+		res := buf.Bytes()
+		assert.Equalf(t, test.expected, res, "%s failed", test.name)
+	}
+}
diff --git a/protocols/isis/packet/hello.go b/protocols/isis/packet/hello.go
index 5d3494a90186c7d51117b22d48d8bd79e973bc3f..d40d4383ce4b9931843c27e2e06109f93cc3d544 100644
--- a/protocols/isis/packet/hello.go
+++ b/protocols/isis/packet/hello.go
@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"fmt"
 
+	"github.com/bio-routing/bio-rd/protocols/isis/types"
 	"github.com/taktv6/tflow2/convert"
 )
 
@@ -19,7 +20,7 @@ type L2Hello struct {
 
 type P2PHello struct {
 	CircuitType    uint8
-	SystemID       [6]byte
+	SystemID       types.SystemID
 	HoldingTimer   uint16
 	PDULength      uint16
 	LocalCircuitID uint8
@@ -28,7 +29,7 @@ type P2PHello struct {
 
 const (
 	P2PHelloMinSize = 20
-	ISISHeaderSize = 8
+	ISISHeaderSize  = 8
 	L2CircuitType   = 2
 )
 
diff --git a/protocols/isis/packet/isis_test.go b/protocols/isis/packet/isis_test.go
index 2d39eb688a0fcab0f9d5be0c55b463a7761b6340..21a9495c506dc991bb5b9650162b870940214520 100644
--- a/protocols/isis/packet/isis_test.go
+++ b/protocols/isis/packet/isis_test.go
@@ -4,43 +4,161 @@ import (
 	"bytes"
 	"testing"
 
+	"github.com/bio-routing/bio-rd/protocols/isis/types"
 	"github.com/stretchr/testify/assert"
 )
 
-func TestHeaderEncode(t *testing.T) {
+func TestDecode(t *testing.T) {
 	tests := []struct {
 		name     string
-		input    *ISISHeader
-		expected []byte
+		input    []byte
+		wantFail bool
+		expected *ISISPacket
 	}{
 		{
-			name: "Test #1",
-			input: &ISISHeader{
-				ProtoDiscriminator:  0x83,
-				LengthIndicator:     27,
-				ProtocolIDExtension: 0,
-				IDLength:            0,
-				PDUType:             16,
-				Version:             1,
-				MaxAreaAddresses:    0,
+			name: "P2P Hello",
+			input: []byte{
+				// LLC
+				0xfe, // DSAP
+				0xfe, // SSAP
+				0x03, // Control Fields
+
+				// Header
+				0x83,
+				20,
+				1,
+				0,
+				17, // PDU Type P2P Hello
+				1,
+				0,
+				0,
+
+				// P2P Hello
+				02,
+				0, 0, 0, 0, 0, 2,
+				0, 27,
+				0, 50,
+				1,
+
+				//TLVs
+				240, 5, 0x02, 0x00, 0x00, 0x01, 0x4b,
+				129, 2, 0xcc, 0x8e,
+				132, 4, 192, 168, 1, 0,
+				1, 6, 0x05, 0x49, 0x00, 0x01, 0x00, 0x10,
+				211, 3, 0, 0, 0,
 			},
-			expected: []byte{
+			wantFail: false,
+			expected: &ISISPacket{
+				Header: &ISISHeader{
+					ProtoDiscriminator:  0x83,
+					LengthIndicator:     20,
+					ProtocolIDExtension: 1,
+					IDLength:            0,
+					PDUType:             17,
+					Version:             1,
+					MaxAreaAddresses:    0,
+				},
+				Body: &P2PHello{
+					CircuitType:    2,
+					SystemID:       types.SystemID{0, 0, 0, 0, 0, 2},
+					HoldingTimer:   27,
+					PDULength:      50,
+					LocalCircuitID: 1,
+					TLVs: []TLV{
+						&P2PAdjacencyStateTLV{
+							TLVType:                240,
+							TLVLength:              5,
+							AdjacencyState:         2,
+							ExtendedLocalCircuitID: 0x0000014b,
+						},
+						&ProtocolsSupportedTLV{
+							TLVType:                 129,
+							TLVLength:               2,
+							NerworkLayerProtocolIDs: []uint8{0xcc, 0x8e},
+						},
+						&IPInterfaceAddressTLV{
+							TLVType:     132,
+							TLVLength:   4,
+							IPv4Address: 3232235776,
+						},
+						&AreaAddressesTLV{
+							TLVType:   1,
+							TLVLength: 6,
+							AreaIDs: []types.AreaID{
+								{
+									0x49, 0x00, 0x01, 0x00, 0x10,
+								},
+							},
+						},
+						&UnknownTLV{
+							TLVType:   211,
+							TLVLength: 3,
+							TLVValue:  []byte{0, 0, 0},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "Incomplete header",
+			input: []byte{
+				// LLC
+				0xfe, // DSAP
+				0xfe, // SSAP
+				0x03, // Control Fields
+
+				// Header
 				0x83,
-				27,
+				20,
+				1,
 				0,
+			},
+			wantFail: true,
+		},
+		{
+			name: "Incomplete P2P Hello",
+			input: []byte{
+				// LLC
+				0xfe, // DSAP
+				0xfe, // SSAP
+				0x03, // Control Fields
+
+				// Header
+				0x83,
+				20,
+				1,
 				0,
-				16,
+				17, // PDU Type P2P Hello
 				1,
 				0,
 				0,
+
+				// P2P Hello
+				02,
+				0, 0, 0, 0, 0, 2,
+				0, 27,
 			},
+			wantFail: true,
 		},
 	}
 
 	for _, test := range tests {
-		buf := bytes.NewBuffer(nil)
-		test.input.Serialize(buf)
-		res := buf.Bytes()
-		assert.Equalf(t, test.expected, res, "%s failed", test.name)
+		buf := bytes.NewBuffer(test.input)
+		pkt, err := Decode(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.Equalf(t, test.expected, pkt, "Test %q", test.name)
 	}
 }
diff --git a/protocols/isis/packet/tlv.go b/protocols/isis/packet/tlv.go
index 4499391df08e0da84401f1c1c1068005c4f0414e..6a545c48009f4f1f656dd5df609f434c0c4b37b8 100644
--- a/protocols/isis/packet/tlv.go
+++ b/protocols/isis/packet/tlv.go
@@ -3,8 +3,6 @@ package packet
 import (
 	"bytes"
 	"fmt"
-
-	log "github.com/sirupsen/logrus"
 )
 
 // TLV is an interface that all TLVs must fulfill
@@ -67,13 +65,7 @@ func readTLVs(buf *bytes.Buffer) ([]TLV, error) {
 		case P2PAdjacencyStateTLVType:
 			tlv, _, err = readP2PAdjacencyStateTLV(buf, tlvType, tlvLength)
 		default:
-			log.Warningf("Unknown type: %d", tlvType)
-			nirvana := make([]byte, tlvLength)
-			_, err = buf.Read(nirvana)
-			if err != nil {
-				return nil, fmt.Errorf("Unable to read: %v", err)
-			}
-			continue
+			tlv, err = readUnknownTLV(buf, tlvType, tlvLength)
 		}
 
 		if err != nil {
diff --git a/protocols/isis/packet/tlv_unknown.go b/protocols/isis/packet/tlv_unknown.go
new file mode 100644
index 0000000000000000000000000000000000000000..b89b7f3bae13cab6727ed3ac1ec98cf9e713d1f2
--- /dev/null
+++ b/protocols/isis/packet/tlv_unknown.go
@@ -0,0 +1,54 @@
+package packet
+
+import (
+	"bytes"
+	"fmt"
+)
+
+// UnknownTLV represents an unknown TLV
+type UnknownTLV struct {
+	TLVType   uint8
+	TLVLength uint8
+	TLVValue  []byte
+}
+
+func readUnknownTLV(buf *bytes.Buffer, tlvType uint8, tlvLength uint8) (*UnknownTLV, error) {
+	pdu := &UnknownTLV{
+		TLVType:   tlvType,
+		TLVLength: tlvLength,
+		TLVValue:  make([]byte, tlvLength),
+	}
+
+	n, err := buf.Read(pdu.TLVValue)
+	if err != nil {
+		return nil, fmt.Errorf("Unable to read: %v", err)
+	}
+
+	if n != int(tlvLength) {
+		return nil, fmt.Errorf("Read incomplete")
+	}
+
+	return pdu, nil
+}
+
+// Type gets the type of the TLV
+func (u UnknownTLV) Type() uint8 {
+	return u.TLVType
+}
+
+// Length gets the length of the TLV
+func (u UnknownTLV) Length() uint8 {
+	return u.TLVLength
+}
+
+// Value gets the TLV itself
+func (u *UnknownTLV) Value() interface{} {
+	return u
+}
+
+// Serialize serializes a protocols supported TLV
+func (u UnknownTLV) Serialize(buf *bytes.Buffer) {
+	buf.WriteByte(u.TLVType)
+	buf.WriteByte(u.TLVLength)
+	buf.Write(u.TLVValue)
+}
diff --git a/protocols/isis/packet/tlv_unknown_test.go b/protocols/isis/packet/tlv_unknown_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..5b0f76dca6c0654cc243b9d71cbd141a75ad870c
--- /dev/null
+++ b/protocols/isis/packet/tlv_unknown_test.go
@@ -0,0 +1,85 @@
+package packet
+
+import (
+	"bytes"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestReadUnknownTLV(t *testing.T) {
+	tests := []struct {
+		name      string
+		input     []byte
+		tlvType   uint8
+		tlvLength uint8
+		wantFail  bool
+		expected  *UnknownTLV
+	}{
+		{
+			name:      "Full",
+			input:     []byte{1, 1, 1},
+			tlvType:   100,
+			tlvLength: 3,
+			wantFail:  false,
+			expected: &UnknownTLV{
+				TLVType:   100,
+				TLVLength: 3,
+				TLVValue:  []byte{1, 1, 1},
+			},
+		},
+		{
+			name:      "Incomplete",
+			input:     []byte{1, 1},
+			tlvType:   100,
+			tlvLength: 3,
+			wantFail:  true,
+		},
+	}
+
+	for _, test := range tests {
+		buf := bytes.NewBuffer(test.input)
+		tlv, err := readUnknownTLV(buf, test.tlvType, test.tlvLength)
+
+		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.Equalf(t, test.expected, tlv, "Test %q", test.name)
+	}
+}
+
+func TestUnknownTLVSerialize(t *testing.T) {
+	tests := []struct {
+		name     string
+		input    *UnknownTLV
+		expected []byte
+	}{
+		{
+			name: "Full",
+			input: &UnknownTLV{
+				TLVType:   100,
+				TLVLength: 3,
+				TLVValue:  []byte{1, 2, 3},
+			},
+			expected: []byte{
+				100, 3, 1, 2, 3,
+			},
+		},
+	}
+
+	for _, test := range tests {
+		buf := bytes.NewBuffer(nil)
+		test.input.Serialize(buf)
+		assert.Equalf(t, test.expected, buf.Bytes(), "Test %q", test.name)
+	}
+}