net/tstun: add inner loop to poll

This avoids re-enqueuing to t.bufferConsumed,
which makes the code a bit clearer.

Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
This commit is contained in:
Josh Bleecher Snyder 2021-07-01 14:48:09 -07:00 committed by Josh Bleecher Snyder
parent a4cc7b6d54
commit c35a832de6

View File

@ -181,6 +181,16 @@ func (t *Wrapper) Close() error {
return err return err
} }
// isClosed reports whether t is closed.
func (t *Wrapper) isClosed() bool {
select {
case <-t.closed:
return true
default:
return false
}
}
// pumpEvents copies events from t.tdev to t.eventsUpDown and t.eventsOther. // pumpEvents copies events from t.tdev to t.eventsUpDown and t.eventsOther.
// pumpEvents exits when t.tdev.events or t.closed is closed. // pumpEvents exits when t.tdev.events or t.closed is closed.
// pumpEvents closes t.eventsUpDown and t.eventsOther when it exits. // pumpEvents closes t.eventsUpDown and t.eventsOther when it exits.
@ -266,28 +276,24 @@ func allowSendOnClosedChannel() {
// so packets may be stuck in t.outbound if t.Read called t.tdev.Read directly. // so packets may be stuck in t.outbound if t.Read called t.tdev.Read directly.
func (t *Wrapper) poll() { func (t *Wrapper) poll() {
defer allowSendOnClosedChannel() // for send to t.outbound defer allowSendOnClosedChannel() // for send to t.outbound
for { for range t.bufferConsumed {
<-t.bufferConsumed var n int
var err error
// Read may use memory in t.buffer before PacketStartOffset for mandatory headers. // Read may use memory in t.buffer before PacketStartOffset for mandatory headers.
// This is the rationale behind the tun.Wrapper.{Read,Write} interfaces // This is the rationale behind the tun.Wrapper.{Read,Write} interfaces
// and the reason t.buffer has size MaxMessageSize and not MaxContentSize. // and the reason t.buffer has size MaxMessageSize and not MaxContentSize.
n, err := t.tdev.Read(t.buffer[:], PacketStartOffset) // In principle, read errors are not fatal (but wireguard-go disagrees).
if err != nil { // We loop here until we get a non-empty (or failed) read.
t.outbound <- tunReadResult{err: err} // We don't need this loop for correctness,
// In principle, read errors are not fatal (but wireguard-go disagrees). // but wireguard-go will skip an empty read,
t.bufferConsumed <- struct{}{} // so we might as well avoid the send through t.outbound.
continue for n == 0 && err == nil {
if t.isClosed() {
return
}
n, err = t.tdev.Read(t.buffer[:], PacketStartOffset)
} }
t.outbound <- tunReadResult{data: t.buffer[PacketStartOffset : PacketStartOffset+n], err: err}
// Wireguard will skip an empty read,
// so we might as well do it here to avoid the send through t.outbound.
if n == 0 {
t.bufferConsumed <- struct{}{}
continue
}
t.outbound <- tunReadResult{data: t.buffer[PacketStartOffset : PacketStartOffset+n]}
} }
} }