diff --git a/config/isis.go b/config/isis.go
index 0ec4c5f05f6fb0c3b9301c2b85fd7a6701f434c0..59b2e5f8d3f580a6ec11e3177ae8803131b0dfc0 100644
--- a/config/isis.go
+++ b/config/isis.go
@@ -1,16 +1,17 @@
 package config
 
 import (
-	"time"
 	"fmt"
+	"time"
 
 	"github.com/bio-routing/bio-rd/protocols/isis/types"
 )
 
 type ISISConfig struct {
-	NETs       []NET
-	Interfaces []ISISInterfaceConfig
+	NETs                       []NET
+	Interfaces                 []ISISInterfaceConfig
 	MinLSPTransmissionInterval time.Duration
+	TrafficEngineeringRouterID [4]byte
 }
 
 type ISISInterfaceConfig struct {
diff --git a/examples/isis/main.go b/examples/isis/main.go
index 1dcf63b003b09e41e703ff0f55501ffcac4072a3..2e5e7090bcbc8b3b8ea2af9dac127c66f7211c6d 100644
--- a/examples/isis/main.go
+++ b/examples/isis/main.go
@@ -33,8 +33,15 @@ func main() {
 					Priority:      0,
 				},
 			},
+			{
+				Name:             "lo",
+				Passive:          true,
+				P2P:              true,
+				ISISLevel2Config: &config.ISISLevelConfig{},
+			},
 		},
 		MinLSPTransmissionInterval: 100,
+		TrafficEngineeringRouterID: [4]byte{10, 20, 30, 40},
 	}
 
 	ds, err := device.New()
