# Flow control ## Link throttling Each client or relay should do appropriate bandwidth throttling to keep its user happy. Communicants rely on TCP's default flow control to push back when they stop reading. The mainline Tor implementation uses token buckets (one for reads, one for writes) for the rate limiting. Since 0.2.0.x, Tor has let the user specify an additional pair of token buckets for "relayed" traffic, so people can deploy a Tor relay with strict rate limiting, but also use the same Tor as a client. To avoid partitioning concerns we combine both classes of traffic over a given OR connection, and keep track of the last time we read or wrote a high-priority (non-relayed) cell. If it's been less than N seconds (currently N=30), we give the whole connection high priority, else we give the whole connection low priority. We also give low priority to reads and writes for connections that are serving directory information. See proposal 111 for details. ## Link padding Link padding can be created by sending PADDING or VPADDING cells along the connection; relay cells of type "DROP" can be used for long-range padding. The payloads of PADDING, VPADDING, or DROP cells are filled with padding bytes. See Section 3. If the link protocol is version 5 or higher, link level padding is enabled as per padding-spec.txt. On these connections, clients may negotiate the use of padding with a CELL_PADDING_NEGOTIATE command whose format is as follows: ```text Version [1 byte] Command [1 byte] ito_low_ms [2 bytes] ito_high_ms [2 bytes] ``` Currently, only version 0 of this cell is defined. In it, the command field is either 1 (stop padding) or 2 (start padding). For the start padding command, a pair of timeout values specifying a low and a high range bounds for randomized padding timeouts may be specified as unsigned integer values in milliseconds. The ito_low_ms field should not be lower than the current consensus parameter value for nf_ito_low (default: 1500). The ito_high_ms field should not be lower than ito_low_ms. (If any party receives an out-of-range value, they clamp it so that it is in-range.) For the stop padding command, the timeout fields should be sent as zero (to avoid client distinguishability) and ignored by the recipient. For more details on padding behavior, see padding-spec.txt. ## Circuit-level flow control To control a circuit's bandwidth usage, each OR keeps track of two 'windows', consisting of how many RELAY_DATA cells it is allowed to originate or willing to consume. These two windows are respectively named: the package window (packaged for transmission) and the deliver window (delivered for local streams). Because of our leaky-pipe topology, every relay on the circuit has a pair of windows, and the OP has a pair of windows for every relay on the circuit. These windows do not apply to relayed cells, however, and a relay that is never used for streams will never decrement its window or cause the client to decrement a window. Each 'window' value is initially set based on the consensus parameter 'circwindow' in the directory (see dir-spec.txt), or to 1000 data cells if no 'circwindow' value is given. In each direction, cells that are not RELAY_DATA cells do not affect the window. An OR or OP (depending on the stream direction) sends a RELAY_SENDME cell to indicate that it is willing to receive more cells when its deliver window goes down below a full increment (100). For example, if the window started at 1000, it should send a RELAY_SENDME when it reaches 900. When an OR or OP receives a RELAY_SENDME, it increments its package window by a value of 100 (circuit window increment) and proceeds to sending the remaining RELAY_DATA cells. If a package window reaches 0, the OR or OP stops reading from TCP connections for all streams on the corresponding circuit, and sends no more RELAY_DATA cells until receiving a RELAY_SENDME cell. If a deliver window goes below 0, the circuit should be torn down. Starting with tor-0.4.1.1-alpha, authenticated SENDMEs are supported (version 1, see below). This means that both the OR and OP need to remember the rolling digest of the cell that precedes (triggers) a RELAY_SENDME. This can be known if the package window gets to a multiple of the circuit window increment (100). When the RELAY_SENDME version 1 arrives, it will contain a digest that MUST match the one remembered. This represents a proof that the end point of the circuit saw the sent cells. On failure to match, the circuit should be torn down. To ensure unpredictability, random bytes should be added to at least one RELAY_DATA cell within one increment window. In other word, every 100 cells (increment), random bytes should be introduced in at least one cell. ### SENDME Cell Format A circuit-level RELAY_SENDME cell always has its StreamID=0. An OR or OP must obey these two consensus parameters in order to know which version to emit and accept. ```text 'sendme_emit_min_version': Minimum version to emit. 'sendme_accept_min_version': Minimum version to accept. ``` If a RELAY_SENDME version is received that is below the minimum accepted version, the circuit should be closed. The RELAY_SENDME payload contains the following: ```text VERSION [1 byte] DATA_LEN [2 bytes] DATA [DATA_LEN bytes] ``` The VERSION tells us what is expected in the DATA section of length DATA_LEN and how to handle it. The recognized values are: 0x00: The rest of the payload should be ignored. 0x01: Authenticated SENDME. The DATA section MUST contain: DIGEST [20 bytes] ```text If the DATA_LEN value is less than 20 bytes, the cell should be dropped and the circuit closed. If the value is more than 20 bytes, then the first 20 bytes should be read to get the DIGEST value. The DIGEST is the rolling digest value from the RELAY_DATA cell that immediately preceded (triggered) this RELAY_SENDME. This value is matched on the other side from the previous cell sent that the OR/OP must remember. (Note that if the digest in use has an output length greater than 20 bytes—as is the case for the hop of an onion service rendezvous circuit created by the hs_ntor handshake—we truncate the digest to 20 bytes here.) ``` If the VERSION is unrecognized or below the minimum accepted version (taken from the consensus), the circuit should be torn down. ## Stream-level flow control Edge nodes use RELAY_SENDME cells to implement end-to-end flow control for individual connections across circuits. Similarly to circuit-level flow control, edge nodes begin with a window of cells (500) per stream, and increment the window by a fixed value (50) upon receiving a RELAY_SENDME cell. Edge nodes initiate RELAY_SENDME cells when both a) the window is <= 450, and b) there are less than ten cell payloads remaining to be flushed at that edge. Stream-level RELAY_SENDME cells are distinguished by having nonzero StreamID. They are still empty; the body still SHOULD be ignored.