1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "fillp_flow_control_alg0.h"
17 #include "res.h"
18 #include "fillp_algorithm.h"
19 #include "fillp_common.h"
20 #include "fillp_output.h"
21 
22 #ifdef FILLP_SUPPORT_GSO
23 #include "check_gso_support.h"
24 #endif
25 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29 
FillpAlg0CalSendInterval(struct FillpPcb * pcb)30 void FillpAlg0CalSendInterval(struct FillpPcb *pcb)
31 {
32     struct FillpFlowControl *flowControl = &pcb->send.flowControl;
33     struct FillpFlowControlAlg0 *alg = (struct FillpFlowControlAlg0 *)flowControl->fcAlg;
34     FILLP_UINT32 minRate = FILLP_FC0_DEFAULT_RATE;
35 
36     if (flowControl->sendRate < minRate) {
37         flowControl->sendRate = minRate;
38     } else if (flowControl->sendRate > alg->maxRateAllowed) {
39         flowControl->sendRate = alg->maxRateAllowed;
40     }
41 
42     FillpCalSendInterval(pcb);
43 }
44 
FillpAlg0UpdateMaxRecvRate(struct FillpFlowControlAlg0 * alg,FILLP_UINT32 recvRate)45 static void FillpAlg0UpdateMaxRecvRate(struct FillpFlowControlAlg0 *alg, FILLP_UINT32 recvRate)
46 {
47     FillpUpdateRecvRateSample(&alg->historyMaxRecvRate, recvRate, alg->historyMaxRecvRateIndex);
48     alg->historyMaxRecvRateIndex = alg->historyMaxRecvRateIndex + 1;
49     alg->historyMaxRecvRateIndex %= FILLP_FC0_PROBE_HISTORY_PACK_MAX_RATE_NUM;
50 }
51 
FillpAlg0FlowControlInit(struct FillpPcb * pcb,struct FillpFlowControlAlg0 * alg)52 static void FillpAlg0FlowControlInit(struct FillpPcb *pcb, struct FillpFlowControlAlg0 *alg)
53 {
54     FILLP_UINT32 i;
55     alg->flowControl = &pcb->send.flowControl;
56     alg->fcState = FILLP_FC0_STATE_INIT;
57 
58     alg->historyMaxRecvRate.maxCnt = FILLP_FC0_PROBE_HISTORY_PACK_MAX_RATE_NUM;
59     alg->historyMaxRecvRateIndex = 0;
60 
61     for (i = 0; i < FILLP_FC0_PROBE_HISTORY_PACK_MAX_RATE_NUM; i++) {
62         alg->historyMaxRecvRate.rateSample[i].i = (FILLP_UINT8)i;
63         alg->historyMaxRecvRate.rateSample[i].v = 0;
64     }
65 
66     alg->maxRecvRate = 0;
67     alg->maxRateAllowed = FILLP_GET_SOCKET(pcb)->resConf.flowControl.maxRate;
68 
69     alg->sendRateIncreaseGainIndex = 0;
70 
71     alg->packDeltaUsArrayIndex = 0;
72     for (i = 0; i < FILLP_FC0_PACK_RECV_INTERVAL_SAMPLE_NUM; i++) {
73         alg->packDeltaUsArray[i] = 0;
74     }
75     alg->historyMaxRecvRate.rateSample[0].v = FILLP_DEFAULT_INITIAL_RATE;
76 }
77 
FillpAlg0FcInit(void * argPcb)78 FILLP_INT FillpAlg0FcInit(void *argPcb)
79 {
80     struct FillpPcb *pcb = (struct FillpPcb *)argPcb;
81     struct FillpFlowControlAlg0 *alg = FILLP_NULL_PTR;
82 
83     if (SockUpdatePktDataOpt(FILLP_GET_SOCKET(pcb), FILLP_OPT_FLAG_TIMESTAMP, 0) != ERR_OK) {
84         return -1;
85     }
86 
87     alg = SpungeAlloc(1, sizeof(struct FillpFlowControlAlg0), SPUNGE_ALLOC_TYPE_CALLOC);
88     if (alg == FILLP_NULL_PTR) {
89         return -1;
90     }
91 
92     alg->historyMaxRecvRate.rateSample = SpungeAlloc(FILLP_FC0_PROBE_HISTORY_PACK_MAX_RATE_NUM,
93         sizeof(struct FillpRateSample), SPUNGE_ALLOC_TYPE_MALLOC);
94     if (alg->historyMaxRecvRate.rateSample == FILLP_NULL_PTR) {
95         SpungeFree(alg, SPUNGE_ALLOC_TYPE_CALLOC);
96         FILLP_LOGERR("fillp to alloc historyMaxRecvRate.rateSample");
97         return -1;
98     }
99 
100     FillpAlg0FlowControlInit(pcb, alg);
101     pcb->send.flowControl.fcAlg = alg;
102     pcb->lastCalcTime = 0;
103 
104     /* in INIT state, tail protect judge threshold should be large than one RTT */
105     pcb->send.tailProtect.judgeThreshold = FILLP_ONE_FIFTH_OF_RTT;
106     pcb->send.retramistRto = (FILLP_ULLONG)pcb->rtt;
107     pcb->send.flowControl.sendRate = FILLP_FC0_DEFAULT_RATE;
108 
109     FillpAlg0CalSendInterval(pcb);
110 #ifdef FILLP_SUPPORT_GSO
111     CheckGSOSupport();
112 #endif
113 
114     return 0;
115 }
116 
FillpAlg0FcDeinit(void * argPcb)117 void FillpAlg0FcDeinit(void *argPcb)
118 {
119     struct FillpPcb *pcb = (struct FillpPcb *)argPcb;
120     struct FillpFlowControlAlg0 *alg = (struct FillpFlowControlAlg0 *)pcb->send.flowControl.fcAlg;
121 
122     if (pcb->send.flowControl.fcAlg == FILLP_NULL_PTR) {
123         return;
124     }
125 
126     if (alg->historyMaxRecvRate.rateSample != FILLP_NULL_PTR) {
127         SpungeFree(alg->historyMaxRecvRate.rateSample, SPUNGE_ALLOC_TYPE_CALLOC);
128         alg->historyMaxRecvRate.rateSample = FILLP_NULL_PTR;
129     }
130 
131     SpungeFree(alg, SPUNGE_ALLOC_TYPE_CALLOC);
132     pcb->send.flowControl.fcAlg = FILLP_NULL_PTR;
133 }
134 
FillpAlg0CalPackInterval(void * argPcb)135 void FillpAlg0CalPackInterval(void *argPcb)
136 {
137     struct FillpPcb *pcb = (struct FillpPcb *)argPcb;
138     FILLP_UINT32 packInterval = FillpGetSockPackInterval(pcb);
139     pcb->statistics.pack.packInterval = packInterval;
140 }
141 
FillpAlg0CalMaxPackRcvInterval(struct FillpPcb * pcb,FILLP_LLONG detaUs,FILLP_UINT32 packRate,FILLP_UINT32 periodSendRate)142 static void FillpAlg0CalMaxPackRcvInterval(struct FillpPcb *pcb, FILLP_LLONG detaUs, FILLP_UINT32 packRate,
143     FILLP_UINT32 periodSendRate)
144 {
145     struct FillpFlowControlAlg0 *alg = (struct FillpFlowControlAlg0 *)pcb->send.flowControl.fcAlg;
146 
147     pcb->statistics.debugPcb.curPackDeltaUs = detaUs;
148     pcb->statistics.pack.periodAckByPackRate = packRate;
149     pcb->statistics.pack.periodSendRate = periodSendRate;
150 
151     alg->packDeltaUsArrayIndex++;
152     alg->packDeltaUsArrayIndex %= FILLP_FC0_PACK_RECV_INTERVAL_SAMPLE_NUM;
153     alg->packDeltaUsArray[alg->packDeltaUsArrayIndex] = (FILLP_UINT32)((FILLP_ULONG)detaUs);
154 }
155 
FillpAlg0FcHandleInit(struct FillpPcb * pcb,FILLP_CONST struct FillpPktPack * pack)156 static void FillpAlg0FcHandleInit(struct FillpPcb *pcb, FILLP_CONST struct FillpPktPack *pack)
157 {
158     struct FillpFlowControl *flowControl = &pcb->send.flowControl;
159     struct FillpFlowControlAlg0 *alg = (struct FillpFlowControlAlg0 *)flowControl->fcAlg;
160     FILLP_UINT32 baseSendRate;
161 
162     /* fc state keeps in INIT state until socket start send data */
163     if (pcb->statistics.traffic.totalSend == 0) {
164         return;
165     }
166 
167     /* in INIT state, tail protect judge threshold should be large than one RTT */
168     pcb->send.tailProtect.judgeThreshold = FILLP_ONE_FIFTH_OF_RTT;
169     alg->sendRateIncreaseGainIndex++;
170     if ((alg->sendRateIncreaseGainIndex < FILLP_FC_RTT_PACK_RATIO) && (pack->rate == 0)) {
171         /* In send rate increase period and recv rate getting nothing currently */
172         return;
173     }
174 
175     alg->maxRecvRate = pack->rate;
176     alg->historyMaxRecvRate.rateSample[0].v = pack->rate;
177     alg->historyMaxRecvRate.rateSample[0].i = 0;
178 
179     baseSendRate = UTILS_MAX(alg->maxRecvRate, FILLP_FC0_DEFAULT_RATE);
180     flowControl->sendRate = baseSendRate;
181     FillpAlg0CalSendInterval(pcb);
182 
183     pcb->send.tailProtect.judgeThreshold = pcb->send.tailProtect.minJudgeThreshold;
184     alg->fcState = FILLP_FC0_STATE_BW_PROBE;
185     FILLP_LOGDTL("fillp_sock_id:%d, fcState INIT -> BW_PROBE, maxRate:%u, sendRateIncreaseGainIndex:%hhu",
186         FILLP_GET_SOCKET(pcb)->index, alg->maxRecvRate, alg->sendRateIncreaseGainIndex);
187 }
188 
FillpAlg0FcHandleBwProbe(struct FillpPcb * pcb,FILLP_CONST struct FillpPktPack * pack)189 static void FillpAlg0FcHandleBwProbe(struct FillpPcb *pcb, FILLP_CONST struct FillpPktPack *pack)
190 {
191     struct FillpFlowControl *flowControl = &pcb->send.flowControl;
192     struct FillpFlowControlAlg0 *alg = (struct FillpFlowControlAlg0 *)flowControl->fcAlg;
193     struct FillpRateSample *historyMaxRecvRate = alg->historyMaxRecvRate.rateSample;
194     FILLP_UINT32 baseSendRate;
195     FILLP_UINT32 recvRate = pack->rate;
196 
197     recvRate = UTILS_MAX(recvRate, FILLP_FC0_DEFAULT_RATE);
198 
199     FillpAlg0UpdateMaxRecvRate(alg, recvRate);
200     baseSendRate = historyMaxRecvRate[0].v;
201     flowControl->sendRate = baseSendRate;
202 
203     FillpAlg0CalSendInterval(pcb);
204 }
205 
FillpAlg0PackStateProcess(struct FillpPcb * pcb,struct FillpPktPack * pack)206 static void FillpAlg0PackStateProcess(struct FillpPcb *pcb, struct FillpPktPack *pack)
207 {
208     struct FillpFlowControl *flowControl = &pcb->send.flowControl;
209     struct FillpFlowControlAlg0 *alg = (struct FillpFlowControlAlg0 *)flowControl->fcAlg;
210     FILLP_UINT32 maxRateAllowed;
211     struct FtSocket *sock = FILLP_GET_SOCKET(pcb);
212 
213     /* Update the allowed max rate */
214     maxRateAllowed = FILLP_GET_SOCKET(pcb)->resConf.flowControl.maxRate;
215     if (pack->oppositeSetRate && (pack->flag & FILLP_PACK_FLAG_WITH_RATE_LIMIT) &&
216         (pack->oppositeSetRate < maxRateAllowed)) {
217         alg->maxRateAllowed = pack->oppositeSetRate;
218     } else {
219         alg->maxRateAllowed = maxRateAllowed;
220     }
221 
222     switch (alg->fcState) {
223         case FILLP_FC0_STATE_INIT:
224             FillpAlg0FcHandleInit(pcb, pack);
225             break;
226         case FILLP_FC0_STATE_BW_PROBE:
227             FillpAlg0FcHandleBwProbe(pcb, pack);
228             break;
229         default:
230             FILLP_LOGDTL("fillp_sock_id:%d fcState:%u wrong", sock->index, alg->fcState);
231             break;
232     }
233 }
234 
FillpAlg0AnalysePack(void * argPcb,FILLP_CONST void * argPack)235 void FillpAlg0AnalysePack(void *argPcb, FILLP_CONST void *argPack)
236 {
237     struct FillpPcb *pcb = (struct FillpPcb *)argPcb;
238     struct FillpPktPack *pack = (struct FillpPktPack *)argPack;
239     FILLP_LLONG detaUs;
240 
241     FILLP_UINT32 periodSendRate; /* Kbps */
242 
243     detaUs = pcb->pcbInst->curTime - pcb->statistics.debugPcb.packRecvedTimeInterval;
244     if (detaUs == 0) {
245         periodSendRate = 0;
246     } else {
247         double rate = (double)pcb->statistics.debugPcb.packIntervalSendBytes * FILLP_FC_IN_BIT;
248         rate *= FILLP_BPS_TO_KBPS;
249         rate /= detaUs;
250         periodSendRate = (FILLP_UINT32)rate;
251     }
252 
253     FillpAlg0CalMaxPackRcvInterval(pcb, detaUs, pack->rate, periodSendRate);
254 
255     pcb->statistics.debugPcb.packRecvedTimeInterval = pcb->pcbInst->curTime;
256     pcb->statistics.debugPcb.packIntervalSendBytes = FILLP_NULL;
257     pcb->statistics.debugPcb.packIntervalSendPkt = FILLP_NULL;
258 
259     FillpAlg0PackStateProcess(pcb, pack);
260 }
261 
262 #ifdef __cplusplus
263 }
264 #endif
265