[tor-bugs] #2536 [Tor Relay]: Disable outgoing token bucket and reduce token bucket refill interval

Tor Bug Tracker & Wiki torproject-admin at torproject.org
Mon Apr 4 14:25:55 UTC 2011


#2536: Disable outgoing token bucket and reduce token bucket refill interval
-------------------------+--------------------------------------------------
 Reporter:  karsten      |          Owner:  karsten           
     Type:  enhancement  |         Status:  assigned          
 Priority:  normal       |      Milestone:  Tor: 0.2.3.x-final
Component:  Tor Relay    |        Version:                    
 Keywords:               |         Parent:                    
   Points:               |   Actualpoints:                    
-------------------------+--------------------------------------------------

Comment(by Flo):

 We can absolutely understand your concerns and Nick always had a point
 there. We are just excited about the performance improvements obtained
 with our initial proposal, so that we tried to find a way to bring it on.
 Nevertheless you are right that it might be a good first step to implement
 a modification as you suggest, even though we expect that it will not
 overcome all the performance issue under all circumstances then.

 In order to meet your comments, we drafted a different, alternative design
 that strictly maintains configured bandwidth limits.

 Let us start from our original patch (cf. tokenbucket proposal). Thus, we
 have a regular token bucket on the reading side with a certain rate and a
 certain burst size. Let x denote the current amount of tokens in the
 bucket. On the outgoing side we need something appropriate that monitors
 and constrains the outgoing rate, but at the same time avoids holding back
 cells (cf. double door effects) whenever possible.
 Here we propose something that adopts the role of a token bucket, but
 realizes this functionality in a slightly different way. We call it a
 "credit bucket". Like a token bucket, the credit bucket also has a current
 fill level, denoted by y. However, the credit bucket is refilled in a
 different way.

 To understand how it works, let us look at the possible operations:

 * As said, x is the fill level of a regular token bucket on the incoming
 side and thus gets incremented periodically according to the configured
 rate. No changes here.

 * If x<=0, we are obviously not allowed to read.

 * If x>0, we are allowed to read up to x bytes of incoming data. If k
 bytes are read (k<=x), then we update x and y as follows:

   x = x - k     (1)
   y = y + k     (2)

 (1) is the standard token bucket operation on the incoming side. Whenever
 data is admitted in, though, an additional operation is performed: (2)
 allocates the same number of bytes on the outgoing side, which will later
 on allow the same number of bytes to leave the onion router without any
 delays.

 * If y + x > -M, we are allowed to write up to y + x + M bytes on the
 outgoing side, where M is a positive constant. M specifies a burst size
 for the outgoing side. M should be higher than the number of tokens that
 get refilled during a refill interval, we would suggest to have M in the
 order of a few seconds "worth" of data. Now if k bytes are written on the
 outgoing side, we proceed as follows:

  1) If k <= y then y = y - k
 In this case we use "saved" credits, previously allocated on the incoming
 side when incoming data has been processed.

  2) If k > y then y = 0 and x = x - (k-y)
 We generated additional traffic in the onion router, so that more data is
 to be sent than has been read (the credit is not sufficient). We therefore
 "steal" tokens from the token buffer on the incoming side to compensate
 for the additionally generated data. This will result in correspondingly
 less data being read on the incoming side subsequently. As a result of
 such an operation, the token bucket fill level x on the incoming side may
 become negative (but it can never fall below -M).

 * If y + x <= -M then outgoing data will be held back. This may lead to
 double-door effects, but only in extreme cases where the outgoing traffic
 largely exceeds the incoming traffic, so that the outgoing bursts size M
 is exceeded.

 Aside from short-term bursts of configurable size (as with every token
 bucket), this procedure guarantees that the configured rate may never be
 exceeded (on the application layer, that is; as with the current
 implementation, an attacker may easily cause the onion router to
 arbitrarily exceed the limits on the lower layers). Over time, we never
 send more data than the configured rate: every sent byte needs a
 corresponding token on the incoming side; this token must either have been
 consumed by an incoming byte before (it then became a "credit"), or it is
 "stolen" from the incoming bucket to compensate for data generated within
 the onion router.

 This modification can be implemented with moderate effort and requires
 changes only at the points where currently the token bucket operations are
 performed.

 We feel that this is not the be-all and end-all solution, because it again
 introduces a feedback loop between the incoming and the outgoing side. We
 therefore still hope that we will be able to come to a both simpler and
 more effective design in the future. However, we believe that what we
 proposed above is a good compromise between avoiding double-door effects
 to the furthest possible extent, strictly enforcing an application-layer
 data rate, and keeping the extent of changes to the code small.

 Comments are, as always, highly welcome.

-- 
Ticket URL: <https://trac.torproject.org/projects/tor/ticket/2536#comment:11>
Tor Bug Tracker & Wiki <https://trac.torproject.org/>
The Tor Project: anonymity online


More information about the tor-bugs mailing list