Skip to content
Snippets Groups Projects
Commit beee8a29 authored by Oliver Herms's avatar Oliver Herms
Browse files

Basics

parent 8092e1d8
No related branches found
No related tags found
No related merge requests found
...@@ -3,20 +3,55 @@ package net ...@@ -3,20 +3,55 @@ package net
import ( import (
"fmt" "fmt"
"net" "net"
"github.com/bio-routing/bio-rd/net/api"
) )
// IP represents an IPv4 or IPv6 address // IP represents an IPv4 or IPv6 address
type IP struct { type IP struct {
higher uint64 higher uint64
lower uint64 lower uint64
ipVersion uint8 isLegacy bool
}
// IPFromProtoIP creates an IP address from a proto IP
func IPFromProtoIP(addr api.IP) IP {
return IP{
higher: addr.Higher,
lower: addr.Lower,
isLegacy: addr.IsLegacy,
}
}
// ToProto converts an IP to a proto IP
func (ip IP) ToProto() *api.IP {
return &api.IP{
Lower: ip.lower,
Higher: ip.higher,
IsLegacy: ip.isLegacy,
}
}
// Lower gets the lower half of the IP address
func (ip IP) Lower() uint64 {
return ip.lower
}
// Higher gets the higher half of the IP address
func (ip IP) Higher() uint64 {
return ip.higher
}
// IsLegacy returns true for IPv6, else false
func (ip IP) IsLegacy() bool {
return ip.isLegacy
} }
// IPv4 returns a new `IP` representing an IPv4 address // IPv4 returns a new `IP` representing an IPv4 address
func IPv4(val uint32) IP { func IPv4(val uint32) IP {
return IP{ return IP{
lower: uint64(val), lower: uint64(val),
ipVersion: 4, isLegacy: true,
} }
} }
...@@ -28,9 +63,9 @@ func IPv4FromOctets(o1, o2, o3, o4 uint8) IP { ...@@ -28,9 +63,9 @@ func IPv4FromOctets(o1, o2, o3, o4 uint8) IP {
// IPv6 returns a new `IP` representing an IPv6 address // IPv6 returns a new `IP` representing an IPv6 address
func IPv6(higher, lower uint64) IP { func IPv6(higher, lower uint64) IP {
return IP{ return IP{
higher: higher, higher: higher,
lower: lower, lower: lower,
ipVersion: 6, isLegacy: false,
} }
} }
...@@ -104,7 +139,7 @@ func (ip IP) Compare(other IP) int { ...@@ -104,7 +139,7 @@ func (ip IP) Compare(other IP) int {
} }
func (ip IP) String() string { func (ip IP) String() string {
if ip.ipVersion == 6 { if !ip.isLegacy {
return ip.stringIPv6() return ip.stringIPv6()
} }
...@@ -131,7 +166,7 @@ func (ip IP) stringIPv4() string { ...@@ -131,7 +166,7 @@ func (ip IP) stringIPv4() string {
// Bytes returns the byte representation of an IP address // Bytes returns the byte representation of an IP address
func (ip IP) Bytes() []byte { func (ip IP) Bytes() []byte {
if ip.ipVersion == 6 { if !ip.isLegacy {
return ip.bytesIPv6() return ip.bytesIPv6()
} }
...@@ -150,12 +185,12 @@ func (ip IP) bytesIPv4() []byte { ...@@ -150,12 +185,12 @@ func (ip IP) bytesIPv4() []byte {
// IsIPv4 returns if the `IP` is of address family IPv4 // IsIPv4 returns if the `IP` is of address family IPv4
func (ip IP) IsIPv4() bool { func (ip IP) IsIPv4() bool {
return ip.ipVersion == 4 return ip.isLegacy
} }
// SizeBytes returns the number of bytes required to represent the `IP` // SizeBytes returns the number of bytes required to represent the `IP`
func (ip IP) SizeBytes() uint8 { func (ip IP) SizeBytes() uint8 {
if ip.ipVersion == 4 { if ip.isLegacy {
return 4 return 4
} }
...@@ -195,7 +230,7 @@ func (ip IP) ToNetIP() net.IP { ...@@ -195,7 +230,7 @@ func (ip IP) ToNetIP() net.IP {
// BitAtPosition returns the bit at position pos // BitAtPosition returns the bit at position pos
func (ip IP) BitAtPosition(pos uint8) bool { func (ip IP) BitAtPosition(pos uint8) bool {
if ip.ipVersion == 6 { if !ip.isLegacy {
return ip.bitAtPositionIPv6(pos) return ip.bitAtPositionIPv6(pos)
} }
......
...@@ -5,9 +5,88 @@ import ( ...@@ -5,9 +5,88 @@ import (
"net" "net"
"testing" "testing"
"github.com/bio-routing/bio-rd/net/api"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestIPToProto(t *testing.T) {
tests := []struct {
name string
ip IP
expected *api.IP
}{
{
name: "IPv4",
ip: IP{
lower: 255,
isLegacy: true,
},
expected: &api.IP{
Lower: 255,
IsLegacy: true,
},
},
{
name: "IPv6",
ip: IP{
higher: 1000,
lower: 255,
isLegacy: false,
},
expected: &api.IP{
Higher: 1000,
Lower: 255,
IsLegacy: false,
},
},
}
for _, test := range tests {
res := test.ip.ToProto()
assert.Equal(t, test.expected, res, test.name)
}
}
func TestIPFromProtoIP(t *testing.T) {
tests := []struct {
name string
proto api.IP
expected IP
}{
{
name: "Test IPv4",
proto: api.IP{
Lower: 100,
Higher: 0,
IsLegacy: true,
},
expected: IP{
lower: 100,
higher: 0,
isLegacy: true,
},
},
{
name: "Test IPv6",
proto: api.IP{
Lower: 100,
Higher: 200,
IsLegacy: false,
},
expected: IP{
lower: 100,
higher: 200,
isLegacy: false,
},
},
}
for _, test := range tests {
res := IPFromProtoIP(test.proto)
assert.Equal(t, test.expected, res, test.name)
}
}
func TestCompare(t *testing.T) { func TestCompare(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
...@@ -155,27 +234,27 @@ func TestIPv4FromOctets(t *testing.T) { ...@@ -155,27 +234,27 @@ func TestIPv4FromOctets(t *testing.T) {
name: "172.217.16.195", name: "172.217.16.195",
octets: []uint8{172, 217, 16, 195}, octets: []uint8{172, 217, 16, 195},
expected: IP{ expected: IP{
higher: 0, higher: 0,
lower: 2899906755, lower: 2899906755,
ipVersion: 4, isLegacy: true,
}, },
}, },
{ {
name: "0.0.0.0", name: "0.0.0.0",
octets: []uint8{0, 0, 0, 0}, octets: []uint8{0, 0, 0, 0},
expected: IP{ expected: IP{
higher: 0, higher: 0,
lower: 0, lower: 0,
ipVersion: 4, isLegacy: true,
}, },
}, },
{ {
name: "255.255.255.255", name: "255.255.255.255",
octets: []uint8{255, 255, 255, 255}, octets: []uint8{255, 255, 255, 255},
expected: IP{ expected: IP{
higher: 0, higher: 0,
lower: math.MaxUint32, lower: math.MaxUint32,
ipVersion: 4, isLegacy: true,
}, },
}, },
} }
...@@ -206,9 +285,8 @@ func TestIPv6FromBlocks(t *testing.T) { ...@@ -206,9 +285,8 @@ func TestIPv6FromBlocks(t *testing.T) {
0xcafe, 0xcafe,
}, },
expected: IP{ expected: IP{
higher: 2306131596687708724, higher: 2306131596687708724,
lower: 6230974922281175806, lower: 6230974922281175806,
ipVersion: 6,
}, },
}, },
} }
...@@ -239,18 +317,17 @@ func TestIPFromBytes(t *testing.T) { ...@@ -239,18 +317,17 @@ func TestIPFromBytes(t *testing.T) {
name: "IPV4: 172.217.16.195", name: "IPV4: 172.217.16.195",
bytes: []byte{172, 217, 16, 195}, bytes: []byte{172, 217, 16, 195},
expected: IP{ expected: IP{
higher: 0, higher: 0,
lower: 2899906755, lower: 2899906755,
ipVersion: 4, isLegacy: true,
}, },
}, },
{ {
name: "IPV6: IPv6 2001:678:1E0:1234:5678:DEAD:BEEF:CAFE", name: "IPV6: IPv6 2001:678:1E0:1234:5678:DEAD:BEEF:CAFE",
bytes: []byte{0x20, 0x01, 0x06, 0x78, 0x01, 0xE0, 0x12, 0x34, 0x56, 0x78, 0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE}, bytes: []byte{0x20, 0x01, 0x06, 0x78, 0x01, 0xE0, 0x12, 0x34, 0x56, 0x78, 0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE},
expected: IP{ expected: IP{
higher: 2306131596687708724, higher: 2306131596687708724,
lower: 6230974922281175806, lower: 6230974922281175806,
ipVersion: 6,
}, },
}, },
{ {
......
...@@ -5,6 +5,8 @@ import ( ...@@ -5,6 +5,8 @@ import (
"math" "math"
"strconv" "strconv"
"strings" "strings"
"github.com/bio-routing/bio-rd/net/api"
) )
// Prefix represents an IPv4 prefix // Prefix represents an IPv4 prefix
...@@ -13,6 +15,22 @@ type Prefix struct { ...@@ -13,6 +15,22 @@ type Prefix struct {
pfxlen uint8 pfxlen uint8
} }
// NewPrefixFromProtoPrefix creates a Prefix from a proto Prefix
func NewPrefixFromProtoPrefix(pfx api.Prefix) Prefix {
return Prefix{
addr: IPFromProtoIP(*pfx.Address),
pfxlen: uint8(pfx.Pfxlen),
}
}
// ToProto converts prefix to proto prefix
func (pfx Prefix) ToProto() api.Prefix {
return api.Prefix{
Address: pfx.addr.ToProto(),
Pfxlen: uint32(pfx.pfxlen),
}
}
// NewPfx creates a new Prefix // NewPfx creates a new Prefix
func NewPfx(addr IP, pfxlen uint8) Prefix { func NewPfx(addr IP, pfxlen uint8) Prefix {
return Prefix{ return Prefix{
...@@ -66,7 +84,7 @@ func (pfx Prefix) Contains(x Prefix) bool { ...@@ -66,7 +84,7 @@ func (pfx Prefix) Contains(x Prefix) bool {
return false return false
} }
if pfx.addr.ipVersion == 4 { if pfx.addr.isLegacy {
return pfx.containsIPv4(x) return pfx.containsIPv4(x)
} }
...@@ -99,7 +117,7 @@ func (pfx Prefix) Equal(x Prefix) bool { ...@@ -99,7 +117,7 @@ func (pfx Prefix) Equal(x Prefix) bool {
// GetSupernet gets the next common supernet of pfx and x // GetSupernet gets the next common supernet of pfx and x
func (pfx Prefix) GetSupernet(x Prefix) Prefix { func (pfx Prefix) GetSupernet(x Prefix) Prefix {
if pfx.addr.ipVersion == 4 { if pfx.addr.isLegacy {
return pfx.supernetIPv4(x) return pfx.supernetIPv4(x)
} }
......
...@@ -3,9 +3,112 @@ package net ...@@ -3,9 +3,112 @@ package net
import ( import (
"testing" "testing"
"github.com/bio-routing/bio-rd/net/api"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestPrefixToProto(t *testing.T) {
tests := []struct {
name string
pfx Prefix
expected api.Prefix
}{
{
name: "IPv4",
pfx: Prefix{
addr: IP{
lower: 200,
isLegacy: true,
},
pfxlen: 24,
},
expected: api.Prefix{
Address: &api.IP{
Lower: 200,
IsLegacy: true,
},
Pfxlen: 24,
},
},
{
name: "IPv6",
pfx: Prefix{
addr: IP{
higher: 100,
lower: 200,
isLegacy: false,
},
pfxlen: 64,
},
expected: api.Prefix{
Address: &api.IP{
Higher: 100,
Lower: 200,
IsLegacy: false,
},
Pfxlen: 64,
},
},
}
for _, test := range tests {
res := test.pfx.ToProto()
assert.Equal(t, test.expected, res, test.name)
}
}
func TestNewPrefixFromProtoPrefix(t *testing.T) {
tests := []struct {
name string
proto api.Prefix
expected Prefix
}{
{
name: "IPv4",
proto: api.Prefix{
Address: &api.IP{
Higher: 0,
Lower: 2000,
IsLegacy: true,
},
Pfxlen: 24,
},
expected: Prefix{
addr: IP{
higher: 0,
lower: 2000,
isLegacy: true,
},
pfxlen: 24,
},
},
{
name: "IPv6",
proto: api.Prefix{
Address: &api.IP{
Higher: 1000,
Lower: 2000,
IsLegacy: false,
},
Pfxlen: 64,
},
expected: Prefix{
addr: IP{
higher: 1000,
lower: 2000,
isLegacy: false,
},
pfxlen: 64,
},
},
}
for _, test := range tests {
res := NewPrefixFromProtoPrefix(test.proto)
assert.Equal(t, test.expected, res, test.name)
}
}
func TestNewPfx(t *testing.T) { func TestNewPfx(t *testing.T) {
p := NewPfx(IPv4(123), 11) p := NewPfx(IPv4(123), 11)
if p.addr != IPv4(123) || p.pfxlen != 11 { if p.addr != IPv4(123) || p.pfxlen != 11 {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment