Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mybee
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
mybee
Commits
f37f7967
Unverified
Commit
f37f7967
authored
May 17, 2021
by
Esad Akar
Committed by
GitHub
May 17, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: bootnodes drop peers from oversaturated bins (#1715)
parent
04e90294
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
160 additions
and
62 deletions
+160
-62
export_test.go
pkg/topology/kademlia/export_test.go
+4
-3
kademlia.go
pkg/topology/kademlia/kademlia.go
+68
-33
kademlia_test.go
pkg/topology/kademlia/kademlia_test.go
+88
-26
No files found.
pkg/topology/kademlia/export_test.go
View file @
f37f7967
...
@@ -8,4 +8,5 @@ var (
...
@@ -8,4 +8,5 @@ var (
TimeToRetry
=
&
timeToRetry
TimeToRetry
=
&
timeToRetry
SaturationPeers
=
&
saturationPeers
SaturationPeers
=
&
saturationPeers
OverSaturationPeers
=
&
overSaturationPeers
OverSaturationPeers
=
&
overSaturationPeers
BootnodeOverSaturationPeers
=
&
bootnodeOverSaturationPeers
)
)
pkg/topology/kademlia/kademlia.go
View file @
f37f7967
...
@@ -36,6 +36,7 @@ const (
...
@@ -36,6 +36,7 @@ const (
var
(
var
(
saturationPeers
=
4
saturationPeers
=
4
overSaturationPeers
=
16
overSaturationPeers
=
16
bootnodeOverSaturationPeers
=
64
shortRetry
=
30
*
time
.
Second
shortRetry
=
30
*
time
.
Second
timeToRetry
=
2
*
shortRetry
timeToRetry
=
2
*
shortRetry
broadcastBinSize
=
4
broadcastBinSize
=
4
...
@@ -44,6 +45,7 @@ var (
...
@@ -44,6 +45,7 @@ var (
var
(
var
(
errOverlayMismatch
=
errors
.
New
(
"overlay mismatch"
)
errOverlayMismatch
=
errors
.
New
(
"overlay mismatch"
)
errPruneEntry
=
errors
.
New
(
"prune entry"
)
errPruneEntry
=
errors
.
New
(
"prune entry"
)
errEmptyBin
=
errors
.
New
(
"empty bin"
)
)
)
type
binSaturationFunc
func
(
bin
uint8
,
peers
,
connected
*
pslice
.
PSlice
)
(
saturated
bool
,
oversaturated
bool
)
type
binSaturationFunc
func
(
bin
uint8
,
peers
,
connected
*
pslice
.
PSlice
)
(
saturated
bool
,
oversaturated
bool
)
...
@@ -101,7 +103,11 @@ func New(base swarm.Address,
...
@@ -101,7 +103,11 @@ func New(base swarm.Address,
logger
logging
.
Logger
,
logger
logging
.
Logger
,
o
Options
)
*
Kad
{
o
Options
)
*
Kad
{
if
o
.
SaturationFunc
==
nil
{
if
o
.
SaturationFunc
==
nil
{
o
.
SaturationFunc
=
binSaturated
os
:=
overSaturationPeers
if
o
.
BootnodeMode
{
os
=
bootnodeOverSaturationPeers
}
o
.
SaturationFunc
=
binSaturated
(
os
)
}
}
if
o
.
BitSuffixLength
==
0
{
if
o
.
BitSuffixLength
==
0
{
o
.
BitSuffixLength
=
defaultBitSuffixLength
o
.
BitSuffixLength
=
defaultBitSuffixLength
...
@@ -543,7 +549,8 @@ func (k *Kad) connectBootnodes(ctx context.Context) {
...
@@ -543,7 +549,8 @@ func (k *Kad) connectBootnodes(ctx context.Context) {
// binSaturated indicates whether a certain bin is saturated or not.
// binSaturated indicates whether a certain bin is saturated or not.
// when a bin is not saturated it means we would like to proactively
// when a bin is not saturated it means we would like to proactively
// initiate connections to other peers in the bin.
// initiate connections to other peers in the bin.
func
binSaturated
(
bin
uint8
,
peers
,
connected
*
pslice
.
PSlice
)
(
bool
,
bool
)
{
func
binSaturated
(
oversaturationAmount
int
)
binSaturationFunc
{
return
func
(
bin
uint8
,
peers
,
connected
*
pslice
.
PSlice
)
(
bool
,
bool
)
{
potentialDepth
:=
recalcDepth
(
peers
,
swarm
.
MaxPO
)
potentialDepth
:=
recalcDepth
(
peers
,
swarm
.
MaxPO
)
// short circuit for bins which are >= depth
// short circuit for bins which are >= depth
...
@@ -566,7 +573,8 @@ func binSaturated(bin uint8, peers, connected *pslice.PSlice) (bool, bool) {
...
@@ -566,7 +573,8 @@ func binSaturated(bin uint8, peers, connected *pslice.PSlice) (bool, bool) {
return
false
,
false
,
nil
return
false
,
false
,
nil
})
})
return
size
>=
saturationPeers
,
size
>=
overSaturationPeers
return
size
>=
saturationPeers
,
size
>=
oversaturationAmount
}
}
}
// recalcDepth calculates and returns the kademlia depth.
// recalcDepth calculates and returns the kademlia depth.
...
@@ -763,15 +771,26 @@ func (k *Kad) Pick(peer p2p.Peer) bool {
...
@@ -763,15 +771,26 @@ func (k *Kad) Pick(peer p2p.Peer) bool {
// Connected is called when a peer has dialed in.
// Connected is called when a peer has dialed in.
func
(
k
*
Kad
)
Connected
(
ctx
context
.
Context
,
peer
p2p
.
Peer
)
error
{
func
(
k
*
Kad
)
Connected
(
ctx
context
.
Context
,
peer
p2p
.
Peer
)
error
{
if
!
k
.
bootnode
{
// don't run this check if we're a bootnode
address
:=
peer
.
Address
po
:=
swarm
.
Proximity
(
k
.
base
.
Bytes
(),
peer
.
Address
.
Bytes
())
po
:=
swarm
.
Proximity
(
k
.
base
.
Bytes
(),
address
.
Bytes
())
if
_
,
overSaturated
:=
k
.
saturationFunc
(
po
,
k
.
knownPeers
,
k
.
connectedPeers
);
overSaturated
{
if
_
,
overSaturated
:=
k
.
saturationFunc
(
po
,
k
.
knownPeers
,
k
.
connectedPeers
);
overSaturated
{
return
topology
.
ErrOversaturated
if
k
.
bootnode
{
randPeer
,
err
:=
k
.
randomPeer
(
po
)
if
err
!=
nil
{
return
err
}
}
_
=
k
.
p2p
.
Disconnect
(
randPeer
)
goto
connected
}
}
if
err
:=
k
.
connected
(
ctx
,
peer
.
Address
);
err
!=
nil
{
return
topology
.
ErrOversaturated
}
connected
:
if
err
:=
k
.
connected
(
ctx
,
address
);
err
!=
nil
{
return
err
return
err
}
}
...
@@ -1203,3 +1222,19 @@ func randomSubset(addrs []swarm.Address, count int) ([]swarm.Address, error) {
...
@@ -1203,3 +1222,19 @@ func randomSubset(addrs []swarm.Address, count int) ([]swarm.Address, error) {
return
addrs
[
:
count
],
nil
return
addrs
[
:
count
],
nil
}
}
func
(
k
*
Kad
)
randomPeer
(
bin
uint8
)
(
swarm
.
Address
,
error
)
{
peers
:=
k
.
connectedPeers
.
BinPeers
(
bin
)
if
len
(
peers
)
==
0
{
return
swarm
.
ZeroAddress
,
errEmptyBin
}
rndIndx
,
err
:=
random
.
Int
(
random
.
Reader
,
big
.
NewInt
(
int64
(
len
(
peers
))))
if
err
!=
nil
{
return
swarm
.
ZeroAddress
,
err
}
return
peers
[
rndIndx
.
Int64
()],
nil
}
pkg/topology/kademlia/kademlia_test.go
View file @
f37f7967
...
@@ -537,6 +537,60 @@ func TestOversaturationBootnode(t *testing.T) {
...
@@ -537,6 +537,60 @@ func TestOversaturationBootnode(t *testing.T) {
}
}
}
}
func
TestBootnodeMaxConnections
(
t
*
testing
.
T
)
{
defer
func
(
p
int
)
{
*
kademlia
.
BootnodeOverSaturationPeers
=
p
}(
*
kademlia
.
BootnodeOverSaturationPeers
)
*
kademlia
.
BootnodeOverSaturationPeers
=
4
var
(
conns
int32
// how many connect calls were made to the p2p mock
base
,
kad
,
ab
,
_
,
signer
=
newTestKademlia
(
&
conns
,
nil
,
kademlia
.
Options
{
BootnodeMode
:
true
})
)
kad
.
SetRadius
(
swarm
.
MaxPO
)
// don't use radius for checks
if
err
:=
kad
.
Start
(
context
.
Background
());
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
kad
.
Close
()
// Add maximum accepted number of peers up until bin 5 without problems
for
i
:=
0
;
i
<
6
;
i
++
{
for
j
:=
0
;
j
<
*
kademlia
.
BootnodeOverSaturationPeers
;
j
++
{
addr
:=
test
.
RandomAddressAt
(
base
,
i
)
// if error is not nil as specified, connectOne goes fatal
connectOne
(
t
,
signer
,
kad
,
ab
,
addr
,
nil
)
}
// see depth is limited to currently added peers proximity
kDepth
(
t
,
kad
,
i
)
}
// see depth is 5
kDepth
(
t
,
kad
,
5
)
depth
:=
5
outSideDepthPeers
:=
5
for
k
:=
0
;
k
<
depth
;
k
++
{
// further connections should succeed outside of depth
for
l
:=
0
;
l
<
outSideDepthPeers
;
l
++
{
addr
:=
test
.
RandomAddressAt
(
base
,
k
)
// if error is not as specified, connectOne goes fatal
connectOne
(
t
,
signer
,
kad
,
ab
,
addr
,
nil
)
// check that pick works correctly
if
!
kad
.
Pick
(
p2p
.
Peer
{
Address
:
addr
})
{
t
.
Fatal
(
"should pick the peer but didnt"
)
}
}
}
got
:=
atomic
.
LoadInt32
(
&
conns
)
want
:=
-
int32
(
depth
*
outSideDepthPeers
)
if
got
!=
want
{
t
.
Fatalf
(
"got %d, want %d"
,
got
,
want
)
}
}
// TestNotifierHooks tests that the Connected/Disconnected hooks
// TestNotifierHooks tests that the Connected/Disconnected hooks
// result in the correct behavior once called.
// result in the correct behavior once called.
func
TestNotifierHooks
(
t
*
testing
.
T
)
{
func
TestNotifierHooks
(
t
*
testing
.
T
)
{
...
@@ -1055,7 +1109,8 @@ func newTestKademlia(connCounter, failedConnCounter *int32, kadOpts kademlia.Opt
...
@@ -1055,7 +1109,8 @@ func newTestKademlia(connCounter, failedConnCounter *int32, kadOpts kademlia.Opt
}
}
func
p2pMock
(
ab
addressbook
.
Interface
,
signer
beeCrypto
.
Signer
,
counter
,
failedCounter
*
int32
)
p2p
.
Service
{
func
p2pMock
(
ab
addressbook
.
Interface
,
signer
beeCrypto
.
Signer
,
counter
,
failedCounter
*
int32
)
p2p
.
Service
{
p2ps
:=
p2pmock
.
New
(
p2pmock
.
WithConnectFunc
(
func
(
ctx
context
.
Context
,
addr
ma
.
Multiaddr
)
(
*
bzz
.
Address
,
error
)
{
p2ps
:=
p2pmock
.
New
(
p2pmock
.
WithConnectFunc
(
func
(
ctx
context
.
Context
,
addr
ma
.
Multiaddr
)
(
*
bzz
.
Address
,
error
)
{
if
addr
.
Equal
(
nonConnectableAddress
)
{
if
addr
.
Equal
(
nonConnectableAddress
)
{
_
=
atomic
.
AddInt32
(
failedCounter
,
1
)
_
=
atomic
.
AddInt32
(
failedCounter
,
1
)
return
nil
,
errors
.
New
(
"non reachable node"
)
return
nil
,
errors
.
New
(
"non reachable node"
)
...
@@ -1086,7 +1141,14 @@ func p2pMock(ab addressbook.Interface, signer beeCrypto.Signer, counter, failedC
...
@@ -1086,7 +1141,14 @@ func p2pMock(ab addressbook.Interface, signer beeCrypto.Signer, counter, failedC
}
}
return
bzzAddr
,
nil
return
bzzAddr
,
nil
}))
}),
p2pmock
.
WithDisconnectFunc
(
func
(
swarm
.
Address
)
error
{
if
counter
!=
nil
{
_
=
atomic
.
AddInt32
(
counter
,
-
1
)
}
return
nil
}),
)
return
p2ps
return
p2ps
}
}
...
...
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