Module memquota

Source
Expand description

Types to support memory quota tracking

We make these newtypes because we otherwise have a confusing a maze of identical-looking, but supposedly semantically different, [Account]s.

§Memory tracking architecture in Arti

§Queues

The following queues in Arti participate in the memory quota system:

  • Tor streams (StreamAccount)
    • inbound data, on its way from the circuit to the stream’s user
    • outbound data, on its way from the stream’s user to the circuit
  • Tor circuits (CircuitAccount)
    • inbound stream requests, on their way from the circuit to the handling code
    • inbound data, on its way from the channel
  • Tor channels (ChannelAccount)
    • outbound data, on its way from a circuit to the channel (this ought to be accounted to the circuit, TODO #1652)

The following data buffers do not participate:

  • Our TLS implementation(s) may have internal buffers. We hope that these buffers will be kept reasonably small, and hooking into them would in any case going be quite hard.

  • TCP sockets will also buffer data, in the operating system. Hooking into this is not trivial.

  • Our pluggable transport driver can buffer some data. This should be kept to a minimum for several reasons, so we hope that the buffers are small.

  • The actual pluggable transport might buffer data. Again, this should be kept to a minimum.

§Overview

See the [tor_memquota] crate-level docs for an overview of the memquota system. To summarise:

When too much memory is in use, the queue with the oldest data is selected for reclaim. The whole Account relating to the victim queue is torn down. When the victim Account collapses, all its queues collapse too: reading ends give EOF, and writing ends give errors. This will tear down the associated Tor protocol association.

All the children Accounts of the victim Account are torn down too. This propagates the collapse to dependent Tor protocol associations.

§Accounting

Within Arti we maintain a hierarchy of [Account]s. These are wrapped in newtypes, here in tor_proto::memquota.

  • ToplevelAccount: In a single Arti instance there will be one of these, used for all memory tracking. This is held (shared) by the chanmgr and the circmgr. Unlike the other layer-specific accounts, this is just a type alias for [MemoryQuotaTracker]. It doesn’t support claiming memory directly from it, so it won’t be subject to reclaim.

  • ChannelAccount. Contains (via parentage) everything that goes via a particular Channel. This includes all circuits on the channel, and those circuits’ streams.

  • CircuitAccount. Has the ChannelAccount as its parent. So if a queue accounted to a channel is selected for reclaim, that channel, and all of its circuits, will collapse.

  • StreamAccount. Has the CircuitAccount as its parent. So if a queue accounted to a circuit is selected for reclaim, that circuit, and all of its streams, will collapse. If a stream’s queue is selected for reclaim, only that stream will collapse. (See #1661 for discussion of this behaviour.)

Thus, killing a single queue will reclaim the memory associated with several other queues.

Structs§

ChannelAccount
[Account] for a Tor Channel
CircuitAccount
[Account] for a Tor Circuit
StreamAccount
[Account] for a Tor Stream

Traits§

SpecificAccount
An [Account], whose type indicates which layer of the stack it’s for

Type Aliases§

ToplevelAccount
Account for the whole system