Process delayed packets when delay is disabled

Moving the wakeup logic into the disable blocks is an optimization.

PiperOrigin-RevId: 221677028
Change-Id: Ib5a5a6d52cc77b4bbc5dedcad9ee1dbb3da98deb
This commit is contained in:
Ian Gudger 2018-11-15 13:16:05 -08:00 committed by Shentubot
parent bc41e4761b
commit 9d8e49d950
2 changed files with 77 additions and 3 deletions

View File

@ -654,21 +654,25 @@ func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error {
case tcpip.DelayOption:
if v == 0 {
atomic.StoreUint32(&e.delay, 0)
// Handle delayed data.
e.sndWaker.Assert()
} else {
atomic.StoreUint32(&e.delay, 1)
}
return nil
case tcpip.CorkOption:
if v == 0 {
atomic.StoreUint32(&e.cork, 0)
// Handle the corked data.
e.sndWaker.Assert()
} else {
atomic.StoreUint32(&e.cork, 1)
}
// Handle the corked data.
e.sndWaker.Assert()
return nil
case tcpip.ReuseAddressOption:

View File

@ -1379,6 +1379,76 @@ func TestDelay(t *testing.T) {
}
}
func TestUndelay(t *testing.T) {
c := context.New(t, defaultMTU)
defer c.Cleanup()
c.CreateConnected(789, 30000, nil)
c.EP.SetSockOpt(tcpip.DelayOption(1))
allData := [][]byte{{0}, {1, 2, 3}}
for i, data := range allData {
view := buffer.NewViewFromBytes(data)
if _, _, err := c.EP.Write(tcpip.SlicePayload(view), tcpip.WriteOptions{}); err != nil {
t.Fatalf("Write #%d failed: %v", i+1, err)
}
}
seq := c.IRS.Add(1)
// Check that data is received.
first := c.GetPacket()
checker.IPv4(t, first,
checker.PayloadLen(len(allData[0])+header.TCPMinimumSize),
checker.TCP(
checker.DstPort(context.TestPort),
checker.SeqNum(uint32(seq)),
checker.AckNum(790),
checker.TCPFlagsMatch(header.TCPFlagAck, ^uint8(header.TCPFlagPsh)),
),
)
if got, want := first[header.IPv4MinimumSize+header.TCPMinimumSize:], allData[0]; !bytes.Equal(got, want) {
t.Fatalf("got first packet's data = %v, want = %v", got, want)
}
seq = seq.Add(seqnum.Size(len(allData[0])))
// Check that we don't get the second packet yet.
c.CheckNoPacketTimeout("delayed second packet transmitted", 100*time.Millisecond)
c.EP.SetSockOpt(tcpip.DelayOption(0))
// Check that data is received.
second := c.GetPacket()
checker.IPv4(t, second,
checker.PayloadLen(len(allData[1])+header.TCPMinimumSize),
checker.TCP(
checker.DstPort(context.TestPort),
checker.SeqNum(uint32(seq)),
checker.AckNum(790),
checker.TCPFlagsMatch(header.TCPFlagAck, ^uint8(header.TCPFlagPsh)),
),
)
if got, want := second[header.IPv4MinimumSize+header.TCPMinimumSize:], allData[1]; !bytes.Equal(got, want) {
t.Fatalf("got second packet's data = %v, want = %v", got, want)
}
seq = seq.Add(seqnum.Size(len(allData[1])))
// Acknowledge the data.
c.SendPacket(nil, &context.Headers{
SrcPort: context.TestPort,
DstPort: c.Port,
Flags: header.TCPFlagAck,
SeqNum: 790,
AckNum: seq,
RcvWnd: 30000,
})
}
func testBrokenUpWrite(t *testing.T, c *context.Context, maxPayload int) {
payloadMultiplier := 10
dataLen := payloadMultiplier * maxPayload