Skip to content

Commit

Permalink
swarm: use happy eyeballs ranking for TCP dials
Browse files Browse the repository at this point in the history
  • Loading branch information
sukunrt committed Sep 15, 2023
1 parent 371ded3 commit 62b878b
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 16 deletions.
43 changes: 37 additions & 6 deletions p2p/net/swarm/dial_ranker.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ func getAddrDelay(addrs []ma.Multiaddr, tcpDelay time.Duration, quicDelay time.D
sort.Slice(addrs, func(i, j int) bool { return score(addrs[i]) < score(addrs[j]) })

// If the first address is (QUIC, IPv6), make the second address (QUIC, IPv4).
happyEyeballs := false
happyEyeballsQUIC := false
happyEyeballsTCP := false
if len(addrs) > 0 {
if isQUICAddr(addrs[0]) && isProtocolAddr(addrs[0], ma.P_IP6) {
for i := 1; i < len(addrs); i++ {
Expand All @@ -103,7 +104,29 @@ func getAddrDelay(addrs []ma.Multiaddr, tcpDelay time.Duration, quicDelay time.D
copy(addrs[2:], addrs[1:i])
addrs[1] = a
}
happyEyeballs = true
happyEyeballsQUIC = true
break
}
}
}
// idx is the index of the first tcp address
idx := 0
for i, a := range addrs {
if isProtocolAddr(a, ma.P_TCP) {
idx = i
break
}
}
if isProtocolAddr(addrs[idx], ma.P_TCP) && isProtocolAddr(addrs[idx], ma.P_IP6) {
for i := idx + 1; i < len(addrs); i++ {
if isProtocolAddr(addrs[i], ma.P_TCP) && isProtocolAddr(addrs[i], ma.P_IP4) {
// make IPv4 address the second element
if i > idx+1 {
a := addrs[i]
copy(addrs[idx+2:], addrs[idx+1:i])
addrs[idx+1] = a
}
happyEyeballsTCP = true
break
}
}
Expand All @@ -112,24 +135,32 @@ func getAddrDelay(addrs []ma.Multiaddr, tcpDelay time.Duration, quicDelay time.D

res := make([]network.AddrDelay, 0, len(addrs))

var tcpIdx int
var totalTCPDelay time.Duration
for i, addr := range addrs {
var delay time.Duration
switch {
case isQUICAddr(addr):
// For QUIC addresses we dial an IPv6 address, then after quicDelay an IPv4
// address, then after quicDelay we dial rest of the addresses.
if i == 1 {
delay = quicDelay
}
if i > 1 && happyEyeballs {
if i > 1 && happyEyeballsQUIC {
delay = 2 * quicDelay
} else if i > 1 {
delay = quicDelay
}
totalTCPDelay = delay + tcpDelay
case isProtocolAddr(addr, ma.P_TCP):
delay = totalTCPDelay
if tcpIdx == 1 {
delay = tcpDelay
}
if tcpIdx > 1 && happyEyeballsTCP {
delay = 2 * tcpDelay
} else if tcpIdx > 1 {
delay = tcpDelay
}
tcpIdx++
delay += totalTCPDelay
}
res = append(res, network.AddrDelay{Addr: addr, Delay: offset + delay})
}
Expand Down
24 changes: 14 additions & 10 deletions p2p/net/swarm/dial_ranker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ func TestDelayRankerTCPDelay(t *testing.T) {
t1 := ma.StringCast("/ip4/1.2.3.5/tcp/1/")
t1v6 := ma.StringCast("/ip6/1::2/tcp/1")
t2 := ma.StringCast("/ip4/1.2.3.4/tcp/2")
t3 := ma.StringCast("/ip6/1::3/tcp/3")

testCase := []struct {
name string
Expand All @@ -169,34 +170,37 @@ func TestDelayRankerTCPDelay(t *testing.T) {
}{
{
name: "quic-with-tcp-ip6-ip4",
addrs: []ma.Multiaddr{q1v1, q1v16, q2v16, q3v16, q2v1, t1, t2},
addrs: []ma.Multiaddr{q1v1, q1v16, q2v16, q3v16, q2v1, t1, t1v6, t2, t3},
output: []network.AddrDelay{
{Addr: q1v16, Delay: 0},
{Addr: q1v1, Delay: PublicQUICDelay},
{Addr: q2v16, Delay: 2 * PublicQUICDelay},
{Addr: q3v16, Delay: 2 * PublicQUICDelay},
{Addr: q2v1, Delay: 2 * PublicQUICDelay},
{Addr: t1, Delay: 3 * PublicQUICDelay},
{Addr: t2, Delay: 3 * PublicQUICDelay},
{Addr: t1v6, Delay: 3 * PublicQUICDelay},
{Addr: t1, Delay: 4 * PublicQUICDelay},
{Addr: t2, Delay: 5 * PublicQUICDelay},
{Addr: t3, Delay: 5 * PublicQUICDelay},
},
},
{
name: "quic-ip4-with-tcp",
addrs: []ma.Multiaddr{q1v1, t1, t2, t1v6},
addrs: []ma.Multiaddr{q1v1, t2, t1v6, t1},
output: []network.AddrDelay{
{Addr: q1v1, Delay: 0},
{Addr: t1, Delay: PublicTCPDelay},
{Addr: t2, Delay: PublicTCPDelay},
{Addr: t1v6, Delay: PublicTCPDelay},
{Addr: t1v6, Delay: PublicQUICDelay},
{Addr: t1, Delay: 2 * PublicQUICDelay},
{Addr: t2, Delay: 3 * PublicQUICDelay},
},
},
{
name: "tcp-ip4-ip6",
addrs: []ma.Multiaddr{t1, t2, t1v6},
addrs: []ma.Multiaddr{t1, t2, t1v6, t3},
output: []network.AddrDelay{
{Addr: t1v6, Delay: 0},
{Addr: t1, Delay: 0},
{Addr: t2, Delay: 0},
{Addr: t1, Delay: PublicTCPDelay},
{Addr: t2, Delay: 2 * PublicTCPDelay},
{Addr: t3, Delay: 2 * PublicTCPDelay},
},
},
}
Expand Down

0 comments on commit 62b878b

Please sign in to comment.