diff --git a/protocols/isis/packet/csnp.go b/protocols/isis/packet/csnp.go
index 76d982e6a863a80d877d7b62d026bbb3779bfe7c..7b6e649a51e19b34fbb32428d17fa14e694f189c 100644
--- a/protocols/isis/packet/csnp.go
+++ b/protocols/isis/packet/csnp.go
@@ -25,7 +25,6 @@ type CSNP struct {
 	StartLSPID LSPID
 	EndLSPID   LSPID
 	TLVs       []TLV
-	//LSPEntries []LSPEntry
 }
 
 func compareLSPIDs(lspIDA, lspIDB LSPID) bool {
@@ -89,7 +88,8 @@ func NewCSNPs(sourceID types.SourceID, lspEntries []*LSPEntry, maxPDULen int) []
 	res[0].StartLSPID = LSPID{}
 	res[len(res)-1].EndLSPID = LSPID{
 		SystemID:     types.SystemID{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-		PseudonodeID: 0xffff,
+		PseudonodeID: 0xff,
+		LSPNumber:    0xff,
 	}
 
 	return res
diff --git a/protocols/isis/packet/csnp_test.go b/protocols/isis/packet/csnp_test.go
index 653a0767e8b677d9fa3d1819198d070db9c285e4..0bf6aaca36526cb2c0fb72812c21a21a3b44001c 100644
--- a/protocols/isis/packet/csnp_test.go
+++ b/protocols/isis/packet/csnp_test.go
@@ -85,7 +85,8 @@ func TestNewCSNPs(t *testing.T) {
 					StartLSPID: LSPID{},
 					EndLSPID: LSPID{
 						SystemID:     types.SystemID{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-						PseudonodeID: 0xffff,
+						PseudonodeID: 0xff,
+						LSPNumber:    0xff,
 					},
 					TLVs: []TLV{
 						&LSPEntriesTLV{
@@ -176,7 +177,8 @@ func TestNewCSNPs(t *testing.T) {
 					},
 					EndLSPID: LSPID{
 						SystemID:     types.SystemID{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-						PseudonodeID: 0xffff,
+						PseudonodeID: 0xff,
+						LSPNumber:    0xff,
 					},
 					TLVs: []TLV{
 						&LSPEntriesTLV{
@@ -268,7 +270,8 @@ func TestNewCSNPs(t *testing.T) {
 					},
 					EndLSPID: LSPID{
 						SystemID:     types.SystemID{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-						PseudonodeID: 0xffff,
+						PseudonodeID: 0xff,
+						LSPNumber:    0xff,
 					},
 					TLVs: []TLV{
 						&LSPEntriesTLV{
@@ -313,12 +316,14 @@ func TestCSNPSerialize(t *testing.T) {
 					CircuitID: 0,
 				},
 				StartLSPID: LSPID{
-					SystemID:     types.SystemID{11, 22, 33, 44, 55, 66},
-					PseudonodeID: 256,
+					SystemID:     types.SystemID{0x11, 0x22, 0x33, 0x44, 0x55, 0x66},
+					PseudonodeID: 0,
+					LSPNumber:    0,
 				},
 				EndLSPID: LSPID{
-					SystemID:     types.SystemID{11, 22, 33, 44, 55, 67},
-					PseudonodeID: 255,
+					SystemID:     types.SystemID{0x11, 0x22, 0x33, 0x44, 0x55, 0x67},
+					PseudonodeID: 0xff,
+					LSPNumber:    0,
 				},
 				TLVs: []TLV{
 					&LSPEntriesTLV{
@@ -326,29 +331,30 @@ func TestCSNPSerialize(t *testing.T) {
 						TLVLength: 16,
 						LSPEntries: []*LSPEntry{
 							{
-								SequenceNumber:    123,
 								RemainingLifetime: 255,
-								LSPChecksum:       111,
 								LSPID: LSPID{
 									SystemID:     types.SystemID{10, 20, 30, 40, 50, 61},
 									PseudonodeID: 11,
+									LSPNumber:    0,
 								},
+								SequenceNumber: 123,
+								LSPChecksum:    111,
 							},
 						},
 					},
 				},
 			},
 			expected: []byte{
-				0, 43,
-				10, 20, 30, 40, 50, 60, 0,
-				11, 22, 33, 44, 55, 66, 1, 0,
-				11, 22, 33, 44, 55, 67, 0, 255,
-				9,
-				16,
-				0, 255,
-				10, 20, 30, 40, 50, 61, 0, 11,
-				0, 0, 0, 123,
-				0, 111,
+				0, 43, // Length
+				10, 20, 30, 40, 50, 60, 0, // SourceID
+				0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0, 0, // Start LDP ID
+				0x11, 0x22, 0x33, 0x44, 0x55, 0x67, 0xff, 0, // End LSP ID
+				9,      // TLV Type
+				16,     // TLV Length
+				0, 255, // Remaining Lifetime
+				10, 20, 30, 40, 50, 61, 11, 0, // LSP ID
+				0, 0, 0, 123, // Seq. Nr.
+				0, 111, // Checksum
 			},
 		},
 	}
diff --git a/protocols/isis/packet/hello.go b/protocols/isis/packet/hello.go
index 7e2680261b6edfc443a2558973dc31eea5df8259..31cccb420c28bb85505154647e67ad6d4106a311 100644
--- a/protocols/isis/packet/hello.go
+++ b/protocols/isis/packet/hello.go
@@ -75,6 +75,18 @@ func (h *P2PHello) GetP2PAdjTLV() *P2PAdjacencyStateTLV {
 	return nil
 }
 
+// GetIPInterfaceAddressesesTLV gets the IP Interface Addresses TLV
+func (h *P2PHello) GetIPInterfaceAddressesesTLV() *IPInterfaceAddressesTLV {
+	for _, tlv := range h.TLVs {
+		if tlv.Type() != IPInterfaceAddressesTLVType {
+			continue
+		}
+
+		return tlv.(*IPInterfaceAddressesTLV)
+	}
+	return nil
+}
+
 // Serialize serializes a P2P Hello
 func (h *P2PHello) Serialize(buf *bytes.Buffer) {
 	buf.WriteByte(h.CircuitType)
diff --git a/protocols/isis/packet/hello_test.go b/protocols/isis/packet/hello_test.go
index cb0f7840e948f38766ec9d630500d193ff2a65f4..b921f96b9945a4b9afe590051bf545dfcf3491bc 100644
--- a/protocols/isis/packet/hello_test.go
+++ b/protocols/isis/packet/hello_test.go
@@ -8,6 +8,40 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
+func TestGetIPInterfaceAddressesesTLV(t *testing.T) {
+	tests := []struct {
+		name     string
+		hello    *P2PHello
+		expected *IPInterfaceAddressesTLV
+	}{
+		{
+			name: "Test #1",
+			hello: &P2PHello{
+				TLVs: []TLV{
+					NewIPInterfaceAddressesTLV([]uint32{111}),
+				},
+			},
+			expected: &IPInterfaceAddressesTLV{
+				TLVType:       IPInterfaceAddressesTLVType,
+				TLVLength:     4,
+				IPv4Addresses: []uint32{111},
+			},
+		},
+		{
+			name: "Test #1",
+			hello: &P2PHello{
+				TLVs: []TLV{},
+			},
+			expected: nil,
+		},
+	}
+
+	for _, test := range tests {
+		ret := test.hello.GetIPInterfaceAddressesesTLV()
+		assert.Equalf(t, test.expected, ret, "Test %q", test.name)
+	}
+}
+
 func TestGetP2PAdjTLV(t *testing.T) {
 	tests := []struct {
 		name     string
@@ -274,10 +308,10 @@ func TestDecodeISISHello(t *testing.T) {
 						TLVLength:               2,
 						NetworkLayerProtocolIDs: []byte{0xcc, 0x8e},
 					},
-					&IPInterfaceAddressTLV{
-						TLVType:     132,
-						TLVLength:   4,
-						IPv4Address: 167772160,
+					&IPInterfaceAddressesTLV{
+						TLVType:       132,
+						TLVLength:     4,
+						IPv4Addresses: []uint32{167772160},
 					},
 					&AreaAddressesTLV{
 						TLVType:   1,
diff --git a/protocols/isis/packet/isis_test.go b/protocols/isis/packet/isis_test.go
index 4da6163a2ab758d49d5986e583caceef8ddd57ea..31f8038a5a63f63664df2e9ff93db8f04bd26fba 100644
--- a/protocols/isis/packet/isis_test.go
+++ b/protocols/isis/packet/isis_test.go
@@ -76,10 +76,10 @@ func TestDecode(t *testing.T) {
 							TLVLength:               2,
 							NetworkLayerProtocolIDs: []uint8{0xcc, 0x8e},
 						},
-						&IPInterfaceAddressTLV{
-							TLVType:     132,
-							TLVLength:   4,
-							IPv4Address: 3232235776,
+						&IPInterfaceAddressesTLV{
+							TLVType:       132,
+							TLVLength:     4,
+							IPv4Addresses: []uint32{3232235776},
 						},
 						&AreaAddressesTLV{
 							TLVType:   1,
diff --git a/protocols/isis/packet/lsp.go b/protocols/isis/packet/lsp.go
index 24717949eb10ed5500ecaf46fe106cdeed2b240e..dc42e2281efc3e3e41b8aa6ff108d552cac72b89 100644
--- a/protocols/isis/packet/lsp.go
+++ b/protocols/isis/packet/lsp.go
@@ -19,7 +19,8 @@ const (
 // LSPID represents a Link State Packet ID
 type LSPID struct {
 	SystemID     types.SystemID
-	PseudonodeID uint16
+	PseudonodeID uint8
+	LSPNumber    uint8
 }
 
 func (l *LSPID) String() string {
@@ -29,7 +30,8 @@ func (l *LSPID) String() string {
 // Serialize serializes an LSPID
 func (l *LSPID) Serialize(buf *bytes.Buffer) {
 	buf.Write(l.SystemID[:])
-	buf.Write(convert.Uint16Byte(l.PseudonodeID))
+	buf.WriteByte(l.PseudonodeID)
+	buf.WriteByte(l.LSPNumber)
 }
 
 // Compare returns 1 if l is bigger m, 0 if they are equal, else -1
diff --git a/protocols/isis/packet/lsp_entry.go b/protocols/isis/packet/lsp_entry.go
index c8d8cd5626898fcba7ddcd9f6c8208e5792b1b52..8c1d259e1de3808b89973c6f24629c549ef0efbf 100644
--- a/protocols/isis/packet/lsp_entry.go
+++ b/protocols/isis/packet/lsp_entry.go
@@ -15,10 +15,10 @@ const (
 
 // LSPEntry represents an LSP entry in a CSNP PDU
 type LSPEntry struct {
-	SequenceNumber    uint32
 	RemainingLifetime uint16
-	LSPChecksum       uint16
 	LSPID             LSPID
+	SequenceNumber    uint32
+	LSPChecksum       uint16
 }
 
 // Serialize serializes an LSPEntry
diff --git a/protocols/isis/packet/lsp_test.go b/protocols/isis/packet/lsp_test.go
index f8979b7ef6159c28f55f052a5dad485cea6403d0..878ca80054e6bda55a02dd2e21c203d452daddcb 100644
--- a/protocols/isis/packet/lsp_test.go
+++ b/protocols/isis/packet/lsp_test.go
@@ -266,6 +266,7 @@ func TestSetChecksum(t *testing.T) {
 				LSPID: LSPID{
 					SystemID:     types.SystemID{10, 20, 30, 40, 50, 60},
 					PseudonodeID: 0,
+					LSPNumber:    0,
 				},
 				SequenceNumber: 1,
 				TypeBlock:      3,
diff --git a/protocols/isis/packet/tlv.go b/protocols/isis/packet/tlv.go
index 3d5b6c88b2d01aeae6707352331e62cc97587e44..3dc3ece2175a29d9828775947889cf860143f2ae 100644
--- a/protocols/isis/packet/tlv.go
+++ b/protocols/isis/packet/tlv.go
@@ -56,8 +56,8 @@ func readTLVs(buf *bytes.Buffer) ([]TLV, error) {
 			tlv, err = readChecksumTLV(buf, tlvType, tlvLength)
 		case ProtocolsSupportedTLVType:
 			tlv, err = readProtocolsSupportedTLV(buf, tlvType, tlvLength)
-		case IPInterfaceAddressTLVType:
-			tlv, err = readIPInterfaceAddressTLV(buf, tlvType, tlvLength)
+		case IPInterfaceAddressesTLVType:
+			tlv, err = readIPInterfaceAddressesTLV(buf, tlvType, tlvLength)
 		case AreaAddressesTLVType:
 			tlv, err = readAreaAddressesTLV(buf, tlvType, tlvLength)
 		case P2PAdjacencyStateTLVType:
diff --git a/protocols/isis/packet/tlv_dynamic_hostname.go b/protocols/isis/packet/tlv_dynamic_hostname.go
index 2b5114e948aef784d74bdf51642619d582722433..1a2b74977718b3e9c99fc0bd6677956897b89bd6 100644
--- a/protocols/isis/packet/tlv_dynamic_hostname.go
+++ b/protocols/isis/packet/tlv_dynamic_hostname.go
@@ -32,6 +32,15 @@ func (d *DynamicHostNameTLV) Value() interface{} {
 	return d
 }
 
+// NewDynamicHostnameTLV creates a new dynamic hostname TLV
+func NewDynamicHostnameTLV(name []byte) *DynamicHostNameTLV {
+	return &DynamicHostNameTLV{
+		TLVType:   DynamicHostNameTLVType,
+		TLVLength: uint8(len(name)),
+		Hostname:  name,
+	}
+}
+
 func readDynamicHostnameTLV(buf *bytes.Buffer, tlvType uint8, tlvLength uint8) (*DynamicHostNameTLV, error) {
 	pdu := &DynamicHostNameTLV{
 		TLVType:   tlvType,
diff --git a/protocols/isis/packet/tlv_extended_is_reachability.go b/protocols/isis/packet/tlv_extended_is_reachability.go
index 20e77188a21fcee35f72427629ac78d4f27e42f5..20aa2d7ee8ace8485bbb00d29154d0044fa87192 100644
--- a/protocols/isis/packet/tlv_extended_is_reachability.go
+++ b/protocols/isis/packet/tlv_extended_is_reachability.go
@@ -1,12 +1,185 @@
 package packet
 
-const ExtendedISReachabilityType = 22
+import (
+	"bytes"
 
+	"github.com/bio-routing/bio-rd/protocols/isis/types"
+	"github.com/taktv6/tflow2/convert"
+)
+
+const (
+	// ExtendedISReachabilityType is the type value of an Extended IS Reachability TLV
+	ExtendedISReachabilityType = 22
+
+	// LinkLocalRemoteIdentifiersSubTLVType is the type value of an Link Local/Remote Indentifiers Sub TLV
+	LinkLocalRemoteIdentifiersSubTLVType = 4
+
+	// IPv4InterfaceAddressSubTLVType is the type value of an IPv4 interface address sub TLV
+	IPv4InterfaceAddressSubTLVType = 6
+
+	// IPv4NeighborAddressSubTLVType is the type value of an IPv4 neighbor address sub TLV
+	IPv4NeighborAddressSubTLVType = 8
+)
+
+// ExtendedISReachabilityTLV is an Extended IS Reachability TLV
 type ExtendedISReachabilityTLV struct {
-	TLVType      uint8
-	TLVLength    uint8
-	SystemID     [7]byte
-	WideMetrics  [3]byte
+	TLVType   uint8
+	TLVLength uint8
+	Neighbors []*ExtendedISReachabilityNeighbor
+}
+
+// Type gets the type of the TLV
+func (e *ExtendedISReachabilityTLV) Type() uint8 {
+	return e.TLVType
+}
+
+// Length gets the length of the TLV
+func (e *ExtendedISReachabilityTLV) Length() uint8 {
+	return e.TLVLength
+}
+
+// Value returns the TLV itself
+func (e *ExtendedISReachabilityTLV) Value() interface{} {
+	return e
+}
+
+// Serialize serializes an ExtendedISReachabilityTLV
+func (e *ExtendedISReachabilityTLV) Serialize(buf *bytes.Buffer) {
+	buf.WriteByte(e.TLVType)
+	buf.WriteByte(e.TLVLength)
+	for i := range e.Neighbors {
+		e.Neighbors[i].Serialize(buf)
+	}
+}
+
+// ExtendedISReachabilityNeighbor is an extended IS Reachability Neighbor
+type ExtendedISReachabilityNeighbor struct {
+	NeighborID   types.SourceID
+	Metric       [3]byte
 	SubTLVLength uint8
-	SubTLVs      []interface{}
+	SubTLVs      []TLV
+}
+
+// Serialize serializes an ExtendedISReachabilityNeighbor
+func (e *ExtendedISReachabilityNeighbor) Serialize(buf *bytes.Buffer) {
+	buf.Write(e.NeighborID.Serialize())
+	buf.Write(e.Metric[:])
+	buf.WriteByte(e.SubTLVLength)
+	for i := range e.SubTLVs {
+		e.SubTLVs[i].Serialize(buf)
+	}
+}
+
+// NewExtendedISReachabilityNeighbor creates a new ExtendedISReachabilityNeighbor
+func NewExtendedISReachabilityNeighbor(neighborID types.SourceID, metric [3]byte) *ExtendedISReachabilityNeighbor {
+	return &ExtendedISReachabilityNeighbor{
+		NeighborID: neighborID,
+		Metric:     metric,
+		SubTLVs:    make([]TLV, 0),
+	}
+}
+
+// NewExtendedISReachabilityTLV creates a new Extended IS Reachability TLV
+func NewExtendedISReachabilityTLV() *ExtendedISReachabilityTLV {
+	e := &ExtendedISReachabilityTLV{
+		TLVType: ExtendedISReachabilityType,
+	}
+
+	return e
+}
+
+// AddSubTLV adds a sub TLV to the ExtendedISReachabilityNeighbor
+func (e *ExtendedISReachabilityNeighbor) AddSubTLV(tlv TLV) {
+	e.SubTLVLength += tlv.Length() + 2
+	e.SubTLVs = append(e.SubTLVs, tlv)
+}
+
+// LinkLocalRemoteIdentifiersSubTLV is an Link Local/Remote Identifiers Sub TLV
+type LinkLocalRemoteIdentifiersSubTLV struct {
+	TLVType   uint8
+	TLVLength uint8
+	Local     uint32
+	Remote    uint32
+}
+
+// Type gets the type of the TLV
+func (l *LinkLocalRemoteIdentifiersSubTLV) Type() uint8 {
+	return l.TLVType
+}
+
+// Length gets the length of the TLV
+func (l *LinkLocalRemoteIdentifiersSubTLV) Length() uint8 {
+	return l.TLVLength
+}
+
+// Value returns the TLV itself
+func (l *LinkLocalRemoteIdentifiersSubTLV) Value() interface{} {
+	return l
+}
+
+// Serialize serializes an IPv4 address sub TLV
+func (l *LinkLocalRemoteIdentifiersSubTLV) Serialize(buf *bytes.Buffer) {
+	buf.WriteByte(l.TLVType)
+	buf.WriteByte(l.TLVLength)
+	buf.Write(convert.Uint32Byte(l.Local))
+	buf.Write(convert.Uint32Byte(l.Remote))
+}
+
+// NewLinkLocalRemoteIdentifiersSubTLV creates a new LinkLocalRemoteIdentifiersSubTLV
+func NewLinkLocalRemoteIdentifiersSubTLV(local uint32, remote uint32) *LinkLocalRemoteIdentifiersSubTLV {
+	return &LinkLocalRemoteIdentifiersSubTLV{
+		TLVType:   LinkLocalRemoteIdentifiersSubTLVType,
+		TLVLength: 8,
+		Local:     local,
+		Remote:    remote,
+	}
+}
+
+// IPv4AddressSubTLV is an IPv4 Address Sub TLV (used for both interface and neighbor)
+type IPv4AddressSubTLV struct {
+	TLVType   uint8
+	TLVLength uint8
+	Address   uint32
+}
+
+// Type gets the type of the TLV
+func (s *IPv4AddressSubTLV) Type() uint8 {
+	return s.TLVType
+}
+
+// Length gets the length of the TLV
+func (s *IPv4AddressSubTLV) Length() uint8 {
+	return s.TLVLength
+}
+
+// Value returns the TLV itself
+func (s *IPv4AddressSubTLV) Value() interface{} {
+	return s
+}
+
+// Serialize serializes an IPv4 address sub TLV
+func (s *IPv4AddressSubTLV) Serialize(buf *bytes.Buffer) {
+	buf.WriteByte(s.TLVType)
+	buf.WriteByte(s.TLVLength)
+	buf.Write(convert.Uint32Byte(s.Address))
+}
+
+// NewIPv4InterfaceAddressSubTLV creates a new IPv4 Interface Address Sub TLV
+func NewIPv4InterfaceAddressSubTLV(addr uint32) *IPv4AddressSubTLV {
+	return newIPv4AddressSubTLV(IPv4InterfaceAddressSubTLVType, addr)
+}
+
+// NewIPv4NeighborAddressSubTLV creates a new IPv4 Neighbor Address Sub TLV
+func NewIPv4NeighborAddressSubTLV(addr uint32) *IPv4AddressSubTLV {
+	return newIPv4AddressSubTLV(IPv4NeighborAddressSubTLVType, addr)
+}
+
+func newIPv4AddressSubTLV(tlvType uint8, addr uint32) *IPv4AddressSubTLV {
+	tlv := &IPv4AddressSubTLV{
+		TLVType:   tlvType,
+		TLVLength: 4,
+		Address:   addr,
+	}
+
+	return tlv
 }
diff --git a/protocols/isis/packet/tlv_extended_is_reachability_test.go b/protocols/isis/packet/tlv_extended_is_reachability_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..bea8f12c77ae5ac58f48aeb17eb4fcf8306513e4
--- /dev/null
+++ b/protocols/isis/packet/tlv_extended_is_reachability_test.go
@@ -0,0 +1,101 @@
+package packet
+
+import (
+	"bytes"
+	"testing"
+
+	"github.com/bio-routing/bio-rd/protocols/isis/types"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestExtendedISReachabilityTLVSerialize(t *testing.T) {
+
+}
+
+func TestExtendedISReachabilityNeighborAddSubTLV(t *testing.T) {
+	tests := []struct {
+		name     string
+		neighbor *ExtendedISReachabilityNeighbor
+		addTLV   TLV
+		expected *ExtendedISReachabilityNeighbor
+	}{
+		{
+			name: "Test #1",
+			neighbor: NewExtendedISReachabilityNeighbor(types.NewSourceID(
+				types.SystemID{1, 2, 3, 4, 5, 6},
+				0,
+			), [3]byte{1, 2, 3}),
+			addTLV: &IPv4AddressSubTLV{
+				TLVType:   6,
+				TLVLength: 4,
+				Address:   111,
+			},
+			expected: &ExtendedISReachabilityNeighbor{
+				NeighborID: types.NewSourceID(
+					types.SystemID{1, 2, 3, 4, 5, 6},
+					0,
+				),
+				Metric:       [3]byte{1, 2, 3},
+				SubTLVLength: 6,
+				SubTLVs: []TLV{
+					&IPv4AddressSubTLV{
+						TLVType:   6,
+						TLVLength: 4,
+						Address:   111,
+					},
+				},
+			},
+		},
+	}
+
+	for _, test := range tests {
+		test.neighbor.AddSubTLV(test.addTLV)
+		assert.Equal(t, test.expected, test.neighbor, test.name)
+	}
+}
+
+func TestIPv4AddressSubTLVSerialize(t *testing.T) {
+	tests := []struct {
+		name     string
+		tlv      *IPv4AddressSubTLV
+		expected []byte
+	}{
+		{
+			name: "Test #1",
+			tlv: &IPv4AddressSubTLV{
+				TLVType:   IPv4InterfaceAddressSubTLVType,
+				TLVLength: 4,
+				Address:   111,
+			},
+			expected: []byte{6, 4, 0, 0, 0, 111},
+		},
+	}
+
+	for _, test := range tests {
+		buf := bytes.NewBuffer(nil)
+		test.tlv.Serialize(buf)
+		assert.Equal(t, test.expected, buf.Bytes(), test.name)
+	}
+}
+
+func TestNewIPv4InterfaceAddressSubTLV(t *testing.T) {
+	tlv := NewIPv4InterfaceAddressSubTLV(111)
+	expectred := &IPv4AddressSubTLV{
+		TLVType:   6,
+		TLVLength: 4,
+		Address:   111,
+	}
+
+	assert.Equal(t, expectred, tlv)
+}
+
+func TestNewIPv4NeighborAddressSubTLV(t *testing.T) {
+	tlv := NewIPv4NeighborAddressSubTLV(111)
+	expectred := &IPv4AddressSubTLV{
+		TLVType:   8,
+		TLVLength: 4,
+		Address:   111,
+	}
+
+	assert.Equal(t, expectred, tlv)
+}
diff --git a/protocols/isis/packet/tlv_ip_interface_address.go b/protocols/isis/packet/tlv_ip_interface_address.go
deleted file mode 100644
index 012688a8b9e049513fa4398e1897b288a22fc5b4..0000000000000000000000000000000000000000
--- a/protocols/isis/packet/tlv_ip_interface_address.go
+++ /dev/null
@@ -1,68 +0,0 @@
-package packet
-
-import (
-	"bytes"
-	"fmt"
-
-	"github.com/bio-routing/bio-rd/util/decode"
-	"github.com/taktv6/tflow2/convert"
-)
-
-// IPInterfaceAddressTLVType is the type value of an IP interface address TLV
-const IPInterfaceAddressTLVType = 132
-
-// IPInterfaceAddressTLV represents an IP interface TLV
-type IPInterfaceAddressTLV struct {
-	TLVType     uint8
-	TLVLength   uint8
-	IPv4Address uint32
-}
-
-// NewIPInterfaceAddressTLV creates a new IPInterfaceAddressTLV
-func NewIPInterfaceAddressTLV(addr uint32) *IPInterfaceAddressTLV {
-	return &IPInterfaceAddressTLV{
-		TLVType:     IPInterfaceAddressTLVType,
-		TLVLength:   4,
-		IPv4Address: addr,
-	}
-}
-
-func readIPInterfaceAddressTLV(buf *bytes.Buffer, tlvType uint8, tlvLength uint8) (*IPInterfaceAddressTLV, error) {
-	pdu := &IPInterfaceAddressTLV{
-		TLVType:   tlvType,
-		TLVLength: tlvLength,
-	}
-
-	fields := []interface{}{
-		&pdu.IPv4Address,
-	}
-
-	err := decode.Decode(buf, fields)
-	if err != nil {
-		return nil, fmt.Errorf("Unable to decode fields: %v", err)
-	}
-
-	return pdu, nil
-}
-
-// Type returns the type of the TLV
-func (i IPInterfaceAddressTLV) Type() uint8 {
-	return i.TLVType
-}
-
-// Length returns the length of the TLV
-func (i IPInterfaceAddressTLV) Length() uint8 {
-	return i.TLVLength
-}
-
-// Value gets the TLV itself
-func (i IPInterfaceAddressTLV) Value() interface{} {
-	return i
-}
-
-// Serialize serializes an IP interfaces address TLV
-func (i IPInterfaceAddressTLV) Serialize(buf *bytes.Buffer) {
-	buf.WriteByte(i.TLVType)
-	buf.WriteByte(i.TLVLength)
-	buf.Write(convert.Uint32Byte(i.IPv4Address))
-}
diff --git a/protocols/isis/packet/tlv_ip_interface_addresses.go b/protocols/isis/packet/tlv_ip_interface_addresses.go
new file mode 100644
index 0000000000000000000000000000000000000000..b68ba48766410c1663ab0662880898a34b98f4e2
--- /dev/null
+++ b/protocols/isis/packet/tlv_ip_interface_addresses.go
@@ -0,0 +1,72 @@
+package packet
+
+import (
+	"bytes"
+	"fmt"
+
+	"github.com/bio-routing/bio-rd/util/decode"
+	"github.com/taktv6/tflow2/convert"
+)
+
+// IPInterfaceAddressesTLVType is the type value of an IP interface address TLV
+const IPInterfaceAddressesTLVType = 132
+
+// IPInterfaceAddressesTLV represents an IP interface TLV
+type IPInterfaceAddressesTLV struct {
+	TLVType       uint8
+	TLVLength     uint8
+	IPv4Addresses []uint32
+}
+
+// NewIPInterfaceAddressesTLV creates a new IPInterfaceAddressesTLV
+func NewIPInterfaceAddressesTLV(addrs []uint32) *IPInterfaceAddressesTLV {
+	return &IPInterfaceAddressesTLV{
+		TLVType:       IPInterfaceAddressesTLVType,
+		TLVLength:     4,
+		IPv4Addresses: addrs,
+	}
+}
+
+func readIPInterfaceAddressesTLV(buf *bytes.Buffer, tlvType uint8, tlvLength uint8) (*IPInterfaceAddressesTLV, error) {
+	pdu := &IPInterfaceAddressesTLV{
+		TLVType:       tlvType,
+		TLVLength:     tlvLength,
+		IPv4Addresses: make([]uint32, tlvLength/4),
+	}
+
+	fields := make([]interface{}, len(pdu.IPv4Addresses))
+	for i := range pdu.IPv4Addresses {
+		fields[i] = &pdu.IPv4Addresses[i]
+	}
+
+	err := decode.Decode(buf, fields)
+	if err != nil {
+		return nil, fmt.Errorf("Unable to decode fields: %v", err)
+	}
+
+	return pdu, nil
+}
+
+// Type returns the type of the TLV
+func (i IPInterfaceAddressesTLV) Type() uint8 {
+	return i.TLVType
+}
+
+// Length returns the length of the TLV
+func (i IPInterfaceAddressesTLV) Length() uint8 {
+	return i.TLVLength
+}
+
+// Value gets the TLV itself
+func (i IPInterfaceAddressesTLV) Value() interface{} {
+	return i
+}
+
+// Serialize serializes an IP interfaces address TLV
+func (i IPInterfaceAddressesTLV) Serialize(buf *bytes.Buffer) {
+	buf.WriteByte(i.TLVType)
+	buf.WriteByte(i.TLVLength)
+	for j := range i.IPv4Addresses {
+		buf.Write(convert.Uint32Byte(i.IPv4Addresses[j]))
+	}
+}
diff --git a/protocols/isis/packet/tlv_ip_interface_address_test.go b/protocols/isis/packet/tlv_ip_interface_addresses_test.go
similarity index 67%
rename from protocols/isis/packet/tlv_ip_interface_address_test.go
rename to protocols/isis/packet/tlv_ip_interface_addresses_test.go
index 432437ce0b943adec0947b3d247afdad411d15d2..b9e51e3d7f6366bd472cf65f7cff8fd8695f730c 100644
--- a/protocols/isis/packet/tlv_ip_interface_address_test.go
+++ b/protocols/isis/packet/tlv_ip_interface_addresses_test.go
@@ -10,22 +10,22 @@ import (
 func TestNewIPInterfaceAddressTLV(t *testing.T) {
 	tests := []struct {
 		name     string
-		addr     uint32
-		expected *IPInterfaceAddressTLV
+		addrs    []uint32
+		expected *IPInterfaceAddressesTLV
 	}{
 		{
-			name: "Test #1",
-			addr: 100,
-			expected: &IPInterfaceAddressTLV{
-				TLVType:     132,
-				TLVLength:   4,
-				IPv4Address: 100,
+			name:  "Test #1",
+			addrs: []uint32{100},
+			expected: &IPInterfaceAddressesTLV{
+				TLVType:       132,
+				TLVLength:     4,
+				IPv4Addresses: []uint32{100},
 			},
 		},
 	}
 
 	for _, test := range tests {
-		tlv := NewIPInterfaceAddressTLV(test.addr)
+		tlv := NewIPInterfaceAddressesTLV(test.addrs)
 		assert.Equalf(t, test.expected, tlv, "Test %q", test.name)
 	}
 }
@@ -36,7 +36,7 @@ func TestReadIPInterfaceAddressTLV(t *testing.T) {
 		input     []byte
 		tlvLength uint8
 		wantFail  bool
-		expected  *IPInterfaceAddressTLV
+		expected  *IPInterfaceAddressesTLV
 	}{
 		{
 			name: "Full",
@@ -44,10 +44,10 @@ func TestReadIPInterfaceAddressTLV(t *testing.T) {
 				0, 0, 0, 100,
 			},
 			tlvLength: 4,
-			expected: &IPInterfaceAddressTLV{
-				TLVType:     132,
-				TLVLength:   4,
-				IPv4Address: 100,
+			expected: &IPInterfaceAddressesTLV{
+				TLVType:       132,
+				TLVLength:     4,
+				IPv4Addresses: []uint32{100},
 			},
 		},
 		{
@@ -62,7 +62,7 @@ func TestReadIPInterfaceAddressTLV(t *testing.T) {
 
 	for _, test := range tests {
 		buf := bytes.NewBuffer(test.input)
-		tlv, err := readIPInterfaceAddressTLV(buf, 132, test.tlvLength)
+		tlv, err := readIPInterfaceAddressesTLV(buf, 132, test.tlvLength)
 
 		if err != nil {
 			if test.wantFail {
diff --git a/protocols/isis/packet/tlv_traffic_engineering_router_id.go b/protocols/isis/packet/tlv_traffic_engineering_router_id.go
new file mode 100644
index 0000000000000000000000000000000000000000..0720607b586fe9b22a70990c1d945b571971ae3f
--- /dev/null
+++ b/protocols/isis/packet/tlv_traffic_engineering_router_id.go
@@ -0,0 +1,69 @@
+package packet
+
+import (
+	"bytes"
+	"fmt"
+
+	"github.com/bio-routing/bio-rd/util/decode"
+)
+
+const (
+	// TrafficEngineeringRouterIDTLVType is the type value of an Traffic Engineering Router ID TLV
+	TrafficEngineeringRouterIDTLVType = 134
+)
+
+// TrafficEngineeringRouterIDTLV is a Traffic Engineering Router ID TLV
+type TrafficEngineeringRouterIDTLV struct {
+	TLVType   uint8
+	TLVLength uint8
+	Address   [4]byte
+}
+
+// NewTrafficEngineeringRouterIDTLV creates a new TrafficEngineeringRouterIDTLV
+func NewTrafficEngineeringRouterIDTLV(addr [4]byte) *TrafficEngineeringRouterIDTLV {
+	return &TrafficEngineeringRouterIDTLV{
+		TLVType:   TrafficEngineeringRouterIDTLVType,
+		TLVLength: 4,
+		Address:   addr,
+	}
+}
+
+// Serialize serializes a TrafficEngineeringRouterIDTLV
+func (t *TrafficEngineeringRouterIDTLV) Serialize(buf *bytes.Buffer) {
+	buf.WriteByte(t.TLVType)
+	buf.WriteByte(t.TLVLength)
+	buf.Write(t.Address[:])
+}
+
+func readTrafficEngineeringRouterIDTLV(buf *bytes.Buffer, tlvType uint8, tlvLength uint8) (*TrafficEngineeringRouterIDTLV, error) {
+	pdu := &TrafficEngineeringRouterIDTLV{
+		TLVType:   tlvType,
+		TLVLength: tlvLength,
+	}
+
+	fields := []interface{}{
+		pdu.Address[:],
+	}
+
+	err := decode.Decode(buf, fields)
+	if err != nil {
+		return nil, fmt.Errorf("Unable to decode fields: %v", err)
+	}
+
+	return pdu, nil
+}
+
+// Type gets the type of the TLV
+func (t TrafficEngineeringRouterIDTLV) Type() uint8 {
+	return t.TLVType
+}
+
+// Length gets the length of the TLV
+func (t TrafficEngineeringRouterIDTLV) Length() uint8 {
+	return t.TLVLength
+}
+
+// Value gets the TLV itself
+func (t TrafficEngineeringRouterIDTLV) Value() interface{} {
+	return t
+}
diff --git a/protocols/isis/packet/tlv_traffic_engineering_router_id_test.go b/protocols/isis/packet/tlv_traffic_engineering_router_id_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..51875f6a4f146fd7d637505d295386b6f020612b
--- /dev/null
+++ b/protocols/isis/packet/tlv_traffic_engineering_router_id_test.go
@@ -0,0 +1,100 @@
+package packet
+
+import (
+	"bytes"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestNewTrafficEngineeringRouterIDTLV(t *testing.T) {
+	tests := []struct {
+		name     string
+		addr     [4]byte
+		expected *TrafficEngineeringRouterIDTLV
+	}{
+		{
+			name: "Test #1",
+			addr: [4]byte{10, 20, 30, 40},
+			expected: &TrafficEngineeringRouterIDTLV{
+				TLVType:   134,
+				TLVLength: 4,
+				Address:   [4]byte{10, 20, 30, 40},
+			},
+		},
+	}
+
+	for _, test := range tests {
+		tlv := NewTrafficEngineeringRouterIDTLV(test.addr)
+		assert.Equal(t, test.expected, tlv, test.name)
+	}
+}
+
+func TestTrafficEngineeringRouterIDTLVSerialize(t *testing.T) {
+	tests := []struct {
+		name     string
+		tlv      *TrafficEngineeringRouterIDTLV
+		expected []byte
+	}{
+		{
+			name: "Test #1",
+			tlv: &TrafficEngineeringRouterIDTLV{
+				TLVType:   134,
+				TLVLength: 4,
+				Address:   [4]byte{10, 0, 0, 123},
+			},
+			expected: []byte{134, 4, 10, 0, 0, 123},
+		},
+	}
+
+	for _, test := range tests {
+		buf := bytes.NewBuffer(nil)
+		test.tlv.Serialize(buf)
+		assert.Equal(t, test.expected, buf.Bytes(), test.name)
+	}
+}
+
+func TestReadTrafficEngineeringRouterIDTLV(t *testing.T) {
+	tests := []struct {
+		name      string
+		tlvType   uint8
+		tlvLength uint8
+		pkt       []byte
+		expected  *TrafficEngineeringRouterIDTLV
+		wantFail  bool
+	}{
+		{
+			name:      "Normal packet",
+			tlvType:   134,
+			tlvLength: 4,
+			pkt: []byte{
+				1, 2, 3, 4,
+			},
+			expected: &TrafficEngineeringRouterIDTLV{
+				TLVType:   134,
+				TLVLength: 4,
+				Address:   [4]byte{1, 2, 3, 4},
+			},
+		},
+	}
+
+	for _, test := range tests {
+		buf := bytes.NewBuffer(test.pkt)
+		tlv, err := readTrafficEngineeringRouterIDTLV(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.Equal(t, test.expected, tlv, test.name)
+	}
+}
diff --git a/protocols/isis/packet/tlv_unknown.go b/protocols/isis/packet/tlv_unknown.go
index 9488ac1ff700e6e15ee8c06256b4b16af206f2a9..13a469d63ba311b5bd5c2f87398a442ca52fdd2d 100644
--- a/protocols/isis/packet/tlv_unknown.go
+++ b/protocols/isis/packet/tlv_unknown.go
@@ -25,7 +25,7 @@ func readUnknownTLV(buf *bytes.Buffer, tlvType uint8, tlvLength uint8) (*Unknown
 	}
 
 	if n != int(tlvLength) {
-		return nil, fmt.Errorf("Read incomplete")
+		return nil, fmt.Errorf("Read of TLVType %d incomplete", pdu.TLVType)
 	}
 
 	return pdu, nil
diff --git a/protocols/isis/server/interface.go b/protocols/isis/server/interface.go
index 97064fe2db801813a588f07e1361c7da31c5b4af..5049a44415422219fd81f884cd5080ea40c5fc23 100644
--- a/protocols/isis/server/interface.go
+++ b/protocols/isis/server/interface.go
@@ -7,6 +7,7 @@ import (
 	"time"
 
 	"github.com/bio-routing/bio-rd/protocols/device"
+	"github.com/bio-routing/tflow2/convert"
 
 	"github.com/bio-routing/bio-rd/config"
 	"github.com/bio-routing/bio-rd/protocols/isis/packet"
@@ -51,6 +52,11 @@ type level struct {
 	neighborsMu   sync.RWMutex
 }
 
+func (l *level) get3ByteMetric() [3]byte {
+	bytes := convert.Uint32Byte(l.Metric)
+	return [3]byte{bytes[1], bytes[2], bytes[3]}
+}
+
 func (ifa *netIf) DeviceUpdate(d *device.Device) {
 	fmt.Printf("ISIS: DeviceUpdate() called\n")
 	ifa.deviceMu.Lock()
@@ -229,6 +235,13 @@ func (ifa *netIf) processIngressP2PHello(pkt *packet.ISISPacket, src types.MACAd
 		if _, ok := ifa.l2.neighbors[src]; !ok {
 			p2pAdjTLV := hello.GetP2PAdjTLV()
 			if p2pAdjTLV == nil {
+				log.Warningf("Received a P2P hello PDU without P2P Adjacency TLV on %s", ifa.name)
+				return
+			}
+
+			ipIfAddrTLV := hello.GetIPInterfaceAddressesesTLV()
+			if ipIfAddrTLV == nil {
+				log.Warningf("Received a P2P hello PDU without IP Interface Addresses TLV on %s", ifa.name)
 				return
 			}
 
@@ -238,6 +251,7 @@ func (ifa *netIf) processIngressP2PHello(pkt *packet.ISISPacket, src types.MACAd
 				holdingTime:            hello.HoldingTimer,
 				localCircuitID:         hello.LocalCircuitID,
 				extendedLocalCircuitID: p2pAdjTLV.ExtendedLocalCircuitID,
+				ipInterfaceAddresses:   ipIfAddrTLV.IPv4Addresses,
 			}
 			fmt.Printf("DEBUG: extendedLocalCircuitID: %v\n", p2pAdjTLV.ExtendedLocalCircuitID)
 
@@ -340,7 +354,7 @@ func (ifa *netIf) p2pHelloTLVs() []packet.TLV {
 	protocolsSupportedTLV := packet.NewProtocolsSupportedTLV(ifa.supportedProtocols)
 	areaAddressesTLV := packet.NewAreaAddressesTLV(ifa.isisServer.getAreas())
 
-	ipInterfaceAddressesTLV := packet.NewIPInterfaceAddressTLV(3232235523) //FIXME: Insert address automatically
+	ipInterfaceAddressesTLV := packet.NewIPInterfaceAddressesTLV([]uint32{3232235523}) //FIXME: Insert address automatically
 
 	return []packet.TLV{
 		p2pAdjStateTLV,
diff --git a/protocols/isis/server/interface_test.go b/protocols/isis/server/interface_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..a573c91d97020a1f37f28a2539c1f19ce0bc9a8b
--- /dev/null
+++ b/protocols/isis/server/interface_test.go
@@ -0,0 +1,35 @@
+package server
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestGet3ByteMetric(t *testing.T) {
+	tests := []struct {
+		name     string
+		level    *level
+		expected [3]byte
+	}{
+		{
+			name: "Test #1",
+			level: &level{
+				Metric: 512,
+			},
+			expected: [3]byte{0, 2, 0},
+		},
+		{
+			name: "Test #2",
+			level: &level{
+				Metric: 513,
+			},
+			expected: [3]byte{0, 2, 1},
+		},
+	}
+
+	for _, test := range tests {
+		res := test.level.get3ByteMetric()
+		assert.Equal(t, test.expected, res, test.name)
+	}
+}
diff --git a/protocols/isis/server/lsdb.go b/protocols/isis/server/lsdb.go
index 9dacc716c21ebb4b5e70f23b1d33f2a9f0a3120c..7e48bdbc5de0d48a62cce9529b143be3c73d0aec 100644
--- a/protocols/isis/server/lsdb.go
+++ b/protocols/isis/server/lsdb.go
@@ -2,6 +2,7 @@ package server
 
 import (
 	"fmt"
+	"os"
 	"sync"
 
 	"github.com/bio-routing/bio-rd/protocols/isis/packet"
@@ -55,6 +56,15 @@ func newLSDB(server *ISISServer) *lsdb {
 	protoSupportedTLV := packet.NewProtocolsSupportedTLV([]uint8{0xcc, 0x8e})
 	localLSPDU.TLVs = append(localLSPDU.TLVs, protoSupportedTLV)
 
+	hostname, err := os.Hostname()
+	if err == nil {
+		hostnameTLV := packet.NewDynamicHostnameTLV([]byte(hostname))
+		localLSPDU.TLVs = append(localLSPDU.TLVs, hostnameTLV)
+	}
+
+	ipInterfaceAddrTLV := packet.NewIPInterfaceAddressesTLV([]uint32{3232235520})
+	localLSPDU.TLVs = append(localLSPDU.TLVs, ipInterfaceAddrTLV)
+
 	localLSPDU.SetChecksum()
 	lsdb.lsps[localLSPID] = newLSDBEntry(localLSPDU)
 	return lsdb
@@ -246,7 +256,8 @@ func (lsdb *lsdb) getCSNP() *packet.CSNP {
 		StartLSPID: packet.LSPID{},
 		EndLSPID: packet.LSPID{
 			SystemID:     types.SystemID{255, 255, 255, 255, 255, 255},
-			PseudonodeID: 65535,
+			PseudonodeID: 255,
+			LSPNumber:    255,
 		},
 		TLVs: make([]packet.TLV, 0, 1),
 	}
diff --git a/protocols/isis/server/lsp.go b/protocols/isis/server/lsp.go
new file mode 100644
index 0000000000000000000000000000000000000000..b6d107a5d8130ccde1af358b9318a7f0915305b7
--- /dev/null
+++ b/protocols/isis/server/lsp.go
@@ -0,0 +1,63 @@
+package server
+
+import (
+	"os"
+
+	"github.com/bio-routing/bio-rd/protocols/isis/packet"
+)
+
+func (s *ISISServer) createLSPDU() *packet.LSPDU {
+	lspID := packet.LSPID{
+		SystemID:     s.config.NETs[0].SystemID,
+		PseudonodeID: 0x00,
+	}
+
+	lspdu := &packet.LSPDU{
+		Length:            packet.LSPDUMinLen,
+		RemainingLifetime: 3600,
+		LSPID:             lspID,
+		SequenceNumber:    1,
+		Checksum:          0,
+		TypeBlock:         0x03,
+		TLVs:              make([]packet.TLV, 0),
+	}
+
+	areaAddressesTLV := packet.NewAreaAddressesTLV(s.getAreas())
+	lspdu.TLVs = append(lspdu.TLVs, areaAddressesTLV)
+
+	protoSupportedTLV := packet.NewProtocolsSupportedTLV([]uint8{0xcc, 0x8e})
+	lspdu.TLVs = append(lspdu.TLVs, protoSupportedTLV)
+
+	hostname, err := os.Hostname()
+	if err == nil {
+		hostnameTLV := packet.NewDynamicHostnameTLV([]byte(hostname))
+		lspdu.TLVs = append(lspdu.TLVs, hostnameTLV)
+	}
+
+	ipInterfaceAddrTLV := packet.NewIPInterfaceAddressesTLV([]uint32{3232235520})
+	lspdu.TLVs = append(lspdu.TLVs, ipInterfaceAddrTLV)
+
+	teRouterIDTLV := packet.NewTrafficEngineeringRouterIDTLV(s.config.TrafficEngineeringRouterID)
+	lspdu.TLVs = append(lspdu.TLVs, teRouterIDTLV)
+
+	extISReachTLV := s.createExtendedISReachabilityTLV()
+	lspdu.TLVs = append(lspdu.TLVs, extISReachTLV)
+
+	lspdu.SetChecksum()
+	return lspdu
+}
+
+func (s *ISISServer) createExtendedISReachabilityTLV() *packet.ExtendedISReachabilityTLV {
+	tlv := packet.NewExtendedISReachabilityTLV()
+
+	s.interfacesMu.RLock()
+	defer s.interfacesMu.RUnlock()
+	for i := range s.interfaces {
+		for j := range s.interfaces[i].l2.neighbors {
+			n := s.interfaces[i].l2.neighbors[j].getExtendedISReachabilityNeighbor()
+			tlv.Neighbors = append(tlv.Neighbors, n)
+		}
+	}
+
+	return tlv
+}
diff --git a/protocols/isis/server/neighbor.go b/protocols/isis/server/neighbor.go
index 33ed7bb8637a79d6d839c985c6b84aa1b4358845..fe1752f5c932127f7280a439500cda87e50f1e37 100644
--- a/protocols/isis/server/neighbor.go
+++ b/protocols/isis/server/neighbor.go
@@ -1,6 +1,7 @@
 package server
 
 import (
+	"github.com/bio-routing/bio-rd/protocols/isis/packet"
 	"github.com/bio-routing/bio-rd/protocols/isis/types"
 )
 
@@ -11,6 +12,7 @@ type neighbor struct {
 	localCircuitID         uint8
 	extendedLocalCircuitID uint32
 	fsm                    *FSM
+	ipInterfaceAddresses   []uint32
 }
 
 func newNeighbor(sysID types.SystemID, ifa *netIf, extendedLocalCircuitID uint32) *neighbor {
@@ -18,5 +20,31 @@ func newNeighbor(sysID types.SystemID, ifa *netIf, extendedLocalCircuitID uint32
 		systemID:               sysID,
 		ifa:                    ifa,
 		extendedLocalCircuitID: extendedLocalCircuitID,
+		ipInterfaceAddresses:   make([]uint32, 0),
 	}
 }
+
+func (n *neighbor) getExtendedISReachabilityNeighbor() *packet.ExtendedISReachabilityNeighbor {
+	eirn := packet.NewExtendedISReachabilityNeighbor(
+		types.NewSourceID(
+			n.systemID,
+			n.localCircuitID,
+		),
+		n.ifa.l2.get3ByteMetric(),
+	)
+
+	for i := range n.ifa.device.Addrs {
+		if !n.ifa.device.Addrs[i].Addr().IsIPv4() {
+			continue
+		}
+
+		eirn.AddSubTLV(packet.NewIPv4InterfaceAddressSubTLV(n.ifa.device.Addrs[i].Addr().ToUint32()))
+	}
+
+	for i := range n.ipInterfaceAddresses {
+		eirn.AddSubTLV(packet.NewIPv4NeighborAddressSubTLV(n.ipInterfaceAddresses[i]))
+	}
+
+	eirn.AddSubTLV(packet.NewLinkLocalRemoteIdentifiersSubTLV(uint32(n.ifa.device.Index), n.extendedLocalCircuitID))
+	return eirn
+}