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