tstest/natlab: add latency & loss simulation
A simple implementation of latency and loss simulation, applied to writes to the ethernet interface of the NIC. The latency implementation could be optimized substantially later if necessary. Updates #13355 Signed-off-by: James Tucker <james@tailscale.com>
This commit is contained in:

committed by
James Tucker

parent
41aac26106
commit
c0a1ed86cb
@ -515,6 +515,8 @@ type network struct {
|
||||
wanIP4 netip.Addr // router's LAN IPv4, if any
|
||||
lanIP4 netip.Prefix // router's LAN IP + CIDR (e.g. 192.168.2.1/24)
|
||||
breakWAN4 bool // break WAN IPv4 connectivity
|
||||
latency time.Duration // latency applied to interface writes
|
||||
lossRate float64 // probability of dropping a packet (0.0 to 1.0)
|
||||
nodesByIP4 map[netip.Addr]*node // by LAN IPv4
|
||||
nodesByMAC map[MAC]*node
|
||||
logf func(format string, args ...any)
|
||||
@ -977,7 +979,7 @@ func (n *network) writeEth(res []byte) bool {
|
||||
for mac, nw := range n.writers.All() {
|
||||
if mac != srcMAC {
|
||||
num++
|
||||
nw.write(res)
|
||||
n.conditionedWrite(nw, res)
|
||||
}
|
||||
}
|
||||
return num > 0
|
||||
@ -987,7 +989,7 @@ func (n *network) writeEth(res []byte) bool {
|
||||
return false
|
||||
}
|
||||
if nw, ok := n.writers.Load(dstMAC); ok {
|
||||
nw.write(res)
|
||||
n.conditionedWrite(nw, res)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -1000,6 +1002,23 @@ func (n *network) writeEth(res []byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *network) conditionedWrite(nw networkWriter, packet []byte) {
|
||||
if n.lossRate > 0 && rand.Float64() < n.lossRate {
|
||||
// packet lost
|
||||
return
|
||||
}
|
||||
if n.latency > 0 {
|
||||
// copy the packet as there's no guarantee packet is owned long enough.
|
||||
// TODO(raggi): this could be optimized substantially if necessary,
|
||||
// a pool of buffers and a cheaper delay mechanism are both obvious improvements.
|
||||
var pkt = make([]byte, len(packet))
|
||||
copy(pkt, packet)
|
||||
time.AfterFunc(n.latency, func() { nw.write(pkt) })
|
||||
} else {
|
||||
nw.write(packet)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
macAllNodes = MAC{0: 0x33, 1: 0x33, 5: 0x01}
|
||||
macAllRouters = MAC{0: 0x33, 1: 0x33, 5: 0x02}
|
||||
|
Reference in New Issue
Block a user