mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
swarm/network: saturation with higher MinBinSize
This commit is contained in:
parent
99df803e89
commit
b64be4f201
3 changed files with 51 additions and 16 deletions
|
|
@ -709,7 +709,7 @@ func (k *Kademlia) saturation() int {
|
||||||
func (k *Kademlia) getUnsaturatedBins(peersPerBin []int, depth int) []int {
|
func (k *Kademlia) getUnsaturatedBins(peersPerBin []int, depth int) []int {
|
||||||
// depth could be calculated from k but as this is called from `Healthy()`,
|
// depth could be calculated from k but as this is called from `Healthy()`,
|
||||||
// the depth has already been calculated so we can require it as a parameter
|
// the depth has already been calculated so we can require it as a parameter
|
||||||
connectedPeersPerBin := make([]int, depth)
|
unsaturatedBins := make([]int, 0)
|
||||||
k.conns.EachBin(k.base, Pof, 0, func(po, size int, f func(func(val pot.Val) bool) bool) bool {
|
k.conns.EachBin(k.base, Pof, 0, func(po, size int, f func(func(val pot.Val) bool) bool) bool {
|
||||||
|
|
||||||
if po >= depth {
|
if po >= depth {
|
||||||
|
|
@ -717,19 +717,13 @@ func (k *Kademlia) getUnsaturatedBins(peersPerBin []int, depth int) []int {
|
||||||
}
|
}
|
||||||
log.Trace("peers per bin", "peersPerBin[po]", peersPerBin[po], "po", po)
|
log.Trace("peers per bin", "peersPerBin[po]", peersPerBin[po], "po", po)
|
||||||
// if there are actually peers in the PeerPot who can fulfill k.MinBinSize
|
// if there are actually peers in the PeerPot who can fulfill k.MinBinSize
|
||||||
if peersPerBin[po] >= k.MinBinSize {
|
if size < k.MinBinSize && size < peersPerBin[po] {
|
||||||
log.Trace("connections for po", "po", po, "size", size)
|
log.Trace("connections for po", "po", po, "size", size)
|
||||||
connectedPeersPerBin[po] += size
|
unsaturatedBins = append(unsaturatedBins, po)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
unsaturatedBins := make([]int, 0)
|
|
||||||
for i := 0; i < len(connectedPeersPerBin); i++ {
|
|
||||||
if connectedPeersPerBin[i] > 0 && connectedPeersPerBin[i] < k.MinBinSize {
|
|
||||||
unsaturatedBins = append(unsaturatedBins, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.Trace("list of unsaturated bins", "unsaturatedBins", unsaturatedBins)
|
log.Trace("list of unsaturated bins", "unsaturatedBins", unsaturatedBins)
|
||||||
return unsaturatedBins
|
return unsaturatedBins
|
||||||
}
|
}
|
||||||
|
|
@ -822,7 +816,7 @@ type Health struct {
|
||||||
Hive string
|
Hive string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Healthy reports the health state of the kademlia connectivity
|
// GetHealthInfo reports the health state of the kademlia connectivity
|
||||||
//
|
//
|
||||||
// The PeerPot argument provides an all-knowing view of the network
|
// The PeerPot argument provides an all-knowing view of the network
|
||||||
// The resulting Health object is a result of comparisons between
|
// The resulting Health object is a result of comparisons between
|
||||||
|
|
@ -830,7 +824,7 @@ type Health struct {
|
||||||
// what SHOULD it have been when we take all we know about the network into consideration.
|
// what SHOULD it have been when we take all we know about the network into consideration.
|
||||||
//
|
//
|
||||||
// used for testing only
|
// used for testing only
|
||||||
func (k *Kademlia) Healthy(pp *PeerPot) *Health {
|
func (k *Kademlia) GetHealthInfo(pp *PeerPot) *Health {
|
||||||
k.lock.RLock()
|
k.lock.RLock()
|
||||||
defer k.lock.RUnlock()
|
defer k.lock.RUnlock()
|
||||||
if len(pp.NNSet) < k.NeighbourhoodSize {
|
if len(pp.NNSet) < k.NeighbourhoodSize {
|
||||||
|
|
@ -839,6 +833,7 @@ func (k *Kademlia) Healthy(pp *PeerPot) *Health {
|
||||||
gotnn, countgotnn, culpritsgotnn := k.connectedNeighbours(pp.NNSet)
|
gotnn, countgotnn, culpritsgotnn := k.connectedNeighbours(pp.NNSet)
|
||||||
knownn, countknownn, culpritsknownn := k.knowNeighbours(pp.NNSet)
|
knownn, countknownn, culpritsknownn := k.knowNeighbours(pp.NNSet)
|
||||||
depth := depthForPot(k.conns, k.NeighbourhoodSize, k.base)
|
depth := depthForPot(k.conns, k.NeighbourhoodSize, k.base)
|
||||||
|
|
||||||
// check saturation
|
// check saturation
|
||||||
unsaturatedBins := k.getUnsaturatedBins(pp.PeersPerBin, depth)
|
unsaturatedBins := k.getUnsaturatedBins(pp.PeersPerBin, depth)
|
||||||
saturated := len(unsaturatedBins) == 0
|
saturated := len(unsaturatedBins) == 0
|
||||||
|
|
@ -856,12 +851,12 @@ func (k *Kademlia) Healthy(pp *PeerPot) *Health {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsHealthyStrict return the strict interpretation of `Healthy` given a `Health` struct
|
// Healthy return the strict interpretation of `Healthy` given a `Health` struct
|
||||||
// definition of strict health: all conditions must be true:
|
// definition of strict health: all conditions must be true:
|
||||||
// - we at least know one peer
|
// - we at least know one peer
|
||||||
// - we know all neighbors
|
// - we know all neighbors
|
||||||
// - we are connected to all known neighbors
|
// - we are connected to all known neighbors
|
||||||
// - it is saturated
|
// - it is saturated
|
||||||
func (h *Health) IsHealthyStrict() bool {
|
func (h *Health) Healthy() bool {
|
||||||
return h.KnowNN && h.ConnectNN && h.CountKnowNN > 0 && h.Saturated
|
return h.KnowNN && h.ConnectNN && h.CountKnowNN > 0 && h.Saturated
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,46 @@ func TestNeighbourhoodDepth(t *testing.T) {
|
||||||
testNum++
|
testNum++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestHighMinBinSize tests that the saturation function also works
|
||||||
|
// if MinBinSize is > 2, the connection count is < k.MinBinSize
|
||||||
|
// and there are more peers available than connected
|
||||||
|
func TestHighMinBinSize(t *testing.T) {
|
||||||
|
// a function to test for different MinBinSize values
|
||||||
|
testKad := func(minBinSize int) {
|
||||||
|
// create a test kademlia
|
||||||
|
tk := newTestKademlia(t, "11111111")
|
||||||
|
// set its MinBinSize to desired value
|
||||||
|
tk.KadParams.MinBinSize = minBinSize
|
||||||
|
|
||||||
|
// add a couple of peers (so we have NN and depth)
|
||||||
|
tk.On("00000000") // bin 0
|
||||||
|
tk.On("11100000") // bin 3
|
||||||
|
tk.On("11110000") // bin 4
|
||||||
|
|
||||||
|
first := "10000000" // add a first peer at bin 1
|
||||||
|
tk.Register(first) // register it
|
||||||
|
// we now have one registered peer at bin 1;
|
||||||
|
// iterate and connect one peer at each iteration;
|
||||||
|
// should be unhealthy until at minBinSize - 1
|
||||||
|
// we connect the unconnected but registered peer
|
||||||
|
for i := 1; i < minBinSize; i++ {
|
||||||
|
peer := fmt.Sprintf("1000%b", 8|i)
|
||||||
|
tk.On(peer)
|
||||||
|
if i == minBinSize-1 {
|
||||||
|
tk.On(first)
|
||||||
|
tk.checkHealth(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tk.checkHealth(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// test MinBinSizes of 3 to 5
|
||||||
|
testMinBinSizes := []int{3, 4, 5}
|
||||||
|
for _, k := range testMinBinSizes {
|
||||||
|
testKad(k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestHealthStrict tests the simplest definition of health
|
// TestHealthStrict tests the simplest definition of health
|
||||||
// Which means whether we are connected to all neighbors we know of
|
// Which means whether we are connected to all neighbors we know of
|
||||||
func TestHealthStrict(t *testing.T) {
|
func TestHealthStrict(t *testing.T) {
|
||||||
|
|
@ -295,13 +335,13 @@ func (tk *testKademlia) checkHealth(expectHealthy bool) {
|
||||||
})
|
})
|
||||||
|
|
||||||
pp := NewPeerPotMap(tk.NeighbourhoodSize, addrs)
|
pp := NewPeerPotMap(tk.NeighbourhoodSize, addrs)
|
||||||
healthParams := tk.Healthy(pp[kid])
|
healthParams := tk.GetHealthInfo(pp[kid])
|
||||||
|
|
||||||
// definition of health, all conditions but be true:
|
// definition of health, all conditions but be true:
|
||||||
// - we at least know one peer
|
// - we at least know one peer
|
||||||
// - we know all neighbors
|
// - we know all neighbors
|
||||||
// - we are connected to all known neighbors
|
// - we are connected to all known neighbors
|
||||||
health := healthParams.IsHealthyStrict()
|
health := healthParams.Healthy()
|
||||||
if expectHealthy != health {
|
if expectHealthy != health {
|
||||||
tk.t.Fatalf("expected kademlia health %v, is %v\n%v", expectHealthy, health, tk.String())
|
tk.t.Fatalf("expected kademlia health %v, is %v\n%v", expectHealthy, health, tk.String())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ func (s *Simulation) WaitTillHealthy(ctx context.Context) (ill map[enode.ID]*net
|
||||||
addr := common.Bytes2Hex(k.BaseAddr())
|
addr := common.Bytes2Hex(k.BaseAddr())
|
||||||
pp := ppmap[addr]
|
pp := ppmap[addr]
|
||||||
//call Healthy RPC
|
//call Healthy RPC
|
||||||
h := k.Healthy(pp)
|
h := k.GetHealthInfo(pp)
|
||||||
//print info
|
//print info
|
||||||
log.Debug(k.String())
|
log.Debug(k.String())
|
||||||
log.Debug("kademlia", "connectNN", h.ConnectNN, "knowNN", h.KnowNN)
|
log.Debug("kademlia", "connectNN", h.ConnectNN, "knowNN", h.KnowNN)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue