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