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_common.h"
17 #include "fillp_output.h"
18 #include "opt.h"
19 
20 #define FILLP_FRAME_INTVL_MIN_INDEX(len) ((FILLP_UINT16)((((FILLP_UINT32)(len)) * 5) / 100))
21 #define FILLP_FRAME_INTVL_MAX_INDEX(len) ((FILLP_UINT16)((((FILLP_UINT32)(len)) * 95) / 100))
22 #define FILLP_UNLIMIT_SEND_INTERVAL 100 /* try to send every 100us */
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
FillpEnablePackTimerInCb(struct FillpPcb * pcb,FILLP_BOOL enNormalPackTimer)28 static void FillpEnablePackTimerInCb(struct FillpPcb *pcb, FILLP_BOOL enNormalPackTimer)
29 {
30     (void)enNormalPackTimer;
31     FillpEnablePackTimer(pcb);
32 }
33 
LogFcFcAppStastics(const struct FillpPcb * pcb,const struct FillAppFcStastics * appFcStastics)34 static void LogFcFcAppStastics(const struct FillpPcb *pcb, const struct FillAppFcStastics *appFcStastics)
35 {
36     FILLP_LOGDBG("fillp_sock_id:%d periodRtt:<%u>, periodRecvRate: <%u, %llu>, periodRecvPktLoss: <%u, %u>, "
37         "periodSendRate: <%llu>, period_send_pkt_loss: %u",
38         FILLP_GET_SOCKET(pcb)->index, appFcStastics->periodRtt, appFcStastics->periodRecvRate,
39         appFcStastics->periodRecvRateBps, appFcStastics->periodRecvPktLoss,
40         appFcStastics->periodRecvPktLossHighPrecision, appFcStastics->periodSendRateBps,
41         appFcStastics->periodSendPktLossHighPrecision);
42 }
43 
FillpCalFcAppStastics(struct FillpPcb * pcb)44 static void FillpCalFcAppStastics(struct FillpPcb *pcb)
45 {
46     struct FtSocket *sock = FILLP_GET_SOCKET(pcb);
47     struct FillpPackStastics *packStastics = &pcb->statistics.pack;
48     struct FillAppFcStastics *appFcStastics = &pcb->statistics.appFcStastics;
49 
50     appFcStastics->periodTimePassed += packStastics->packTimePassed;
51     appFcStastics->periodRecvBits += (FILLP_LLONG)packStastics->periodRecvBits;
52     appFcStastics->periodRecvPkts += packStastics->periodRecvedOnes;
53 
54     if (appFcStastics->periodTimePassed < (FILLP_LLONG)(sock->resConf.common.fcStasticsInterval)) {
55         return;
56     }
57 
58     FILLP_UINT32 pktData = pcb->recv.pktNum - appFcStastics->pktNum;
59     if (pktData == 0) {
60         appFcStastics->periodRecvPktLossHighPrecision = 0;
61     } else if (pktData >= appFcStastics->periodRecvPkts) {
62         appFcStastics->periodRecvPktLossHighPrecision = (pktData - appFcStastics->periodRecvPkts) *
63             FILLP_RECV_PKT_LOSS_H_PERCISION * FILLP_RECV_PKT_LOSS_MAX / pktData;
64     } else {
65         appFcStastics->periodRecvPktLossHighPrecision = 0;
66         FILLP_LOGINF("fillp_sock_id:%d, recv_pkt_num:%u, pre_pkt_num:%u, periodRecvPkts:%u",
67             FILLP_GET_SOCKET(pcb)->index, pcb->recv.pktNum, appFcStastics->pktNum,
68             appFcStastics->periodRecvPkts);
69     }
70     appFcStastics->periodRecvPktLoss =
71         appFcStastics->periodRecvPktLossHighPrecision / (FILLP_UINT32)FILLP_RECV_PKT_LOSS_H_PERCISION;
72 
73     /* bits num / (us / 1,000,000) equal to (bits num * 1,000,000) / us */
74     appFcStastics->periodRecvRateBps =
75         (FILLP_ULLONG)(((FILLP_ULLONG)appFcStastics->periodRecvBits * FILLP_UTILS_MS2US(FILLP_ONE_SECOND)) /
76         (FILLP_ULLONG)appFcStastics->periodTimePassed);
77     appFcStastics->periodRecvRate = (FILLP_UINT32)FILLP_UTILS_BPS2KBPS(appFcStastics->periodRecvRateBps);
78 
79     if ((appFcStastics->periodSendPkts == 0) ||
80         (appFcStastics->periodSendPkts < appFcStastics->periodSendLostPkts)) {
81         appFcStastics->periodSendPktLossHighPrecision = 0;
82     } else {
83         appFcStastics->periodSendPktLossHighPrecision = appFcStastics->periodSendLostPkts *
84             FILLP_RECV_PKT_LOSS_H_PERCISION * FILLP_RECV_PKT_LOSS_MAX / appFcStastics->periodSendPkts;
85     }
86 
87     appFcStastics->periodSendRateBps =
88         (FILLP_ULLONG)((appFcStastics->periodSendBits * FILLP_UTILS_MS2US(FILLP_ONE_SECOND)) /
89         (FILLP_ULLONG)appFcStastics->periodTimePassed);
90 
91     appFcStastics->periodTimePassed = 0;
92     appFcStastics->periodRecvBits = 0;
93     appFcStastics->periodRecvPkts = 0;
94     appFcStastics->pktNum = pcb->recv.pktNum;
95     appFcStastics->periodSendLostPkts = 0;
96     appFcStastics->periodSendPkts = 0;
97     appFcStastics->periodSendBits = 0;
98     LogFcFcAppStastics(pcb, appFcStastics);
99 }
100 
FillpCalRecvRate(struct FillpPcb * pcb)101 static void FillpCalRecvRate(struct FillpPcb *pcb)
102 {
103     struct FillpPackStastics *packStastics = &pcb->statistics.pack;
104     FILLP_UINT32 recvRate;
105 
106     /* Cal Pkt loss and rate */
107     FILLP_UINT32 pktData = pcb->recv.pktNum - packStastics->packPktNum;
108     if (pktData == 0) {
109         packStastics->periodRecvPktLoss = 0;
110     } else {
111         if (pktData <= packStastics->periodRecvedOnes) {
112             packStastics->periodRecvPktLoss = 0;
113         } else {
114             packStastics->periodRecvPktLoss = (FILLP_UINT16)(
115                 (FILLP_ULLONG)(pktData - packStastics->periodRecvedOnes) * FILLP_RECV_PKT_LOSS_MAX / pktData);
116         }
117     }
118     /*  kbps  */
119     recvRate = (FILLP_UINT32)((packStastics->periodRecvBits * FILLP_ONE_SECOND) /
120         (FILLP_ULLONG)packStastics->packTimePassed);
121     packStastics->periodRecvRate = (packStastics->lastPackRecvRate + recvRate) >> 1;
122     packStastics->lastPackRecvRate = recvRate;
123 
124     if (packStastics->maxRecvRate < packStastics->periodRecvRate) {
125         packStastics->maxRecvRate = packStastics->periodRecvRate;
126     }
127     FILLP_LOGDBG("fillp_sock_id:%d nackSend: %u nackFailed: %u nackRcv: %u "
128                  "packSend: %u packFailed: %u packRcv: %u nackPktNum: %u "
129                  "totalSendBytes: %u packIntervalSendPkt: %u "
130                  "total_recvd_count: %u recv rate: %u pack input interval: %lld",
131                  FILLP_GET_SOCKET(pcb)->index, pcb->statistics.debugPcb.nackSend,
132                  pcb->statistics.debugPcb.nackFailed, pcb->statistics.debugPcb.nackRcv,
133                  pcb->statistics.debugPcb.packSend, pcb->statistics.debugPcb.packFailed,
134                  pcb->statistics.debugPcb.packRcv, pcb->statistics.debugPcb.nackPktNum,
135                  pcb->statistics.traffic.totalSendBytes, pcb->statistics.debugPcb.packIntervalSendPkt,
136                  pcb->statistics.traffic.totalRecved, pcb->statistics.pack.periodRecvRate,
137                  pcb->statistics.debugPcb.packRecvedTimeInterval);
138 
139     FILLP_LOGDBG("fillp_sock_id:%d periodRecvRate: %u, maxRecvRate: %u \n", FILLP_GET_SOCKET(pcb)->index,
140         packStastics->periodRecvRate, packStastics->maxRecvRate);
141 
142     pcb->recv.prePackPktNum = packStastics->packPktNum;
143     packStastics->packPktNum = pcb->recv.pktNum;
144     packStastics->periodRecvBits = 0;
145     packStastics->periodRecvedOnes = 0;
146 }
147 
FillpPackTimerCb(void * argPcb)148 void FillpPackTimerCb(void *argPcb)
149 {
150     struct FillpPcb *pcb = (struct FillpPcb *)argPcb;
151     struct FtSocket *sock = FILLP_GET_SOCKET(pcb);
152     struct FillpPackStastics *pack = &pcb->statistics.pack;
153     FILLP_BOOL enableNormalTimer;
154     FILLP_LLONG curTime = SYS_ARCH_GET_CUR_TIME_LONGLONG();
155 
156     pack->packTimePassed = curTime - pack->packSendTime;
157     pack->packSendTime = curTime;
158 
159     FILLP_LOGDBG("pack fire time =%lld", pcb->pcbInst->curTime);
160     FillpCalFcAppStastics(pcb);
161     FillpCalRecvRate(pcb);
162     FillpUploadRecvBox(pcb);
163 
164     if (pcb->algFuncs.packTimer != FILLP_NULL_PTR) {
165         pcb->algFuncs.packTimer(pcb);
166     }
167 
168     enableNormalTimer = FillpSendPackWithPcbBuffer(pcb);
169     if (enableNormalTimer &&
170         (curTime - pack->packRttDetectTime) > (FILLP_LLONG)(sock->resConf.common.fcStasticsInterval)) {
171         FillpSendAdhocpackToDetectRtt(pcb);
172         pack->packRttDetectTime = curTime;
173     }
174 
175     pack->packSendTime = pcb->pcbInst->curTime;
176     FillpEnablePackTimerInCb(pcb, enableNormalTimer);
177 }
178 
FillpSendTimerCb(void * argPcb)179 void FillpSendTimerCb(void *argPcb)
180 {
181     struct FillpPcb *pcb = (struct FillpPcb *)argPcb;
182     struct FillpFlowControl *flowControl = &pcb->send.flowControl;
183     FILLP_LLONG detaTime = (FILLP_LLONG)(pcb->pcbInst->curTime - flowControl->sendTime);
184     FILLP_LLONG realDetaTime = (FILLP_LLONG)((FILLP_ULLONG)detaTime << FILLP_TIME_PRECISION);
185 
186     FILLP_LOGDBG("cur %lld, deta_time:%lld, send_interval:%lld",
187         pcb->pcbInst->curTime, realDetaTime, flowControl->sendInterval);
188     if (realDetaTime >= flowControl->sendInterval) {
189         SpungeDoSendCycle((struct SpungePcb *)pcb->spcb, pcb->pcbInst, realDetaTime);
190     } else {
191         FillpEnableSendTimer(pcb);
192     }
193 }
194 
FillpEnableSendTimer(struct FillpPcb * pcb)195 void FillpEnableSendTimer(struct FillpPcb *pcb)
196 {
197     if (pcb->send.flowControl.sendInterval < pcb->pcbInst->minSendInterval) {
198         pcb->pcbInst->minSendInterval = pcb->send.flowControl.sendInterval;
199     }
200     if (FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->sendTimerNode)) {
201         return;
202     }
203     FILLP_LOGDBG("enable, pcb->send.flowControl.sendTime:%lld, interval:%u", pcb->send.flowControl.sendTime,
204         pcb->sendTimerNode.interval);
205     if (pcb->send.flowControl.sendTime == 0) {
206         pcb->send.flowControl.remainBytes = 0;
207         pcb->send.flowControl.sendTime = pcb->pcbInst->curTime;
208     }
209     FILLP_LOGDBG("enable time =%lld\t next expire timer=%lld", pcb->pcbInst->curTime,
210         pcb->send.flowControl.sendTime + pcb->sendTimerNode.interval);
211     FillpTimingWheelAddTimer(&pcb->pcbInst->timingWheel,
212         pcb->send.flowControl.sendTime + pcb->sendTimerNode.interval, &pcb->sendTimerNode);
213 }
214 
FillpDisableSendTimer(struct FillpPcb * pcb)215 void FillpDisableSendTimer(struct FillpPcb *pcb)
216 {
217     if (FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->sendTimerNode)) {
218         FillpTimingWheelDelTimer(pcb->sendTimerNode.wheel, &pcb->sendTimerNode);
219     }
220 }
221 
FillpEnablePackTimer(struct FillpPcb * pcb)222 void FillpEnablePackTimer(struct FillpPcb *pcb)
223 {
224     if (!FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->packTimerNode)) {
225         FILLP_LOGDBG("enable time =%lld\t next expire timer=%u", pcb->pcbInst->curTime,
226             pcb->packTimerNode.interval);
227         FillpTimingWheelAddTimer(&pcb->pcbInst->timingWheel,
228             pcb->packTimerNode.interval + pcb->pcbInst->curTime, &pcb->packTimerNode);
229     }
230 }
231 
FillpDisablePackTimer(struct FillpPcb * pcb)232 void FillpDisablePackTimer(struct FillpPcb *pcb)
233 {
234     if (FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->packTimerNode)) {
235         FillpTimingWheelDelTimer(pcb->packTimerNode.wheel, &pcb->packTimerNode);
236     }
237 }
238 
FillpEnableFcTimer(struct FillpPcb * pcb)239 void FillpEnableFcTimer(struct FillpPcb *pcb)
240 {
241     if (!FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->FcTimerNode)) {
242         FillpTimingWheelAddTimer(&pcb->pcbInst->timingWheel,
243             pcb->FcTimerNode.interval + pcb->pcbInst->curTime, &pcb->FcTimerNode);
244     }
245 }
FillpDisableFcTimer(struct FillpPcb * pcb)246 void FillpDisableFcTimer(struct FillpPcb *pcb)
247 {
248     if (FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->FcTimerNode)) {
249         FillpTimingWheelDelTimer(pcb->FcTimerNode.wheel, &pcb->FcTimerNode);
250     }
251 }
252 
FillpEnableKeepAliveTimer(struct FillpPcb * pcb)253 void FillpEnableKeepAliveTimer(struct FillpPcb *pcb)
254 {
255     if (!FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->keepAliveTimerNode)) {
256         FillpTimingWheelAddTimer(&pcb->pcbInst->timingWheel,
257             pcb->keepAliveTimerNode.interval + pcb->pcbInst->curTime, &pcb->keepAliveTimerNode);
258     }
259 }
260 
FillpDisableKeepAliveTimer(struct FillpPcb * pcb)261 void FillpDisableKeepAliveTimer(struct FillpPcb *pcb)
262 {
263     if (FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->keepAliveTimerNode)) {
264         FillpTimingWheelDelTimer(pcb->keepAliveTimerNode.wheel, &pcb->keepAliveTimerNode);
265     }
266 }
267 
FillpEnableDelayNackTimer(struct FillpPcb * pcb)268 void FillpEnableDelayNackTimer(struct FillpPcb *pcb)
269 {
270     if (!FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->delayNackTimerNode)) {
271         FILLP_LOGDBG("Delay NACK Timer Enable: curTime:%lld, interval:%u", pcb->pcbInst->curTime,
272             pcb->delayNackTimerNode.interval);
273         FillpTimingWheelAddTimer(&pcb->pcbInst->timingWheel,
274             pcb->pcbInst->curTime + pcb->delayNackTimerNode.interval, &pcb->delayNackTimerNode);
275     }
276 }
277 
FillpDisableDelayNackTimer(struct FillpPcb * pcb)278 void FillpDisableDelayNackTimer(struct FillpPcb *pcb)
279 {
280     if (FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->delayNackTimerNode)) {
281         FillpTimingWheelDelTimer(pcb->delayNackTimerNode.wheel, &pcb->delayNackTimerNode);
282     }
283 }
284 
FillpEnableDataBurstTimer(struct FillpPcb * pcb)285 void FillpEnableDataBurstTimer(struct FillpPcb *pcb)
286 {
287     if (!FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->dataBurstTimerNode)) {
288         FILLP_LOGDBG("Data Burst Timer Enable: curTime:%lld, interval:%u", pcb->pcbInst->curTime,
289             pcb->dataBurstTimerNode.interval);
290         FillpTimingWheelAddTimer(&pcb->pcbInst->timingWheel,
291             pcb->pcbInst->curTime + pcb->dataBurstTimerNode.interval, &pcb->dataBurstTimerNode);
292     }
293 }
FillpDisableDataBurstTimer(struct FillpPcb * pcb)294 void FillpDisableDataBurstTimer(struct FillpPcb *pcb)
295 {
296     if (FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->dataBurstTimerNode)) {
297         FillpTimingWheelDelTimer(pcb->dataBurstTimerNode.wheel, &pcb->dataBurstTimerNode);
298     }
299 }
300 
FillpEnableConnRetryCheckTimer(struct FillpPcb * pcb)301 void FillpEnableConnRetryCheckTimer(struct FillpPcb *pcb)
302 {
303     if (!FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->connRetryTimeoutTimerNode)) {
304         FillpTimingWheelAddTimer(&pcb->pcbInst->timingWheel,
305             pcb->pcbInst->curTime + pcb->connRetryTimeoutTimerNode.interval, &pcb->connRetryTimeoutTimerNode);
306     }
307 }
FillpDisableConnRetryCheckTimer(struct FillpPcb * pcb)308 void FillpDisableConnRetryCheckTimer(struct FillpPcb *pcb)
309 {
310     if (FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->connRetryTimeoutTimerNode)) {
311         FillpTimingWheelDelTimer(pcb->connRetryTimeoutTimerNode.wheel, &pcb->connRetryTimeoutTimerNode);
312     }
313 }
314 
FillpEnableFinCheckTimer(struct FillpPcb * pcb)315 void FillpEnableFinCheckTimer(struct FillpPcb *pcb)
316 {
317     if (!FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->finCheckTimer)) {
318         FillpTimingWheelAddTimer(&pcb->pcbInst->timingWheel,
319             pcb->pcbInst->curTime + pcb->finCheckTimer.interval, &pcb->finCheckTimer);
320     }
321 }
322 
FillpDisableFinCheckTimer(struct FillpPcb * pcb)323 void FillpDisableFinCheckTimer(struct FillpPcb *pcb)
324 {
325     if (FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->finCheckTimer)) {
326         FillpTimingWheelDelTimer(pcb->finCheckTimer.wheel, &pcb->finCheckTimer);
327     }
328 }
329 
FillpFcTimerCb(void * argPcb)330 void FillpFcTimerCb(void *argPcb)
331 {
332     struct FillpPcb *pcb = (struct FillpPcb *)argPcb;
333 
334     if (pcb->algFuncs.fcTime != FILLP_NULL_PTR) {
335         pcb->algFuncs.fcTime(pcb);
336         FillpEnableFcTimer(pcb);
337     }
338 }
339 
340 #ifdef __cplusplus
341 }
342 #endif
343