Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce SlowOpenToxic to approximate the TCP handshake latency #536

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Create slow_open toxic
Introduce a new toxic (`slow_open` / `SlowOpenToxic`) that adds a
delay to the first data packet of a new TCP connection. This
simulates the delay affecting the TCP handshake (SYN +
SYN/ACK), which is not covered by the `latency` toxic.
stribioli committed Jul 6, 2023
commit 233c9c5972899b7762f5682c0b613b36905d687c
70 changes: 70 additions & 0 deletions toxics/slow_open.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package toxics

import (
"time"
)

// The SlowOpenToxic adds a delay to the first data packet of a new TCP
// connection, to simulate the delay affecting the TCP handshake (which
// is not covered by the latency toxic)
type SlowOpenToxic struct {
// Times in milliseconds
Delay int64 `json:"delay"`
}

type SlowOpenToxicState struct {
Warm bool
}

func (t *SlowOpenToxic) GetBufferSize() int {
return 1024
}

func (t *SlowOpenToxic) Pipe(stub *ToxicStub) {
state := stub.State.(*SlowOpenToxicState)

for {
if !state.Warm {
select {
case <-stub.Interrupt:
return
case c := <-stub.Input:
if c == nil {
stub.Close()
return
}

delay := time.Duration(t.Delay) * time.Millisecond
state.Warm = true

select {
case <-time.After(delay):
c.Timestamp = c.Timestamp.Add(delay)
stub.Output <- c
case <-stub.Interrupt:
stub.Output <- c
return
}
}
} else {
select {
case <-stub.Interrupt:
return
case c := <-stub.Input:
if c == nil {
stub.Close()
return
}
stub.Output <- c
}
}
}
}

func (t *SlowOpenToxic) NewState() interface{} {
return new(SlowOpenToxicState)
}

func init() {
Register("slow_open", new(SlowOpenToxic))
}