diff --git a/net/ip.go b/net/ip.go
index c82a2eef2d217945b2fbe692eff31a094f580583..f1d80fcd473ffb94fb0898733e38ad92c32e69af 100644
--- a/net/ip.go
+++ b/net/ip.go
@@ -1,23 +1,30 @@
 package net
 
+import (
+	"fmt"
+)
+
 // IP represents an IPv4 or IPv6 address
 type IP struct {
-	higher uint64
-	lower  uint64
+	higher    uint64
+	lower     uint64
+	ipVersion uint8
 }
 
 // IPv4 returns a new `IP` representing an IPv4 address
 func IPv4(val uint32) IP {
 	return IP{
-		lower: uint64(val),
+		lower:     uint64(val),
+		ipVersion: 4,
 	}
 }
 
 // IPv6 returns a new `IP` representing an IPv6 address
 func IPv6(higher, lower uint64) IP {
 	return IP{
-		higher: higher,
-		lower:  lower,
+		higher:    higher,
+		lower:     lower,
+		ipVersion: 6,
 	}
 }
 
@@ -27,8 +34,8 @@ func (ip *IP) ToUint32() uint32 {
 }
 
 // Compare compares two IP addresses (returns 0 if equal, -1 if `ip` is smaller than `other`, 1 if `ip` is greater than `other`)
