mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
The UDP proxy is setting a deadline of 90 seconds when reading from the backend. If no data is received within this interval, it reclaims the connection. This means, the backend would see a different connection every 90 seconds if the backend never sends back any reply to a client. This change prevents the proxy from eagerly GC'ing such connections by taking into account the last time a datagram was proxyed to the backend. Signed-off-by: Albin Kerouanton <albinker@gmail.com>
79 lines
1.9 KiB
Go
79 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"net"
|
|
"testing"
|
|
"time"
|
|
|
|
"gotest.tools/v3/assert"
|
|
)
|
|
|
|
// TestUDPOneSided makes sure that the conntrack entry isn't GC'd if the
|
|
// backend never writes to the UDP client.
|
|
func TestUDPOneSided(t *testing.T) {
|
|
frontend, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0})
|
|
assert.NilError(t, err)
|
|
defer frontend.Close()
|
|
|
|
backend, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0})
|
|
assert.NilError(t, err)
|
|
defer backend.Close()
|
|
|
|
type udpMsg struct {
|
|
data []byte
|
|
saddr *net.UDPAddr
|
|
}
|
|
msgs := make(chan udpMsg)
|
|
go func() {
|
|
for {
|
|
buf := make([]byte, 1024)
|
|
n, saddr, err := backend.ReadFromUDP(buf)
|
|
if err != nil {
|
|
return
|
|
}
|
|
msgs <- udpMsg{data: buf[:n], saddr: saddr}
|
|
}
|
|
}()
|
|
|
|
proxy, err := NewUDPProxy(frontend, backend.LocalAddr().(*net.UDPAddr), ip4)
|
|
assert.NilError(t, err)
|
|
defer proxy.Close()
|
|
|
|
const connTrackTimeout = 1 * time.Second
|
|
proxy.connTrackTimeout = connTrackTimeout
|
|
|
|
go func() {
|
|
proxy.Run()
|
|
}()
|
|
|
|
client, err := net.DialUDP("udp", nil, frontend.LocalAddr().(*net.UDPAddr))
|
|
assert.NilError(t, err)
|
|
defer client.Close()
|
|
|
|
var expSaddr *net.UDPAddr
|
|
for i := range 15 {
|
|
_, err = client.Write([]byte("hello"))
|
|
assert.NilError(t, err)
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
msg := <-msgs
|
|
assert.Equal(t, string(msg.data), "hello")
|
|
if i == 0 {
|
|
expSaddr = msg.saddr
|
|
} else {
|
|
assert.Equal(t, msg.saddr.Port, expSaddr.Port)
|
|
}
|
|
}
|
|
|
|
// The conntrack entry is checked every connTrackTimeout, but the latest
|
|
// write might be less than connTrackTimeout ago. So we need to wait for
|
|
// at least twice the conntrack timeout to make sure the entry is GC'd.
|
|
time.Sleep(2 * connTrackTimeout)
|
|
_, err = client.Write([]byte("hello"))
|
|
assert.NilError(t, err)
|
|
|
|
msg := <-msgs
|
|
assert.Equal(t, string(msg.data), "hello")
|
|
assert.Check(t, msg.saddr.Port != expSaddr.Port)
|
|
}
|