diff options
author | Bhasker Hariharan <bhaskerh@google.com> | 2021-10-27 17:22:48 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-10-27 17:25:46 -0700 |
commit | 8acc3a9bb2225a5af9e5bf587d2a2baad0e5f841 (patch) | |
tree | 24c9464e53c56817bcb0feb4a537d27cbb0d7ee2 /pkg/tcpip/link/sharedmem/queue | |
parent | 9541a5842bf843414d872a539d32ce6e3202bf04 (diff) |
Reduce eventFD notifications on transmit.
When transmitting packets we only need to notify if the peer is not
already processing packets. sharedData region is used to enable/disable
notifications and the peer will disable notifications when its actively
processing packets and enable notifications just before it goes to
sleep waiting on packets. This allows more efficient transmit as the
sharedmem endpoint does not need to notify on eventFD and incur an
expensive host systemcall when the peer is already awake.
PiperOrigin-RevId: 406018843
Diffstat (limited to 'pkg/tcpip/link/sharedmem/queue')
-rw-r--r-- | pkg/tcpip/link/sharedmem/queue/queue_test.go | 20 | ||||
-rw-r--r-- | pkg/tcpip/link/sharedmem/queue/rx.go | 17 | ||||
-rw-r--r-- | pkg/tcpip/link/sharedmem/queue/tx.go | 16 |
3 files changed, 37 insertions, 16 deletions
diff --git a/pkg/tcpip/link/sharedmem/queue/queue_test.go b/pkg/tcpip/link/sharedmem/queue/queue_test.go index 9a0aad5d7..b8a7f3d86 100644 --- a/pkg/tcpip/link/sharedmem/queue/queue_test.go +++ b/pkg/tcpip/link/sharedmem/queue/queue_test.go @@ -35,7 +35,8 @@ func TestBasicTxQueue(t *testing.T) { txp.Init(pb2) var q Tx - q.Init(pb1, pb2) + var state uint32 + q.Init(pb1, pb2, &state) // Enqueue two buffers. b := []TxBuffer{ @@ -203,7 +204,8 @@ func TestBadTxCompletion(t *testing.T) { txp.Init(pb2) var q Tx - q.Init(pb1, pb2) + var state uint32 + q.Init(pb1, pb2, &state) // Post a completion that is too short, and check that it is ignored. if d := txp.Push(7); d == nil { @@ -318,7 +320,8 @@ func TestFillTxPipe(t *testing.T) { txp.Init(pb2) var q Tx - q.Init(pb1, pb2) + var state uint32 + q.Init(pb1, pb2, &state) // Transmit twice, which should fill the tx pipe. b := []TxBuffer{ @@ -386,7 +389,8 @@ func TestLotsOfTransmissions(t *testing.T) { txp.Init(pb2) var q Tx - q.Init(pb1, pb2) + var state uint32 + q.Init(pb1, pb2, &state) // Prepare packet with two buffers. b := []TxBuffer{ @@ -496,8 +500,8 @@ func TestRxEnableNotification(t *testing.T) { q.Init(pb1, pb2, &state) q.EnableNotification() - if state != eventFDEnabled { - t.Fatalf("Bad value in shared state: got %v, want %v", state, eventFDEnabled) + if state != EventFDEnabled { + t.Fatalf("Bad value in shared state: got %v, want %v", state, EventFDEnabled) } } @@ -511,7 +515,7 @@ func TestRxDisableNotification(t *testing.T) { q.Init(pb1, pb2, &state) q.DisableNotification() - if state != eventFDDisabled { - t.Fatalf("Bad value in shared state: got %v, want %v", state, eventFDDisabled) + if state != EventFDDisabled { + t.Fatalf("Bad value in shared state: got %v, want %v", state, EventFDDisabled) } } diff --git a/pkg/tcpip/link/sharedmem/queue/rx.go b/pkg/tcpip/link/sharedmem/queue/rx.go index a78826ebc..89bdf5ef6 100644 --- a/pkg/tcpip/link/sharedmem/queue/rx.go +++ b/pkg/tcpip/link/sharedmem/queue/rx.go @@ -49,9 +49,16 @@ const ( sizeOfConsumedBuffer = 28 // The following are the allowed states of the shared data area. - eventFDUninitialized = 0 - eventFDDisabled = 1 - eventFDEnabled = 2 + // EventFDUinitialized is the value stored at the start of the shared data + // region when it hasn't been initialized. + EventFDUninitialized = 0 + // EventFDDisabled is the value stored at the start of the shared data region + // when notifications using eventFD has been disabled. + EventFDDisabled = 1 + // EventFDEnabled is the value stored at the start of the shared data region + // when eventFD should be notified as the peer might be blocked waiting on + // notifications. + EventFDEnabled = 2 ) // RxBuffer is the descriptor of a receive buffer. @@ -84,13 +91,13 @@ func (r *Rx) Init(tx, rx []byte, sharedEventFDState *uint32) { // EnableNotification updates the shared state such that the peer will notify // the eventfd when there are packets to be dequeued. func (r *Rx) EnableNotification() { - atomic.StoreUint32(r.sharedEventFDState, eventFDEnabled) + atomic.StoreUint32(r.sharedEventFDState, EventFDEnabled) } // DisableNotification updates the shared state such that the peer will not // notify the eventfd. func (r *Rx) DisableNotification() { - atomic.StoreUint32(r.sharedEventFDState, eventFDDisabled) + atomic.StoreUint32(r.sharedEventFDState, EventFDDisabled) } // PostedBuffersLimit returns the maximum number of buffers that can be posted diff --git a/pkg/tcpip/link/sharedmem/queue/tx.go b/pkg/tcpip/link/sharedmem/queue/tx.go index beffe807b..09907c761 100644 --- a/pkg/tcpip/link/sharedmem/queue/tx.go +++ b/pkg/tcpip/link/sharedmem/queue/tx.go @@ -16,6 +16,7 @@ package queue import ( "encoding/binary" + "sync/atomic" "gvisor.dev/gvisor/pkg/log" "gvisor.dev/gvisor/pkg/tcpip/link/sharedmem/pipe" @@ -49,14 +50,23 @@ type TxBuffer struct { // // This struct is thread-compatible. type Tx struct { - tx pipe.Tx - rx pipe.Rx + tx pipe.Tx + rx pipe.Rx + sharedEventFDState *uint32 } // Init initializes the transmit queue with the given pipes. -func (t *Tx) Init(tx, rx []byte) { +func (t *Tx) Init(tx, rx []byte, sharedEventFDState *uint32) { t.tx.Init(tx) t.rx.Init(rx) + t.sharedEventFDState = sharedEventFDState +} + +// NotificationsEnabled returns true if eventFD should be used to notify the +// peer of events (eg. packet transmit etc). +func (t *Tx) NotificationsEnabled() bool { + // Notifications are considered enabled unless explicitly disabled. + return atomic.LoadUint32(t.sharedEventFDState) != EventFDDisabled } // Enqueue queues the given linked list of buffers for transmission as one |