-func (ip *IP) Compare(other *IP) int {
-	if ip.higher == other.higher && ip.lower == other.lower {
+func (ip IP) Compare(other IP) int {
+	if ip == other {
 		return 0
 	}
 
@@ -46,3 +53,39 @@ func (ip *IP) Compare(other *IP) int {
 
 	return -1
 }
+
+func (ip IP) String() string {
+	if ip.ipVersion == 6 {
+		return ip.stringIPv6()
+	}
+
+	return ip.stringIPv4()
+}
+
+func (ip IP) stringIPv6() string {
+	fmt.Println(ip.higher & 0xFFFF000000000000 >> 48)
+
+	return fmt.Sprintf("%X:%X:%X:%X:%X:%X:%X:%X",
+		ip.higher&0xFFFF000000000000>>48,
+		ip.higher&0x0000FFFF00000000>>32,
+		ip.higher&0x00000000FFFF0000>>16,
+		ip.higher&0x000000000000FFFF,
+		ip.lower&0xFFFF000000000000>>48,
+		ip.lower&0x0000FFFF00000000>>32,
+		ip.lower&0x00000000FFFF0000>>16,
+		ip.lower&0x000000000000FFFF)
+}
+
+func (ip IP) stringIPv4() string {
+	u := ip.ToUint32()
+
+	return fmt.Sprintf("%d.%d.%d.%d",
+		u&0xFF000000>>24,
+		u&0x00FF0000>>16,
+		u&0x0000FF00>>8,
+		u&0x000000FF)
+}
+
+func (ip IP) Bytes() {
+
+}
diff --git a/net/ip_test.go b/net/ip_test.go
index fe199241276439b2a3cc65b8bcb130be92f58ea6..ab8bfcd7b757a810993f3ee40e7279cc32c675ce 100644
--- a/net/ip_test.go
+++ b/net/ip_test.go
@@ -37,17 +37,17 @@ func TestToUint32(t *testing.T) {
 func TestCompare(t *testing.T) {
 	tests := []struct {
 		name     string
-		ip       *IP
-		other    *IP
+		ip       IP
+		other    IP
 		expected int
 	}{
 		{
 			name: "equal",
-			ip: &IP{
+			ip: IP{
 				lower:  100,
 				higher: 200,
 			},
-			other: &IP{
+			other: IP{
 				lower:  100,
 				higher: 200,
 			},
@@ -55,11 +55,11 @@ func TestCompare(t *testing.T) {
 		},
 		{
 			name: "greater higher word",
-			ip: &IP{
+			ip: IP{
 				lower:  123,
 				higher: 200,
 			},
-			other: &IP{
+			other: IP{
 				lower:  456,
 				higher: 100,
 			},
@@ -67,11 +67,11 @@ func TestCompare(t *testing.T) {
 		},
 		{
 			name: "lesser higher word",
-			ip: &IP{
+			ip: IP{
 				lower:  123,
 				higher: 100,
 			},
-			other: &IP{
+			other: IP{
 				lower:  456,
 				higher: 200,
 			},
@@ -79,11 +79,11 @@ func TestCompare(t *testing.T) {
 		},
 		{
 			name: "equal higher word but lesser lower word",
-			ip: &IP{
+			ip: IP{
 				lower:  456,
 				higher: 100,
 			},
-			other: &IP{
+			other: IP{
 				lower:  123,
 				higher: 100,
 			},
@@ -91,11 +91,11 @@ func TestCompare(t *testing.T) {
 		},
 		{
 			name: "equal higher word but lesser lower word",
-			ip: &IP{
+			ip: IP{
 				lower:  123,
 				higher: 100,
 			},
-			other: &IP{
+			other: IP{
 				lower:  456,
 				higher: 100,
 			},
@@ -109,3 +109,39 @@ func TestCompare(t *testing.T) {
 		})
 	}
 }
+
+func TestIPString(t *testing.T) {
+	tests := []struct {
+		ip       IP
+		expected string
+	}{
+		{
+			ip:       IPv4(strAddr("192.168.0.1")),
+			expected: "192.168.0.1",
+		},
+		{
+			ip:       IPv4(strAddr("0.0.0.0")),
+			expected: "0.0.0.0",
+		},
+		{
+			ip:       IPv4(strAddr("255.255.255.255")),
+			expected: "255.255.255.255",
+		},
+		{
+			ip:       IPv6(0, 0),
+			expected: "0:0:0:0:0:0:0:0",
+		},
+		{
+			ip:       IPv6(2306131596687708724, 6230974922281175806),
+			expected: "2001:678:1E0:1234:5678:DEAD:BEEF:CAFE",
+		},
+		{
+			ip:       IPv6(^uint64(0), ^uint64(0)),
+			expected: "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF",
+		},
+	}
+
+	for _, test := range tests {
+		assert.Equal(t, test.expected, test.ip.String())
+	}
+}
diff --git a/route/bgp_path.go b/route/bgp_path.go
index 373888abed2644958b4bd3597d4678027287909e..d2aa5247abb665a53e3073a06a9d9ec1d0c52369 100644
--- a/route/bgp_path.go
+++ b/route/bgp_path.go
@@ -21,7 +21,7 @@ type BGPPath struct {
 	MED               uint32
 	EBGP              bool
 	BGPIdentifier     uint32
-	Source            uint32
+	Source            bnet.IP
 	Communities       []uint32
 	LargeCommunities  []packet.LargeCommunity
 	UnknownAttributes *packet.PathAttribute
@@ -92,19 +92,19 @@ func (b *BGPPath) Compare(c *BGPPath) int8 {
 	}
 
 	// g)
-	if c.Source < b.Source {
+	if c.Source.Compare(b.Source) == -1 {
 		return 1
 	}
 
-	if c.Source > b.Source {
+	if c.Source.Compare(b.Source) == 1 {
 		return -1
 	}
 
-	if c.NextHop < b.NextHop {
+	if c.NextHop.Compare(b.NextHop) == -1 {
 		return 1
 	}
 
-	if c.NextHop > b.NextHop {
+	if c.NextHop.Compare(b.NextHop) == 1 {
 		return -1
 	}
 
@@ -156,7 +156,7 @@ func (b *BGPPath) better(c *BGPPath) bool {
 		return true
 	}
 
-	if c.Source < b.Source {
+	if c.Source.Compare(b.Source) == -1 {
 		return true
 	}
 
@@ -184,7 +184,7 @@ func (b *BGPPath) Print() string {
 	ret += fmt.Sprintf("\t\tOrigin: %s\n", origin)
 	ret += fmt.Sprintf("\t\tAS Path: %v\n", b.ASPath)
 	ret += fmt.Sprintf("\t\tBGP type: %s\n", bgpType)
-	nh := uint32To4Byte(b.NextHop)
+	nh := uint32To4Byte(b.NextHop.ToUint32())
 	ret += fmt.Sprintf("\t\tNEXT HOP: %d.%d.%d.%d\n", nh[0], nh[1], nh[2], nh[3])
 	ret += fmt.Sprintf("\t\tMED: %d\n", b.MED)
 	ret += fmt.Sprintf("\t\tPath ID: %d\n", b.PathIdentifier)
diff --git a/routingtable/filter/actions/set_nexthop_action.go b/routingtable/filter/actions/set_nexthop_action.go
index f178f61802882157856fc1f4bf15c8d9f0b08dc6..de1e9bc959b8f9d827c48c844699aa2aed92fda9 100644
--- a/routingtable/filter/actions/set_nexthop_action.go
+++ b/routingtable/filter/actions/set_nexthop_action.go
@@ -2,16 +2,17 @@ package actions
 
 import (
 	"github.com/bio-routing/bio-rd/net"
+	bnet "github.com/bio-routing/bio-rd/net"
 	"github.com/bio-routing/bio-rd/route"
 )
 
 type SetNextHopAction struct {
-	addr uint32
+	ip bnet.IP
 }
 
-func NewSetNextHopAction(addr uint32) *SetNextHopAction {
+func NewSetNextHopAction(ip bnet.IP) *SetNextHopAction {
 	return &SetNextHopAction{
-		addr: addr,
+		ip: ip,
 	}
 }
 
@@ -21,7 +22,7 @@ func (a *SetNextHopAction) Do(p net.Prefix, pa *route.Path) (modPath *route.Path
 	}
 
 	modified := pa.Copy()
-	modified.BGPPath.NextHop = a.addr
+	modified.BGPPath.NextHop = a.ip
 
 	return modified, false
 }
diff --git a/routingtable/neighbor.go b/routingtable/neighbor.go
index f298356fa73ef40de0293b76d55c28cc0c363dfe..bf6e97c6af46da590dd071e6e40b9978410f78ce 100644
--- a/routingtable/neighbor.go
+++ b/routingtable/neighbor.go
@@ -1,12 +1,14 @@
 package routingtable
 
+import bnet "github.com/bio-routing/bio-rd/net"
+
 // Neighbor represents the attributes identifying a neighbor relationsship
 type Neighbor struct {
 	// Addres is the IPv4 address of the neighbor as integer representation
-	Address uint32
+	Address bnet.IP
 
 	// Local address is the local address of the BGP TCP connection
-	LocalAddress uint32
+	LocalAddress bnet.IP
 
 	// Type is the type / protocol used for routing inforation communitation
 	Type uint8