流量控制
对于一个带宽1Gbps, RTT为100ms的网络来说
BDP=1,000,000,000*0.1/8=12,500,000字节=12207K=12M
传统TCP接收窗口大小=65535byte=64K, 显然满足不了
udt使用包大小1500byte, 默认接口窗口大小为8192, 因此
接收窗口的大小为=1500*8192=12,288,000字节=12000K=11.7M
因此, 可以看到udt的默认设置已经足够.
Congestion Control(拥塞控制)
1. 两个重要的参数:
congestion window size and the inter-packet sending interval
2. 主要的接口
1) init: when the UDT socket is connected.
2) close: when the UDT socket is closed.
3) onACK: when ACK is received.
4) onLOSS: when NACK is received.
5) onTimeout: when timeout occurs.
6) onPktSent: when a data packet is sent.
7) onPktRecv: when a data packet is received.
3. udt的拥塞算法:
On ACK packet received:
1) If the current status is in the slow start phase, set the
congestion window size to the product of packet arrival rate and
(RTT + SYN). Slow Start ends. Stop.
2) Set the congestion window size (CWND) to: CWND = A * (RTT + SYN) +16.
3) The number of sent packets to be increased in the next SYN period
(inc) is calculated as:
if (B <= C)
inc = 1/PS;
else
inc = max(10^(ceil(log10((B-C)*PS*8))) * Beta/PS, 1/PS);
where B is the estimated link capacity and C is the current
sending speed. All are counted as packets per second. PS is the
fixed size of UDT packet counted in bytes. Beta is a constant
value of 0.0000015.
4) The SND period is updated as:
SND = (SND * SYN) / (SND * inc + SYN).
Java代码
- Java代码
- */
- public void onACK(long ackSeqno){
- //increase window during slow start
- if(slowStartPhase){
- congestionWindowSize+=ackSeqno-lastAckSeqNumber;
- lastAckSeqNumber = ackSeqno;
- //but not beyond a maximum size
- if(congestionWindowSize>session.getFlowWindowSize()){
- slowStartPhase=false;
- if(packetArrivalRate>0){
- packetSendingPeriod=1000000.0/packetArrivalRate;
- }
- else{
- packetSendingPeriod=(double)congestionWindowSize/(roundTripTime+Util.getSYNTimeD());
- }
- }
- }else{
- //1.if it is not in slow start phase,set the congestion window size
- //to the product of packet arrival rate and(rtt +SYN)
- double A=packetArrivalRate/1000000.0*(roundTripTime+Util.getSYNTimeD());
- congestionWindowSize=(long)A+16;
- if(logger.isLoggable(Level.FINER)){
- logger.finer("receive rate "+packetArrivalRate+" rtt "+roundTripTime+" set to window size: "+(A+16));
- }
- }
- //no rate increase during slow start
- if(slowStartPhase)return;
- //no rate increase "immediately" after a NAK
- if(loss){
- loss=false;
- return;
- }
- //4. compute the increase in sent packets for the next SYN period
- double numOfIncreasingPacket=computeNumOfIncreasingPacket();
- //5. update the send period
- double factor=Util.getSYNTimeD()/(packetSendingPeriod*numOfIncreasingPacket+Util.getSYNTimeD());
- packetSendingPeriod=factor*packetSendingPeriod;
- //packetSendingPeriod=0.995*packetSendingPeriod;
- statistics.setSendPeriod(packetSendingPeriod);
- }
On NAK packet received:
1) If it is in slow start phase, set inter-packet interval to
1/recvrate. Slow start ends. Stop.
2) If this NAK starts a new congestion period, increase inter-packet
interval (snd) to snd = snd * 1.125; Update AvgNAKNum, reset
NAKCount to 1, and compute DecRandom to a random (average
distribution) number between 1 and AvgNAKNum. Update LastDecSeq.
Stop.
3) If DecCount <= 5, and NAKCount == DecCount * DecRandom:
a. Update SND period: SND = SND * 1.125;
b. Increase DecCount by 1;
c. Record the current largest sent sequence number (LastDecSeq).
Java代码
- /* (non-Javadoc)
- * @see udt.CongestionControl#onNAK(java.util.List)
- */
- public void onLoss(List<Integer>lossInfo){
- loss=true;
- long firstBiggestlossSeqNo=lossInfo.get(0);
- nACKCount++;
- /*1) If it is in slow start phase, set inter-packet interval to
- 1/recvrate. Slow start ends. Stop. */
- if(slowStartPhase){
- if(packetArrivalRate>0){
- packetSendingPeriod = 100000.0/packetArrivalRate;
- }
- else{
- packetSendingPeriod=congestionWindowSize/(roundTripTime+Util.getSYNTime());
- }
- slowStartPhase = false;
- return;
- }
- long currentMaxSequenceNumber=session.getSocket().getSender().getCurrentSequenceNumber();
- // 2)If this NAK starts a new congestion epoch
- if(firstBiggestlossSeqNo>lastDecreaseSeqNo){
- // -increase inter-packet interval
- packetSendingPeriod = Math.ceil(packetSendingPeriod*1.125);
- // -Update AvgNAKNum(the average number of NAKs per congestion)
- averageNACKNum = (int)Math.ceil(averageNACKNum*0.875 + nACKCount*0.125);
- // -reset NAKCount and DecCount to 1,
- nACKCount=1;
- decCount=1;
- /* - compute DecRandom to a random (average distribution) number between 1 and AvgNAKNum */
- decreaseRandom =(int)Math.ceil((averageNACKNum-1)*Math.random()+1);
- // -Update LastDecSeq
- lastDecreaseSeqNo = currentMaxSequenceNumber;
- // -Stop.
- }
- //* 3) If DecCount <= 5, and NAKCount == DecCount * DecRandom:
- else if(decCount<=5 && nACKCount==decCount*decreaseRandom){
- // a. Update SND period: SNDSND = SND * 1.125;
- packetSendingPeriod = Math.ceil(packetSendingPeriod*1.125);
- // b. Increase DecCount by 1;
- decCount++;
- // c. Record the current largest sent sequence number (LastDecSeq).
- lastDecreaseSeqNo= currentMaxSequenceNumber;
- }
- statistics.setSendPeriod(packetSendingPeriod);
- return;
- }