diff --git a/net/ip.go b/net/ip.go new file mode 100644 index 0000000000000000000000000000000000000000..efbac355c6edd7eb02654eabc60484452a22316e --- /dev/null +++ b/net/ip.go @@ -0,0 +1,46 @@ +package net + +// IP represents an IPv4 or IPv6 address +type IP struct { + higher uint64 + lower uint64 +} + +func IPv4(val uint32) IP { + return IP{ + lower: uint64(val), + } +} + +func IPv6(higher, lower uint64) IP { + return IP{ + higher: higher, + lower: lower, + } +} + +// ToUint32 returns the uint32 representation of an IP address +func (ip *IP) ToUint32() uint32 { + return uint32(^uint64(0) >> 32 & ip.lower) +} + +// 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 { + return 0 + } + + if ip.higher > other.higher { + return 1 + } + + if ip.higher < other.higher { + return -1 + } + + if ip.lower > other.lower { + return 1 + } + + return -1 +} diff --git a/net/ip_test.go b/net/ip_test.go new file mode 100644 index 0000000000000000000000000000000000000000..fe199241276439b2a3cc65b8bcb130be92f58ea6 --- /dev/null +++ b/net/ip_test.go @@ -0,0 +1,111 @@ +package net + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestToUint32(t *testing.T) { + tests := []struct { + name string + val uint64 + expected uint32 + }{ + { + name: "IP: 172.24.5.1", + val: 2887255297, + expected: 2887255297, + }, + { + name: "bigger than IPv4 address", + val: 2887255295 + 17179869184, + expected: 2887255295, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ip := IP{ + lower: test.val, + } + assert.Equal(t, test.expected, ip.ToUint32()) + }) + } +} + +func TestCompare(t *testing.T) { + tests := []struct { + name string + ip *IP + other *IP + expected int + }{ + { + name: "equal", + ip: &IP{ + lower: 100, + higher: 200, + }, + other: &IP{ + lower: 100, + higher: 200, + }, + expected: 0, + }, + { + name: "greater higher word", + ip: &IP{ + lower: 123, + higher: 200, + }, + other: &IP{ + lower: 456, + higher: 100, + }, + expected: 1, + }, + { + name: "lesser higher word", + ip: &IP{ + lower: 123, + higher: 100, + }, + other: &IP{ + lower: 456, + higher: 200, + }, + expected: -1, + }, + { + name: "equal higher word but lesser lower word", + ip: &IP{ + lower: 456, + higher: 100, + }, + other: &IP{ + lower: 123, + higher: 100, + }, + expected: 1, + }, + { + name: "equal higher word but lesser lower word", + ip: &IP{ + lower: 123, + higher: 100, + }, + other: &IP{ + lower: 456, + higher: 100, + }, + expected: -1, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, test.expected, test.ip.Compare(test.other)) + }) + } +} diff --git a/route/bgp_path.go b/route/bgp_path.go index 55db7045e83a50f59ac002ffa8363bbea5db538f..373888abed2644958b4bd3597d4678027287909e 100644 --- a/route/bgp_path.go +++ b/route/bgp_path.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" + bnet "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/protocols/bgp/packet" "github.com/taktv6/tflow2/convert" ) @@ -12,7 +13,7 @@ import ( // BGPPath represents a set of BGP path attributes type BGPPath struct { PathIdentifier uint32 - NextHop uint32 + NextHop bnet.IP LocalPref uint32 ASPath packet.ASPath ASPathLen uint16