Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
p2p
go-cidranger
Commits
15fff359
Commit
15fff359
authored
Aug 21, 2020
by
Steven Allen
Committed by
Adin Schmahmann
Aug 25, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Reduce network size & allocations
parent
8a304357
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
82 additions
and
59 deletions
+82
-59
cidranger_test.go
cidranger_test.go
+2
-2
net/ip.go
net/ip.go
+66
-41
net/ip_test.go
net/ip_test.go
+13
-14
trie.go
trie.go
+1
-2
No files found.
cidranger_test.go
View file @
15fff359
...
@@ -107,10 +107,10 @@ func testCoversNetworksAgainstBase(t *testing.T, iterations int, netGen networkG
...
@@ -107,10 +107,10 @@ func testCoversNetworksAgainstBase(t *testing.T, iterations int, netGen networkG
for
i
:=
0
;
i
<
iterations
;
i
++
{
for
i
:=
0
;
i
<
iterations
;
i
++
{
network
:=
netGen
()
network
:=
netGen
()
expected
,
err
:=
baseRanger
.
CoveredNetworks
(
network
.
IPNet
)
expected
,
err
:=
baseRanger
.
CoveredNetworks
(
network
.
IPNet
()
)
assert
.
NoError
(
t
,
err
)
assert
.
NoError
(
t
,
err
)
for
_
,
ranger
:=
range
rangers
{
for
_
,
ranger
:=
range
rangers
{
actual
,
err
:=
ranger
.
CoveredNetworks
(
network
.
IPNet
)
actual
,
err
:=
ranger
.
CoveredNetworks
(
network
.
IPNet
()
)
assert
.
NoError
(
t
,
err
)
assert
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
len
(
expected
),
len
(
actual
))
assert
.
Equal
(
t
,
len
(
expected
),
len
(
actual
))
for
_
,
network
:=
range
actual
{
for
_
,
network
:=
range
actual
{
...
...
net/ip.go
View file @
15fff359
...
@@ -170,63 +170,82 @@ func (n NetworkNumber) LeastCommonBitPosition(n1 NetworkNumber) (uint, error) {
...
@@ -170,63 +170,82 @@ func (n NetworkNumber) LeastCommonBitPosition(n1 NetworkNumber) (uint, error) {
// Network represents a block of network numbers, also known as CIDR.
// Network represents a block of network numbers, also known as CIDR.
type
Network
struct
{
type
Network
struct
{
net
.
IPNet
Number
NetworkNumber
Number
NetworkNumber
Mask
NetworkNumberMask
Mask
NetworkNumberMask
}
}
// NewNetwork returns Network built using given net.IPNet.
// NewNetwork returns Network built using given net.IPNet.
func
NewNetwork
(
ipNet
net
.
IPNet
)
Network
{
func
NewNetwork
(
ipNet
net
.
IPNet
)
Network
{
ones
,
_
:=
ipNet
.
Mask
.
Size
()
return
Network
{
return
Network
{
IPNet
:
ipNet
,
Number
:
NewNetworkNumber
(
ipNet
.
IP
),
Number
:
NewNetworkNumber
(
ipNet
.
IP
),
Mask
:
NetworkNumberMask
(
NewNetworkNumber
(
net
.
IP
(
ipNet
.
Mask
))
),
Mask
:
NetworkNumberMask
(
ones
),
}
}
}
}
// Masked returns a new network conforming to new mask.
// Masked returns a new network conforming to new mask.
func
(
n
Network
)
Masked
(
ones
int
)
Network
{
func
(
n
Network
)
Masked
(
ones
int
)
Network
{
mask
:=
net
.
CIDRMask
(
ones
,
len
(
n
.
Number
)
*
BitsPerUint32
)
mask
:=
NetworkNumberMask
(
ones
)
return
NewNetwork
(
net
.
IPNet
{
return
Network
{
IP
:
n
.
IP
.
Mask
(
mask
),
Number
:
mask
.
Mask
(
n
.
Number
),
Mask
:
mask
,
Mask
:
mask
,
})
}
}
func
sub
(
a
,
b
uint8
)
uint8
{
res
:=
a
-
b
if
res
>
a
{
res
=
0
}
return
res
}
func
mask
(
m
NetworkNumberMask
)
(
mask1
,
mask2
,
mask3
,
mask4
uint32
)
{
// We're relying on overflow here.
const
ones
uint32
=
0xFFFFFFFF
mask1
=
ones
<<
sub
(
1
*
32
,
uint8
(
m
))
mask2
=
ones
<<
sub
(
2
*
32
,
uint8
(
m
))
mask3
=
ones
<<
sub
(
3
*
32
,
uint8
(
m
))
mask4
=
ones
<<
sub
(
4
*
32
,
uint8
(
m
))
return
}
}
// Contains returns true if NetworkNumber is in range of Network, false
// Contains returns true if NetworkNumber is in range of Network, false
// otherwise.
// otherwise.
func
(
n
Network
)
Contains
(
nn
NetworkNumber
)
bool
{
func
(
n
Network
)
Contains
(
nn
NetworkNumber
)
bool
{
if
len
(
n
.
Mask
)
!=
len
(
nn
)
{
if
len
(
n
.
Number
)
!=
len
(
nn
)
{
return
false
return
false
}
}
if
nn
[
0
]
&
n
.
Mask
[
0
]
!=
n
.
Number
[
0
]
{
const
ones
uint32
=
0xFFFFFFFF
mask1
,
mask2
,
mask3
,
mask4
:=
mask
(
n
.
Mask
)
switch
len
(
n
.
Number
)
{
case
IPv4Uint32Count
:
return
nn
[
0
]
&
mask1
==
n
.
Number
[
0
]
case
IPv6Uint32Count
:
return
nn
[
0
]
&
mask1
==
n
.
Number
[
0
]
&&
nn
[
1
]
&
mask2
==
n
.
Number
[
1
]
&&
nn
[
2
]
&
mask3
==
n
.
Number
[
2
]
&&
nn
[
3
]
&
mask4
==
n
.
Number
[
3
]
default
:
return
false
return
false
}
}
if
len
(
nn
)
==
IPv6Uint32Count
{
return
nn
[
1
]
&
n
.
Mask
[
1
]
==
n
.
Number
[
1
]
&&
nn
[
2
]
&
n
.
Mask
[
2
]
==
n
.
Number
[
2
]
&&
nn
[
3
]
&
n
.
Mask
[
3
]
==
n
.
Number
[
3
]
}
return
true
}
}
// Contains returns true if Network covers o, false otherwise
// Contains returns true if Network covers o, false otherwise
func
(
n
Network
)
Covers
(
o
Network
)
bool
{
func
(
n
Network
)
Covers
(
o
Network
)
bool
{
if
len
(
n
.
Number
)
!=
len
(
o
.
Number
)
{
return
n
.
Contains
(
o
.
Number
)
&&
n
.
Mask
<=
o
.
Mask
return
false
}
nMaskSize
,
_
:=
n
.
IPNet
.
Mask
.
Size
()
oMaskSize
,
_
:=
o
.
IPNet
.
Mask
.
Size
()
return
n
.
Contains
(
o
.
Number
)
&&
nMaskSize
<=
oMaskSize
}
}
// LeastCommonBitPosition returns the smallest position of the preceding common
// LeastCommonBitPosition returns the smallest position of the preceding common
// bits of the 2 networks, and returns an error ErrNoGreatestCommonBit
// bits of the 2 networks, and returns an error ErrNoGreatestCommonBit
// if the two network number diverges from the first bit.
// if the two network number diverges from the first bit.
func
(
n
Network
)
LeastCommonBitPosition
(
n1
Network
)
(
uint
,
error
)
{
func
(
n
Network
)
LeastCommonBitPosition
(
n1
Network
)
(
uint
,
error
)
{
maskSize
,
_
:=
n
.
IPNet
.
Mask
.
Size
()
maskSize
:=
n
.
Mask
if
maskSize1
,
_
:=
n1
.
IPNet
.
Mask
.
Size
();
maskSize1
<
maskSize
{
if
n1
.
Mask
<
n
.
Mask
{
maskSize
=
maskSize1
maskSize
=
n1
.
Mask
}
}
maskPosition
:=
len
(
n1
.
Number
)
*
BitsPerUint32
-
maskSize
maskPosition
:=
len
(
n1
.
Number
)
*
BitsPerUint32
-
int
(
maskSize
)
lcb
,
err
:=
n
.
Number
.
LeastCommonBitPosition
(
n1
.
Number
)
lcb
,
err
:=
n
.
Number
.
LeastCommonBitPosition
(
n1
.
Number
)
if
err
!=
nil
{
if
err
!=
nil
{
return
0
,
err
return
0
,
err
...
@@ -236,32 +255,38 @@ func (n Network) LeastCommonBitPosition(n1 Network) (uint, error) {
...
@@ -236,32 +255,38 @@ func (n Network) LeastCommonBitPosition(n1 Network) (uint, error) {
// Equal is the equality test for 2 networks.
// Equal is the equality test for 2 networks.
func
(
n
Network
)
Equal
(
n1
Network
)
bool
{
func
(
n
Network
)
Equal
(
n1
Network
)
bool
{
nones
,
nbits
:=
n
.
IPNet
.
Mask
.
Size
()
return
n
.
Number
.
Equal
(
n1
.
Number
)
&&
n
.
Mask
==
n1
.
Mask
n1ones
,
n1bits
:=
n1
.
IPNet
.
Mask
.
Size
()
return
nones
==
n1ones
&&
nbits
==
n1bits
&&
n
.
IPNet
.
IP
.
Equal
(
n1
.
IPNet
.
IP
)
}
}
func
(
n
Network
)
String
()
string
{
func
(
n
Network
)
String
()
string
{
return
n
.
IPNet
.
String
()
return
fmt
.
Sprintf
(
"%s/%d"
,
n
.
Number
.
ToIP
(),
n
.
Mask
)
}
func
(
n
Network
)
IPNet
()
net
.
IPNet
{
return
net
.
IPNet
{
IP
:
n
.
Number
.
ToIP
(),
Mask
:
net
.
CIDRMask
(
int
(
n
.
Mask
),
len
(
n
.
Number
)
*
32
),
}
}
}
// NetworkNumberMask is an IP address.
// NetworkNumberMask is an IP address.
type
NetworkNumberMask
NetworkNumber
type
NetworkNumberMask
int
// Mask returns a new masked NetworkNumber from given NetworkNumber.
// Mask returns a new masked NetworkNumber from given NetworkNumber.
func
(
m
NetworkNumberMask
)
Mask
(
n
NetworkNumber
)
(
NetworkNumber
,
error
)
{
func
(
m
NetworkNumberMask
)
Mask
(
n
NetworkNumber
)
NetworkNumber
{
if
len
(
m
)
!=
len
(
n
)
{
mask1
,
mask2
,
mask3
,
mask4
:=
mask
(
m
)
return
nil
,
ErrVersionMismatch
}
result
:=
make
(
NetworkNumber
,
len
(
n
))
result
:=
make
(
NetworkNumber
,
len
(
m
))
switch
len
(
n
)
{
result
[
0
]
=
m
[
0
]
&
n
[
0
]
case
IPv4Uint32Count
:
if
len
(
m
)
==
IPv6Uint32Count
{
result
[
0
]
=
n
[
0
]
&
mask1
result
[
1
]
=
m
[
1
]
&
n
[
1
]
case
IPv6Uint32Count
:
result
[
2
]
=
m
[
2
]
&
n
[
2
]
result
[
0
]
=
n
[
0
]
&
mask1
result
[
3
]
=
m
[
3
]
&
n
[
3
]
result
[
1
]
=
n
[
1
]
&
mask2
result
[
2
]
=
n
[
2
]
&
mask3
result
[
3
]
=
n
[
3
]
&
mask4
}
}
return
result
,
nil
return
result
}
}
// NextIP returns the next sequential ip.
// NextIP returns the next sequential ip.
...
...
net/ip_test.go
View file @
15fff359
...
@@ -220,9 +220,11 @@ func TestNewNetwork(t *testing.T) {
...
@@ -220,9 +220,11 @@ func TestNewNetwork(t *testing.T) {
_
,
ipNet
,
_
:=
net
.
ParseCIDR
(
"192.128.0.0/24"
)
_
,
ipNet
,
_
:=
net
.
ParseCIDR
(
"192.128.0.0/24"
)
n
:=
NewNetwork
(
*
ipNet
)
n
:=
NewNetwork
(
*
ipNet
)
assert
.
Equal
(
t
,
*
ipNet
,
n
.
IPNet
)
newIPNet
:=
n
.
IPNet
()
assert
.
True
(
t
,
ipNet
.
IP
.
Equal
(
newIPNet
.
IP
))
assert
.
Equal
(
t
,
ipNet
.
Mask
,
newIPNet
.
Mask
)
assert
.
Equal
(
t
,
NetworkNumber
{
3229614080
},
n
.
Number
)
assert
.
Equal
(
t
,
NetworkNumber
{
3229614080
},
n
.
Number
)
assert
.
Equal
(
t
,
NetworkNumberMask
{
math
.
MaxUint32
-
uint32
(
math
.
MaxUint8
)}
,
n
.
Mask
)
assert
.
Equal
(
t
,
NetworkNumberMask
(
24
)
,
n
.
Mask
)
}
}
func
TestNetworkMasked
(
t
*
testing
.
T
)
{
func
TestNetworkMasked
(
t
*
testing
.
T
)
{
...
@@ -245,7 +247,7 @@ func TestNetworkMasked(t *testing.T) {
...
@@ -245,7 +247,7 @@ func TestNetworkMasked(t *testing.T) {
_
,
expected
,
_
:=
net
.
ParseCIDR
(
testcase
.
maskedNetwork
)
_
,
expected
,
_
:=
net
.
ParseCIDR
(
testcase
.
maskedNetwork
)
n1
:=
NewNetwork
(
*
network
)
n1
:=
NewNetwork
(
*
network
)
e1
:=
NewNetwork
(
*
expected
)
e1
:=
NewNetwork
(
*
expected
)
assert
.
True
(
t
,
e1
.
String
()
==
n1
.
Masked
(
testcase
.
mask
)
.
String
())
assert
.
Equal
(
t
,
e1
.
String
()
,
n1
.
Masked
(
testcase
.
mask
)
.
String
())
}
}
}
}
...
@@ -377,22 +379,19 @@ func TestMask(t *testing.T) {
...
@@ -377,22 +379,19 @@ func TestMask(t *testing.T) {
mask
NetworkNumberMask
mask
NetworkNumberMask
ip
NetworkNumber
ip
NetworkNumber
masked
NetworkNumber
masked
NetworkNumber
err
error
name
string
name
string
}{
}{
{
NetworkNumberMask
{
math
.
MaxUint32
},
NetworkNumber
{
math
.
MaxUint32
},
NetworkNumber
{
math
.
MaxUint32
},
nil
,
"nop IPv4 mask"
},
{
32
,
NetworkNumber
{
math
.
MaxUint32
},
NetworkNumber
{
math
.
MaxUint32
},
"nop IPv4 mask"
},
{
NetworkNumberMask
{
math
.
MaxUint32
-
math
.
MaxUint16
},
NetworkNumber
{
math
.
MaxUint16
+
1
},
NetworkNumber
{
math
.
MaxUint16
+
1
},
nil
,
"nop IPv4 mask"
},
{
16
,
NetworkNumber
{
math
.
MaxUint16
+
1
},
NetworkNumber
{
math
.
MaxUint16
+
1
},
"nop IPv4 mask"
},
{
NetworkNumberMask
{
math
.
MaxUint32
-
math
.
MaxUint16
},
NetworkNumber
{
math
.
MaxUint32
},
NetworkNumber
{
math
.
MaxUint32
-
math
.
MaxUint16
},
nil
,
"IPv4 masked"
},
{
16
,
NetworkNumber
{
math
.
MaxUint32
},
NetworkNumber
{
math
.
MaxUint32
-
math
.
MaxUint16
},
"IPv4 masked"
},
{
NetworkNumberMask
{
math
.
MaxUint32
,
0
,
0
,
0
},
NetworkNumber
{
math
.
MaxUint32
,
0
,
0
,
0
},
NetworkNumber
{
math
.
MaxUint32
,
0
,
0
,
0
},
nil
,
"nop IPv6 mask"
},
{
96
,
NetworkNumber
{
math
.
MaxUint32
,
0
,
0
,
0
},
NetworkNumber
{
math
.
MaxUint32
,
0
,
0
,
0
},
"nop IPv6 mask"
},
{
NetworkNumberMask
{
math
.
MaxUint32
-
math
.
MaxUint16
,
0
,
0
,
0
},
NetworkNumber
{
math
.
MaxUint16
+
1
,
0
,
0
,
0
},
NetworkNumber
{
math
.
MaxUint16
+
1
,
0
,
0
,
0
},
nil
,
"nop IPv6 mask"
},
{
16
,
NetworkNumber
{
math
.
MaxUint16
+
1
,
0
,
0
,
0
},
NetworkNumber
{
math
.
MaxUint16
+
1
,
0
,
0
,
0
},
"nop IPv6 mask"
},
{
NetworkNumberMask
{
math
.
MaxUint32
-
math
.
MaxUint16
,
0
,
0
,
0
},
NetworkNumber
{
math
.
MaxUint32
,
0
,
0
,
0
},
NetworkNumber
{
math
.
MaxUint32
-
math
.
MaxUint16
,
0
,
0
,
0
},
nil
,
"IPv6 masked"
},
{
16
,
NetworkNumber
{
math
.
MaxUint32
,
0
,
0
,
0
},
NetworkNumber
{
math
.
MaxUint32
-
math
.
MaxUint16
,
0
,
0
,
0
},
"IPv6 masked"
},
{
NetworkNumberMask
{
math
.
MaxUint32
},
NetworkNumber
{
math
.
MaxUint32
,
0
},
nil
,
ErrVersionMismatch
,
"Version mismatch"
},
}
}
for
_
,
tc
:=
range
cases
{
for
_
,
tc
:=
range
cases
{
t
.
Run
(
tc
.
name
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
tc
.
name
,
func
(
t
*
testing
.
T
)
{
masked
,
err
:=
tc
.
mask
.
Mask
(
tc
.
ip
)
masked
:=
tc
.
mask
.
Mask
(
tc
.
ip
)
assert
.
Equal
(
t
,
tc
.
masked
,
masked
)
assert
.
Equal
(
t
,
tc
.
masked
,
masked
,
tc
.
name
)
assert
.
Equal
(
t
,
tc
.
err
,
err
)
})
})
}
}
}
}
...
...
trie.go
View file @
15fff359
...
@@ -84,8 +84,7 @@ func newPathprefixTrie(network rnet.Network, numBitsSkipped uint) *prefixTrie {
...
@@ -84,8 +84,7 @@ func newPathprefixTrie(network rnet.Network, numBitsSkipped uint) *prefixTrie {
}
}
func
newEntryTrie
(
network
rnet
.
Network
,
entry
RangerEntry
)
*
prefixTrie
{
func
newEntryTrie
(
network
rnet
.
Network
,
entry
RangerEntry
)
*
prefixTrie
{
ones
,
_
:=
network
.
IPNet
.
Mask
.
Size
()
leaf
:=
newPathprefixTrie
(
network
,
uint
(
network
.
Mask
))
leaf
:=
newPathprefixTrie
(
network
,
uint
(
ones
))
leaf
.
entry
=
entry
leaf
.
entry
=
entry
return
leaf
return
leaf
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment