Active algorithms calculate the rates for all the flows in the FG and actively distribute them. In a passive algorithm, UPDATE returns a rate that should be used instead of the rate that the congestion controller has determined. This can make a passive algorithm easier to implement; however, when round-trip times of flows are unequal, flows with shorter RTTs may (depending on the congestion control algorithm) update and react to the overall FSE state more often than flows with longer RTTs, which can produce unwanted side effects. This problem is more significant when the congestion control convergence depends on the RTT. While the passive algorithm works better for congestion controls with RTT-independent convergence, it can still produce oscillations on short time scales. The algorithm described below is therefore considered highly experimental and not safe to deploy outside of testbed environments. Results of a simplified passive FSE algorithm with both NADA and GCC can be found in [
FSE-NOMS].
In the passive version of the FSE, TLO (Total Leftover Rate) is a static variable per FG that is initialized to 0. Additionally, S_CR is limited to increase or decrease as conservatively as a flow's congestion controller decides in order to prohibit sudden rate jumps.
- (1)
- When a flow f starts, it registers itself with SBD and the FSE. FSE_R(f) and DR(f) are initialized with the congestion controller's initial rate. SBD will assign the correct FGI. When a flow is assigned an FGI, it adds its FSE_R(f) to S_CR.
- (2)
- When a flow f stops or pauses, it sets its DR(f) to 0 and sets P(f) to -1.
- (3)
-
Every time the congestion controller of the flow f determines a new sending rate CC_R(f), assuming the flow's new desired rate new_DR(f) to be "infinity" in case of a bulk data transfer with an unknown maximum rate, the flow calls UPDATE, which carries out the tasks listed below to derive the flow's new sending rate, Rate(f). A flow's UPDATE function uses a few local (i.e., per-flow) temporary variables, which are all initialized to 0: DELTA, new_S_CR, and S_P.
- (a)
-
For all the flows in its FG (including itself), it calculates the sum of all the calculated rates, new_S_CR. Then, it calculates DELTA: the difference between FSE_R(f) and CC_R(f).
for all flows i in FG do
new_S_CR = new_S_CR + FSE_R(i)
end for
DELTA = CC_R(f) - FSE_R(f)
- (b)
-
It updates S_CR, FSE_R(f), and DR(f).
FSE_R(f) = CC_R(f)
if DELTA > 0 then // the flow's rate has increased
S_CR = S_CR + DELTA
else if DELTA < 0 then
S_CR = new_S_CR + DELTA
end if
DR(f) = min(new_DR(f),FSE_R(f))
- (c)
-
It calculates the leftover rate TLO, removes the terminated flows from the FSE, and calculates the sum of all the priorities, S_P.
for all flows i in FG do
if P(i)<0 then
delete flow
else
S_P = S_P + P(i)
end if
end for
if DR(f) < FSE_R(f) then
TLO = TLO + (P(f)/S_P) * S_CR - DR(f))
end if
- (d)
-
It calculates the sending rate, Rate(f).
Rate(f) = min(new_DR(f), (P(f)*S_CR)/S_P + TLO)
if Rate(f) != new_DR(f) and TLO > 0 then
TLO = 0 // f has 'taken' TLO
end if
- (e)
-
It updates DR(f) and FSE_R(f) with Rate(f).
if Rate(f) > DR(f) then
DR(f) = Rate(f)
end if
FSE_R(f) = Rate(f)
The goals of the flow algorithm are to achieve prioritization, improve network utilization in the face of application-limited flows, and impose limits on the increase behavior such that the negative impact of multiple flows trying to increase their rate together is minimized. It does that by assigning a flow a sending rate that may not be what the flow's congestion controller expected. It therefore builds on the assumption that no significant inefficiencies arise from temporary application-limited behavior or from quickly jumping to a rate that is higher than the congestion controller intended. How problematic these issues really are depends on the controllers in use and requires careful per-controller experimentation. The coupled congestion control mechanism described here also does not require all controllers to be equal; effects of heterogeneous controllers, or homogeneous controllers being in different states, are also subject to experimentation.
This algorithm gives the leftover rate of application-limited flows to the first flow that updates its sending rate, provided that this flow needs it all (otherwise, its own leftover rate can be taken by the next flow that updates its rate). Other policies could be applied, e.g., to divide the leftover rate of a flow equally among all other flows in the FGI.
In order to illustrate the operation of the passive coupled congestion control algorithm, this section presents a toy example of two flows that use it. Let us assume that both flows traverse a common 10 Mbit/s bottleneck and use a simplistic congestion controller that starts out with 1 Mbit/s, increases its rate by 1 Mbit/s in the absence of congestion, and decreases it by 2 Mbit/s in the presence of congestion. For simplicity, flows are assumed to always operate in a round-robin fashion. Rate numbers below without units are assumed to be in Mbit/s. For illustration purposes, the actual sending rate is also shown for every flow in FSE diagrams even though it is not really stored in the FSE.
Flow #1 begins. It is a bulk data transfer and considers itself to have top priority. This is the FSE after the flow algorithm's step 1:
----------------------------------------
| # | FGI | P | FSE_R | DR | Rate |
| | | | | | |
| 1 | 1 | 1 | 1 | 1 | 1 |
----------------------------------------
S_CR = 1, TLO = 0
Its congestion controller gradually increases its rate. Eventually, at some point, the FSE should look like this:
-----------------------------------------
| # | FGI | P | FSE_R | DR | Rate |
| | | | | | |
| 1 | 1 | 1 | 10 | 10 | 10 |
-----------------------------------------
S_CR = 10, TLO = 0
Now, another flow joins. It is also a bulk data transfer and has a lower priority (0.5):
------------------------------------------
| # | FGI | P | FSE_R | DR | Rate |
| | | | | | |
| 1 | 1 | 1 | 10 | 10 | 10 |
| 2 | 1 | 0.5 | 1 | 1 | 1 |
------------------------------------------
S_CR = 11, TLO = 0
Now, assume that the first flow updates its rate to 8, because the total sending rate of 11 exceeds the total capacity. Let us take a closer look at what happens in step 3 of the flow algorithm.
CC_R(1) = 8. new_DR(1) = infinity.
- (3a)
- new_S_CR = 11; DELTA = 8 - 10 = -2.
- (3b)
- FSE_R(1) = 8. DELTA is negative, hence S_CR = 9; DR(1) = 8
- (3c)
- S_P = 1.5.
- (3d)
- new sending rate Rate(1) = min(infinity, 1/1.5 * 9 + 0) = 6.
- (3e)
- FSE_R(1) = 6.
The resulting FSE looks as follows:
-------------------------------------------
| # | FGI | P | FSE_R | DR | Rate |
| | | | | | |
| 1 | 1 | 1 | 6 | 8 | 6 |
| 2 | 1 | 0.5 | 1 | 1 | 1 |
-------------------------------------------
S_CR = 9, TLO = 0
The effect is that flow #1 is sending with 6 Mbit/s instead of the 8 Mbit/s that the congestion controller derived. Let us now assume that flow #2 updates its rate. Its congestion controller detects that the network is not fully saturated (the actual total sending rate is 6+1=7) and increases its rate.
CC_R(2) = 2. new_DR(2) = infinity.
- (3a)
- new_S_CR = 7; DELTA = 2 - 1 = 1.
- (3b)
- FSE_R(2) = 2. DELTA is positive, hence S_CR = 9 + 1 = 10; DR(2) = 2.
- (3c)
- S_P = 1.5.
- (3d)
- Rate(2) = min(infinity, 0.5/1.5 * 10 + 0) = 3.33.
- (3e)
- DR(2) = FSE_R(2) = 3.33.
The resulting FSE looks as follows:
-------------------------------------------
| # | FGI | P | FSE_R | DR | Rate |
| | | | | | |
| 1 | 1 | 1 | 6 | 8 | 6 |
| 2 | 1 | 0.5 | 3.33 | 3.33 | 3.33 |
-------------------------------------------
S_CR = 10, TLO = 0
The effect is that flow #2 is now sending with 3.33 Mbit/s, which is close to half of the rate of flow #1 and leads to a total utilization of 6(#1) + 3.33(#2) = 9.33 Mbit/s. Flow #2's congestion controller has increased its rate faster than the controller actually expected. Now, flow #1 updates its rate. Its congestion controller detects that the network is not fully saturated and increases its rate. Additionally, the application feeding into flow #1 limits the flow's sending rate to at most 2 Mbit/s.
CC_R(1) = 7. new_DR(1) = 2.
- (3a)
- new_S_CR = 9.33; DELTA = 1.
- (3b)
- FSE_R(1) = 7, DELTA is positive, hence S_CR = 10 + 1 = 11; DR(1) = min(2, 7) = 2.
- (3c)
- S_P = 1.5; DR(1) < FSE_R(1), hence TLO = 1/1.5 * 11 - 2 = 5.33.
- (3d)
- Rate(1) = min(2, 1/1.5 * 11 + 5.33) = 2.
- (3e)
- FSE_R(1) = 2.
The resulting FSE looks as follows:
-------------------------------------------
| # | FGI | P | FSE_R | DR | Rate |
| | | | | | |
| 1 | 1 | 1 | 2 | 2 | 2 |
| 2 | 1 | 0.5 | 3.33 | 3.33 | 3.33 |
-------------------------------------------
S_CR = 11, TLO = 5.33
Now, the total rate of the two flows is 2 + 3.33 = 5.33 Mbit/s, i.e., the network is significantly underutilized due to the limitation of flow #1. Flow #2 updates its rate. Its congestion controller detects that the network is not fully saturated and increases its rate.
CC_R(2) = 4.33. new_DR(2) = infinity.
- (3a)
- new_S_CR = 5.33; DELTA = 1.
- (3b)
- FSE_R(2) = 4.33. DELTA is positive, hence S_CR = 12; DR(2) = 4.33.
- (3c)
- S_P = 1.5.
- (3d)
- Rate(2) = min(infinity, 0.5/1.5 * 12 + 5.33 ) = 9.33.
- (3e)
- FSE_R(2) = 9.33, DR(2) = 9.33.
The resulting FSE looks as follows:
-------------------------------------------
| # | FGI | P | FSE_R | DR | Rate |
| | | | | | |
| 1 | 1 | 1 | 2 | 2 | 2 |
| 2 | 1 | 0.5 | 9.33 | 9.33 | 9.33 |
-------------------------------------------
S_CR = 12, TLO = 0
Now, the total rate of the two flows is 2 + 9.33 = 11.33 Mbit/s. Finally, flow #1 terminates. It sets P(1) to -1 and DR(1) to 0. Let us assume that it terminated late enough for flow #2 to still experience the network in a congested state, i.e., flow #2 decreases its rate in the next iteration.
CC_R(2) = 7.33. new_DR(2) = infinity.
- (3a)
- new_S_CR = 11.33; DELTA = -2.
- (3b)
- FSE_R(2) = 7.33. DELTA is negative, hence S_CR = 9.33; DR(2) = 7.33.
- (3c)
- Flow 1 has P(1) = -1, hence it is deleted from the FSE. S_P = 0.5.
- (3d)
- Rate(2) = min(infinity, 0.5/0.5*9.33 + 0) = 9.33.
- (3e)
- FSE_R(2) = DR(2) = 9.33.
The resulting FSE looks as follows:
-------------------------------------------
| # | FGI | P | FSE_R | DR | Rate |
| | | | | | |
| 2 | 1 | 0.5 | 9.33 | 9.33 | 9.33 |
-------------------------------------------
S_CR = 9.33, TLO = 0