From 2586cdbf0164879d559c397ecdf6ece7747617f3 Mon Sep 17 00:00:00 2001
From: Daniel Czerwonk <daniel@dan-nrw.de>
Date: Thu, 28 Jun 2018 20:59:05 +0200
Subject: [PATCH] net cleanup, prefix uses our IP type now

---
 net/ip.go            | 31 +++++++++++++++++++-
 net/ip_test.go       |  6 ++--
 net/prefix.go        | 35 +++++++++++++++-------
 net/prefix_test.go   | 69 ++++++++++++++++++++------------------------
 route/route.go       |  2 +-
 routingtable/trie.go | 12 ++++----
 6 files changed, 96 insertions(+), 59 deletions(-)

diff --git a/net/ip.go b/net/ip.go
index a277a192..2774ee5c 100644
--- a/net/ip.go
+++ b/net/ip.go
@@ -105,7 +105,7 @@ func (ip IP) Bytes() []byte {
 }
 
 func (ip IP) bytesIPv4() []byte {
-	u := uint32(^uint64(0) >> 32 & ip.lower)
+	u := ip.toUint32()
 	return []byte{
 		byte(u & 0xFF000000 >> 24),
 		byte(u & 0x00FF0000 >> 16),
@@ -114,6 +114,10 @@ func (ip IP) bytesIPv4() []byte {
 	}
 }
 
+func (ip IP) toUint32() uint32 {
+	return uint32(^uint64(0) >> 32 & ip.lower)
+}
+
 func (ip IP) bytesIPv6() []byte {
 	return []byte{
 		byte(ip.higher & 0xFF00000000000000 >> 56),
@@ -139,3 +143,28 @@ func (ip IP) bytesIPv6() []byte {
 func (ip IP) ToNetIP() net.IP {
 	return net.IP(ip.Bytes())
 }
+
+// BitAtPosition returns the bit at position pos
+func (ip IP) BitAtPosition(pos uint8) bool {
+	if ip.ipVersion == 6 {
+		return ip.bitAtPositionIPv6(pos)
+	}
+
+	return ip.bitAtPositionIPv4(pos)
+}
+
+func (ip IP) bitAtPositionIPv4(pos uint8) bool {
+	if pos > 32 {
+		return false
+	}
+
+	return false
+}
+
+func (ip IP) bitAtPositionIPv6(pos uint8) bool {
+	if pos > 128 {
+		return false
+	}
+
+	return false
+}
diff --git a/net/ip_test.go b/net/ip_test.go
index 7283cfa8..cb97d5bd 100644
--- a/net/ip_test.go
+++ b/net/ip_test.go
@@ -90,15 +90,15 @@ func TestIPString(t *testing.T) {
 		expected string
 	}{
 		{
-			ip:       IPv4(strAddr("192.168.0.1")),
+			ip:       IPv4FromOctets(192, 168, 0, 1),
 			expected: "192.168.0.1",
 		},
 		{
-			ip:       IPv4(strAddr("0.0.0.0")),
+			ip:       IPv4FromOctets(0, 0, 0, 0),
 			expected: "0.0.0.0",
 		},
 		{
-			ip:       IPv4(strAddr("255.255.255.255")),
+			ip:       IPv4FromOctets(255, 255, 255, 255),
 			expected: "255.255.255.255",
 		},
 		{
diff --git a/net/prefix.go b/net/prefix.go
index 126090fa..914470b0 100644
--- a/net/prefix.go
+++ b/net/prefix.go
@@ -3,21 +3,18 @@ package net
 import (
 	"fmt"
 	"math"
-	"net"
 	"strconv"
 	"strings"
-
-	"github.com/taktv6/tflow2/convert"
 )
 
 // Prefix represents an IPv4 prefix
 type Prefix struct {
-	addr   uint32
+	addr   IP
 	pfxlen uint8
 }
 
 // NewPfx creates a new Prefix
-func NewPfx(addr uint32, pfxlen uint8) Prefix {
+func NewPfx(addr IP, pfxlen uint8) Prefix {
 	return Prefix{
 		addr:   addr,
 		pfxlen: pfxlen,
@@ -49,7 +46,7 @@ func StrToAddr(x string) (uint32, error) {
 }
 
 // Addr returns the address of the prefix
-func (pfx Prefix) Addr() uint32 {
+func (pfx Prefix) Addr() IP {
 	return pfx.addr
 }
 
@@ -60,7 +57,7 @@ func (pfx Prefix) Pfxlen() uint8 {
 
 // String returns a string representation of pfx
 func (pfx Prefix) String() string {
-	return fmt.Sprintf("%s/%d", net.IP(convert.Uint32Byte(pfx.addr)), pfx.pfxlen)
+	return fmt.Sprintf("%s/%d", pfx.addr, pfx.pfxlen)
 }
 
 // Contains checks if x is a subnet of or equal to pfx
@@ -69,8 +66,16 @@ func (pfx Prefix) Contains(x Prefix) bool {
 		return false
 	}
 
+	if pfx.addr.ipVersion == 4 {
+		return pfx.containsIPv4(x)
+	}
+
+	panic("No IPv6 support yet!")
+}
+
+func (pfx Prefix) containsIPv4(x Prefix) bool {
 	mask := uint32((math.MaxUint32 << (32 - pfx.pfxlen)))
-	return (pfx.addr & mask) == (x.addr & mask)
+	return (pfx.addr.toUint32() & mask) == (x.addr.toUint32() & mask)
 }
 
 // Equal checks if pfx and x are equal
@@ -80,9 +85,17 @@ func (pfx Prefix) Equal(x Prefix) bool {
 
 // GetSupernet gets the next common supernet of pfx and x
 func (pfx Prefix) GetSupernet(x Prefix) Prefix {
+	if pfx.addr.ipVersion == 4 {
+		return pfx.supernetIPv4(x)
+	}
+
+	panic("No IPv6 support yet!")
+}
+
+func (pfx Prefix) supernetIPv4(x Prefix) Prefix {
 	maxPfxLen := min(pfx.pfxlen, x.pfxlen) - 1
-	a := pfx.addr >> (32 - maxPfxLen)
-	b := x.addr >> (32 - maxPfxLen)
+	a := pfx.addr.toUint32() >> (32 - maxPfxLen)
+	b := x.addr.toUint32() >> (32 - maxPfxLen)
 
 	for i := 0; a != b; i++ {
 		a = a >> 1
@@ -91,7 +104,7 @@ func (pfx Prefix) GetSupernet(x Prefix) Prefix {
 	}
 
 	return Prefix{
-		addr:   a << (32 - maxPfxLen),
+		addr:   IPv4(a << (32 - maxPfxLen)),
 		pfxlen: maxPfxLen,
 	}
 }
diff --git a/net/prefix_test.go b/net/prefix_test.go
index 9ab908bc..82a6bafa 100644
--- a/net/prefix_test.go
+++ b/net/prefix_test.go
@@ -7,8 +7,8 @@ import (
 )
 
 func TestNewPfx(t *testing.T) {
-	p := NewPfx(123, 11)
-	if p.addr != 123 || p.pfxlen != 11 {
+	p := NewPfx(IPv4(123), 11)
+	if p.addr != IPv4(123) || p.pfxlen != 11 {
 		t.Errorf("NewPfx() failed: Unexpected values")
 	}
 }
@@ -17,12 +17,12 @@ func TestAddr(t *testing.T) {
 	tests := []struct {
 		name     string
 		pfx      Prefix
-		expected uint32
+		expected IP
 	}{
 		{
 			name:     "Test 1",
-			pfx:      NewPfx(100, 5),
-			expected: 100,
+			pfx:      NewPfx(IPv4(100), 5),
+			expected: IPv4(100),
 		},
 	}
 
@@ -42,7 +42,7 @@ func TestPfxlen(t *testing.T) {
 	}{
 		{
 			name:     "Test 1",
-			pfx:      NewPfx(100, 5),
+			pfx:      NewPfx(IPv4(100), 5),
 			expected: 5,
 		},
 	}
@@ -65,30 +65,30 @@ func TestGetSupernet(t *testing.T) {
 		{
 			name: "Test 1",
 			a: Prefix{
-				addr:   167772160, // 10.0.0.0/8
+				addr:   IPv4FromOctets(10, 0, 0, 0),
 				pfxlen: 8,
 			},
 			b: Prefix{
-				addr:   191134464, // 11.100.123.0/24
+				addr:   IPv4FromOctets(11, 100, 123, 0),
 				pfxlen: 24,
 			},
 			expected: Prefix{
-				addr:   167772160, // 10.0.0.0/7
+				addr:   IPv4FromOctets(10, 0, 0, 0),
 				pfxlen: 7,
 			},
 		},
 		{
 			name: "Test 2",
 			a: Prefix{
-				addr:   167772160, // 10.0.0.0/8
+				addr:   IPv4FromOctets(10, 0, 0, 0),
 				pfxlen: 8,
 			},
 			b: Prefix{
-				addr:   3232235520, // 192.168.0.0/24
+				addr:   IPv4FromOctets(192, 168, 0, 0),
 				pfxlen: 24,
 			},
 			expected: Prefix{
-				addr:   0, // 0.0.0.0/0
+				addr:   IPv4(0), // 0.0.0.0/0
 				pfxlen: 0,
 			},
 		},
@@ -110,11 +110,11 @@ func TestContains(t *testing.T) {
 		{
 			name: "Test 1",
 			a: Prefix{
-				addr:   0,
+				addr:   IPv4(0),
 				pfxlen: 0,
 			},
 			b: Prefix{
-				addr:   100,
+				addr:   IPv4(100),
 				pfxlen: 24,
 			},
 			expected: true,
@@ -122,11 +122,11 @@ func TestContains(t *testing.T) {
 		{
 			name: "Test 2",
 			a: Prefix{
-				addr:   100,
+				addr:   IPv4(100),
 				pfxlen: 24,
 			},
 			b: Prefix{
-				addr:   0,
+				addr:   IPv4(0),
 				pfxlen: 0,
 			},
 			expected: false,
@@ -134,11 +134,11 @@ func TestContains(t *testing.T) {
 		{
 			name: "Test 3",
 			a: Prefix{
-				addr:   167772160,
+				addr:   IPv4(167772160),
 				pfxlen: 8,
 			},
 			b: Prefix{
-				addr:   167772160,
+				addr:   IPv4(167772160),
 				pfxlen: 9,
 			},
 			expected: true,
@@ -146,11 +146,11 @@ func TestContains(t *testing.T) {
 		{
 			name: "Test 4",
 			a: Prefix{
-				addr:   167772160,
+				addr:   IPv4(167772160),
 				pfxlen: 8,
 			},
 			b: Prefix{
-				addr:   174391040,
+				addr:   IPv4(174391040),
 				pfxlen: 24,
 			},
 			expected: true,
@@ -158,11 +158,11 @@ func TestContains(t *testing.T) {
 		{
 			name: "Test 5",
 			a: Prefix{
-				addr:   167772160,
+				addr:   IPv4(167772160),
 				pfxlen: 8,
 			},
 			b: Prefix{
-				addr:   184549377,
+				addr:   IPv4(184549377),
 				pfxlen: 24,
 			},
 			expected: false,
@@ -170,11 +170,11 @@ func TestContains(t *testing.T) {
 		{
 			name: "Test 6",
 			a: Prefix{
-				addr:   167772160,
+				addr:   IPv4(167772160),
 				pfxlen: 8,
 			},
 			b: Prefix{
-				addr:   191134464,
+				addr:   IPv4(191134464),
 				pfxlen: 24,
 			},
 			expected: false,
@@ -182,11 +182,11 @@ func TestContains(t *testing.T) {
 		{
 			name: "Test 7",
 			a: Prefix{
-				addr:   strAddr("169.0.0.0"),
+				addr:   IPv4FromOctets(169, 0, 0, 0),
 				pfxlen: 25,
 			},
 			b: Prefix{
-				addr:   strAddr("169.1.1.0"),
+				addr:   IPv4FromOctets(169, 1, 1, 0),
 				pfxlen: 26,
 			},
 			expected: false,
@@ -245,14 +245,14 @@ func TestEqual(t *testing.T) {
 	}{
 		{
 			name:     "Equal PFXs",
-			a:        NewPfx(100, 8),
-			b:        NewPfx(100, 8),
+			a:        NewPfx(IPv4(100), 8),
+			b:        NewPfx(IPv4(100), 8),
 			expected: true,
 		},
 		{
 			name:     "Unequal PFXs",
-			a:        NewPfx(100, 8),
-			b:        NewPfx(200, 8),
+			a:        NewPfx(IPv4(100), 8),
+			b:        NewPfx(IPv4(200), 8),
 			expected: false,
 		},
 	}
@@ -273,12 +273,12 @@ func TestString(t *testing.T) {
 	}{
 		{
 			name:     "Test 1",
-			pfx:      NewPfx(167772160, 8), // 10.0.0.0/8
+			pfx:      NewPfx(IPv4FromOctets(10, 0, 0, 0), 8),
 			expected: "10.0.0.0/8",
 		},
 		{
 			name:     "Test 2",
-			pfx:      NewPfx(167772160, 16), // 10.0.0.0/8
+			pfx:      NewPfx(IPv4FromOctets(10, 0, 0, 0), 16),
 			expected: "10.0.0.0/16",
 		},
 	}
@@ -344,8 +344,3 @@ func TestStrToAddr(t *testing.T) {
 		assert.Equal(t, test.expected, res)
 	}
 }
-
-func strAddr(s string) uint32 {
-	ret, _ := StrToAddr(s)
-	return ret
-}
diff --git a/route/route.go b/route/route.go
index 300f5dcb..f9251bbc 100644
--- a/route/route.go
+++ b/route/route.go
@@ -63,7 +63,7 @@ func (r *Route) Prefix() net.Prefix {
 }
 
 // Addr gets a routes address
-func (r *Route) Addr() uint32 {
+func (r *Route) Addr() net.IP {
 	return r.pfx.Addr()
 }
 
diff --git a/routingtable/trie.go b/routingtable/trie.go
index 5e719f08..51c1bfa0 100644
--- a/routingtable/trie.go
+++ b/routingtable/trie.go
@@ -46,7 +46,7 @@ func (n *node) removePath(pfx net.Prefix, p *route.Path) (final bool) {
 		return nPathsAfterDel == 0
 	}
 
-	b := getBitUint32(pfx.Addr(), n.route.Pfxlen()+1)
+	b := pfx.Addr().BitAtPosition(n.route.Pfxlen() + 1)
 	if !b {
 		return n.l.removePath(pfx, p)
 	}
@@ -111,7 +111,7 @@ func (n *node) get(pfx net.Prefix) *node {
 		return nil
 	}
 
-	b := getBitUint32(pfx.Addr(), n.route.Pfxlen()+1)
+	b := pfx.Addr().BitAtPosition(n.route.Pfxlen() + 1)
 	if !b {
 		return n.l.get(pfx)
 	}
@@ -136,7 +136,7 @@ func (n *node) addPath(pfx net.Prefix, p *route.Path) (*node, bool) {
 	}
 
 	// pfx is a subnet of this node
-	b := getBitUint32(pfx.Addr(), n.route.Pfxlen()+1)
+	b := pfx.Addr().BitAtPosition(n.route.Pfxlen() + 1)
 
 	if !b {
 		return n.insertLow(pfx, p, currentPfx.Pfxlen())
@@ -177,7 +177,7 @@ func (n *node) newSuperNode(pfx net.Prefix, p *route.Path) *node {
 
 func (n *node) insertChildren(old *node, newPfx net.Prefix, newPath *route.Path) {
 	// Place the old node
-	b := getBitUint32(old.route.Prefix().Addr(), n.route.Pfxlen()+1)
+	b := old.route.Prefix().Addr().BitAtPosition(n.route.Pfxlen() + 1)
 	if !b {
 		n.l = old
 		n.l.skip = old.route.Pfxlen() - n.route.Pfxlen() - 1
@@ -188,7 +188,7 @@ func (n *node) insertChildren(old *node, newPfx net.Prefix, newPath *route.Path)
 
 	// Place the new Prefix
 	newNode := newNode(newPfx, newPath, newPfx.Pfxlen()-n.route.Pfxlen()-1, false)
-	b = getBitUint32(newPfx.Addr(), n.route.Pfxlen()+1)
+	b = newPfx.Addr().BitAtPosition(n.route.Pfxlen() + 1)
 	if !b {
 		n.l = newNode
 	} else {
@@ -203,7 +203,7 @@ func (n *node) insertBefore(pfx net.Prefix, p *route.Path, parentPfxLen uint8) *
 	skip := n.skip - pfxLenDiff
 	new := newNode(pfx, p, skip, false)
 
-	b := getBitUint32(pfx.Addr(), parentPfxLen)
+	b := pfx.Addr().BitAtPosition(parentPfxLen)
 	if !b {
 		new.l = tmp
 		new.l.skip = tmp.route.Pfxlen() - pfx.Pfxlen() - 1
-- 
GitLab