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 "res.h"
18 #include "opt.h"
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 #define FILLP_PACKET_INTER  2
25 
FillpFreeItemAndEvent(struct FillpPcb * pcb,struct FillpPcbItem * item)26 void FillpFreeItemAndEvent(struct FillpPcb *pcb, struct FillpPcbItem *item)
27 {
28     FillpFreeBufItem(item);
29     (void)SYS_ARCH_ATOMIC_INC(&(FILLP_GET_SOCKET(pcb)->sendEventCount), 1);
30 #ifdef SOCK_SEND_SEM
31     (void)SYS_ARCH_SEM_POST(&pcb->send.sendSem);
32 #endif /* SOCK_SEND_SEM */
33 }
34 
InsertUnrecvListFail(struct FillpPcb * pcb,struct FillpPcbItem * item)35 void InsertUnrecvListFail(struct FillpPcb *pcb, struct FillpPcbItem *item)
36 {
37     FILLP_LOGERR("fillp_sock_id:%d Can't add item <%u,%u> to unrecvList",
38         FILLP_GET_SOCKET(pcb)->index, item->seqNum, item->dataLen);
39     FillpFreeItemAndEvent(pcb, item);
40 }
41 
FillpDelPktSeqHashItem(FILLP_UINT32 pktNum,FILLP_CONST struct FillpHashLlist * mapList)42 static void FillpDelPktSeqHashItem(FILLP_UINT32 pktNum, FILLP_CONST struct FillpHashLlist *mapList)
43 {
44     FILLP_UINT32 hashIndex = (FILLP_UINT32)(pktNum & mapList->hashModSize);
45     struct Hlist *list = &mapList->hashMap[hashIndex];
46 
47     struct HlistNode *pos = HLIST_FIRST(list);
48     struct FillpPcbItem *item = FILLP_NULL_PTR;
49 
50     while (pos != FILLP_NULL_PTR) {
51         item = FillpPcbPktSeqMapNodeEntry(pos);
52 
53         if (item->pktNum == pktNum) {
54             break;
55         } else if (FillpNumIsbigger(item->pktNum, pktNum)) {
56             return;
57         }
58         pos = pos->next;
59     }
60 
61     if (pos != FILLP_NULL_PTR) {
62         HlistDelete(list, pos);
63     }
64 }
65 
FillpMoveUnackToUnrecv(FILLP_UINT32 ackSeq,FILLP_UINT32 lostSeq,struct FillpPcb * pcb,FILLP_BOOL isFromPack)66 void FillpMoveUnackToUnrecv(FILLP_UINT32 ackSeq, FILLP_UINT32 lostSeq, struct FillpPcb *pcb,
67     FILLP_BOOL isFromPack)
68 {
69     FillpMoveUnackToUnrecvAll(ackSeq, lostSeq, pcb, isFromPack, FILLP_FALSE);
70 }
71 
FillpMoveOneNode(struct Hlist * list,FILLP_UINT32 lostSeq,struct FillpPcb * pcb,FILLP_BOOL isFromPack,FILLP_BOOL onePktOnly)72 static FILLP_BOOL FillpMoveOneNode(struct Hlist *list, FILLP_UINT32 lostSeq, struct FillpPcb *pcb,
73     FILLP_BOOL isFromPack, FILLP_BOOL onePktOnly)
74 {
75     FILLP_BOOL pktFound = FILLP_FALSE;
76     struct FillpHashLlist *unackList = &pcb->send.unackList;
77     FILLP_LLONG cmpGap;
78     if (g_resource.retransmitCmpTime) {
79         cmpGap = (FILLP_LLONG)pcb->send.retramistRto;
80     } else {
81         cmpGap = 0;
82     }
83     while (HLIST_FIRST(list) != FILLP_NULL_PTR) {
84         struct FillpPcbItem *item = FillpPcbEntry(HLIST_FIRST(list));
85         if (FillpNumIsbigger(item->seqNum, lostSeq) == FILLP_TRUE) {
86             break;
87         }
88 
89         FILLP_LLONG gap = pcb->pcbInst->curTime - item->lastSendTimestamp;
90         if (gap < cmpGap) {
91             break;
92         }
93 
94         HlistDelete(list, HLIST_FIRST(list));
95         if (unackList->count > 0) {
96             unackList->count--;
97         }
98 
99         if (isFromPack) {
100             pcb->send.inSendBytes -= (FILLP_ULLONG)item->dataLen;
101             item->infCount--;
102         }
103         FillpDelPktSeqHashItem(item->pktNum, &pcb->send.pktSeqMap);
104         if (SkipListInsert(&pcb->send.unrecvList, (void *)item, &item->skipListNode, FILLP_TRUE) !=
105             ERR_OK) {
106             InsertUnrecvListFail(pcb, item);
107             FILLP_LOGERR("fillp_sock_id:%d Can't move to unrecvList from unackList !!!",
108                 FILLP_GET_SOCKET(pcb)->index);
109             break;
110         }
111 
112         pcb->send.unrecvRedunListBytes += item->dataLen;
113         item->sendCount++;
114         if (isFromPack) {
115             item->resendTrigger = (FILLP_UINT8)FILLP_ITEM_RESEND_TRIGGER_PACK;
116         } else { /* item resend triggered by tail protect */
117             item->resendTrigger = (FILLP_UINT8)FILLP_ITEM_RESEND_TRIGGER_TP;
118         }
119         pcb->statistics.appFcStastics.periodSendLostPkts++;
120 
121         if (onePktOnly) {
122             pktFound = FILLP_TRUE;
123             break;
124         }
125     }
126     return pktFound;
127 }
128 
FillpMoveUnackToUnrecvAll(FILLP_UINT32 ackSeq,FILLP_UINT32 lostSeq,struct FillpPcb * pcb,FILLP_BOOL isFromPack,FILLP_BOOL onePktOnly)129 void FillpMoveUnackToUnrecvAll(FILLP_UINT32 ackSeq, FILLP_UINT32 lostSeq, struct FillpPcb *pcb,
130     FILLP_BOOL isFromPack, FILLP_BOOL onePktOnly)
131 {
132     struct FillpHashLlist *unackList = FILLP_NULL_PTR;
133     FILLP_UINT32 i;
134     FILLP_UINT32 ackSeqIndex;
135     FILLP_UINT32 lostSeqIndex;
136     FILLP_UINT32 loopCount;
137     FILLP_UINT32 unackListSize;
138     FILLP_UINT32 hashModSize;
139 
140     if (lostSeq == ackSeq) {
141         return;
142     }
143 
144     ackSeqIndex = FILLP_UNACKLIST_HASHINDEX(ackSeq, pcb);
145     lostSeqIndex = FILLP_UNACKLIST_HASHINDEX(lostSeq, pcb);
146     unackList = &pcb->send.unackList;
147     loopCount = (FILLP_UINT32)((lostSeqIndex + unackList->size - ackSeqIndex) & unackList->hashModSize);
148     unackListSize = unackList->size;
149     hashModSize = unackList->hashModSize;
150 
151     if ((lostSeq - ackSeq) / FILLP_UNACK_HASH_MOD >= unackListSize) {
152         loopCount = unackListSize;
153     }
154 
155     for (i = 0; i <= loopCount; i++) {
156         FILLP_UINT32 hashIndex = (FILLP_UINT32)((i + ackSeqIndex) & hashModSize);
157         struct Hlist *list = &unackList->hashMap[hashIndex];
158 
159         FILLP_BOOL pktFound = FillpMoveOneNode(list, lostSeq, pcb, isFromPack, onePktOnly);
160         if (pktFound == FILLP_TRUE) {
161             break;
162         }
163     }
164 
165     if (pcb->send.unrecvList.nodeNum > 0) {
166         FillpEnableSendTimer(pcb);
167     }
168 }
169 
LogForMsgRTT(const struct FillpPcbItem * item)170 static inline void LogForMsgRTT(const struct FillpPcbItem *item)
171 {
172     if (UTILS_FLAGS_CHECK(item->flags, FILLP_ITEM_FLAGS_LAST_PKT_FOR_CAL_COST)) {
173         FILLP_LOGINF("cost between send-recv: last seq:%u, cost:%lld, size:%u", item->seqNum,
174             (SYS_ARCH_GET_CUR_TIME_LONGLONG() - (FILLP_LLONG)item->appSendTimestamp), item->appSendSize);
175     }
176 }
177 
FillpAckItemWaitTklist(struct FillpPcb * pcb,FILLP_UINT32 seqNum)178 static void FillpAckItemWaitTklist(struct FillpPcb *pcb, FILLP_UINT32 seqNum)
179 {
180     struct SkipListNode *node = FILLP_NULL_PTR;
181     struct FillpPcbItem *item = FILLP_NULL_PTR;
182 
183     if (!FillpNumIsbigger(seqNum, pcb->send.ackSeqNum)) {
184         return;
185     }
186 
187     node = SkipListGetPop(&pcb->send.itemWaitTokenLists);
188     while (node != FILLP_NULL_PTR) {
189         item = (struct FillpPcbItem *)node->item;
190         if (FillpNumIsbigger(item->seqNum, seqNum)) {
191             break;
192         }
193 
194         pcb->send.inSendBytes -= (FILLP_ULLONG)((FILLP_ULLONG)item->dataLen * item->infCount);
195         item->infCount = 0;
196         (void)SkipListPopValue(&pcb->send.itemWaitTokenLists);
197         pcb->pcbInst->stb.waitPktCount--;
198         FillpFreeBufItem(item);
199         (void)SYS_ARCH_ATOMIC_INC(&(FILLP_GET_SOCKET(pcb)->sendEventCount), 1);
200 #ifdef SOCK_SEND_SEM
201         (void)SYS_ARCH_SEM_POST(&pcb->send.send_sem);
202 #endif /* SOCK_SEND_SEM */
203         node = SkipListGetPop(&pcb->send.itemWaitTokenLists);
204     }
205 }
206 
FillpAckUnrecvList(struct FillpPcb * pcb,FILLP_UINT32 seqNum)207 static int FillpAckUnrecvList(struct FillpPcb *pcb, FILLP_UINT32 seqNum)
208 {
209     struct SkipListNode *node = FILLP_NULL_PTR;
210     struct FillpPcbItem *item = FILLP_NULL_PTR;
211     struct FtNetconn *conn = FILLP_GET_CONN(pcb);
212     struct FtSocket *sock = (struct FtSocket *)conn->sock;
213 
214     FILLP_INT count = 0;
215     if (!FillpNumIsbigger(seqNum, pcb->send.ackSeqNum)) {
216         return count;
217     }
218 
219     node = SkipListGetPop(&pcb->send.unrecvList);
220     while (node != FILLP_NULL_PTR) {
221         item = (struct FillpPcbItem *)node->item;
222         if (FillpNumIsbigger(item->seqNum, seqNum)) {
223             break;
224         }
225 
226         (void)SkipListPopValue(&pcb->send.unrecvList);
227 
228         pcb->send.unrecvRedunListBytes -= item->dataLen;
229         pcb->send.inSendBytes -= (FILLP_ULLONG)((FILLP_ULLONG)item->dataLen * item->infCount);
230         item->infCount = 0;
231         FillpFreeBufItem(item);
232         (void)SYS_ARCH_ATOMIC_INC(&sock->sendEventCount, 1);
233 #ifdef SOCK_SEND_SEM
234         (void)SYS_ARCH_SEM_POST(&pcb->send.send_sem);
235 #endif /* SOCK_SEND_SEM */
236         count++;
237         node = SkipListGetPop(&pcb->send.unrecvList);
238     }
239     return count;
240 }
241 
FillpAckRedunlist(struct FillpPcb * pcb,FILLP_UINT32 seqNum)242 static void FillpAckRedunlist(struct FillpPcb *pcb, FILLP_UINT32 seqNum)
243 {
244     struct SkipListNode *node = FILLP_NULL_PTR;
245     struct FillpPcbItem *item = FILLP_NULL_PTR;
246 
247     if (!FillpNumIsbigger(seqNum, pcb->send.ackSeqNum)) {
248         return;
249     }
250 
251     node = SkipListGetPop(&pcb->send.redunList);
252     while (node != FILLP_NULL_PTR) {
253         item = (struct FillpPcbItem *)node->item;
254         if (FillpNumIsbigger(item->seqNum, seqNum)) {
255             break;
256         }
257 
258         pcb->send.unrecvRedunListBytes -= item->dataLen;
259         pcb->send.inSendBytes -= (FILLP_ULLONG)((FILLP_ULLONG)item->dataLen * item->infCount);
260         item->infCount = 0;
261         (void)SkipListPopValue(&pcb->send.redunList);
262         FillpFreeBufItem(item);
263         (void)SYS_ARCH_ATOMIC_INC(&(FILLP_GET_SOCKET(pcb)->sendEventCount), 1);
264 #ifdef SOCK_SEND_SEM
265         (void)SYS_ARCH_SEM_POST(&pcb->send.send_sem);
266 #endif /* SOCK_SEND_SEM */
267         node = SkipListGetPop(&pcb->send.redunList);
268     }
269 }
270 
FreeUnackList(struct FillpPcb * pcb,struct FillpPcbItem * item,struct Hlist * tempCtl)271 static void FreeUnackList(struct FillpPcb *pcb, struct FillpPcbItem *item, struct Hlist *tempCtl)
272 {
273     LogForMsgRTT(item);
274     HlistDelNode(&item->pktSeqMapNode);
275     HlistDelete(tempCtl, HLIST_FIRST(tempCtl));
276 
277     if (pcb->send.unackList.count > 0) {
278         pcb->send.unackList.count--;
279     }
280 
281     pcb->send.inSendBytes -= (FILLP_ULLONG)((FILLP_ULLONG)item->dataLen * item->infCount);
282     item->infCount = 0;
283     FillpFreeItemAndEvent(pcb, item);
284 }
285 
FillpAckUnackList(struct FillpPcb * pcb,FILLP_UINT32 curSeq,FILLP_INT cntLimit)286 IGNORE_OVERFLOW static void FillpAckUnackList(struct FillpPcb *pcb,
287     FILLP_UINT32 curSeq, FILLP_INT cntLimit)
288 {
289     FILLP_UINT32 i, loopCount;
290 
291     struct FtNetconn *conn = FILLP_GET_CONN(pcb);
292     struct FtSocket *sock = (struct FtSocket *)conn->sock;
293 
294     if (!FillpNumIsbigger(curSeq, pcb->send.ackSeqNum)) {
295         return;
296     }
297 
298     FillpAckRedunlist(pcb, curSeq);
299     FillpAckItemWaitTklist(pcb, curSeq);
300 
301     /* 1) First , we ack all unrecvList
302        2) Then , we just try to ack limited unACK items
303        3) If all items acked, then we can set the pcb->send.ackSeqNum = curSeq
304     */
305     FILLP_INT count = FillpAckUnrecvList(pcb, curSeq);
306     if ((cntLimit > 0) && (count >= cntLimit)) {
307         goto END;
308     }
309 
310     struct FillpHashLlist *unackList = &(pcb->send.unackList);
311     FILLP_UINT32 unackListSize = unackList->size;
312     FILLP_UINT32 hashModSize = unackList->hashModSize;
313 
314     FILLP_UINT32 lastSeqIndex = (pcb->send.ackSeqNum / FILLP_UNACK_HASH_MOD) & hashModSize;
315     FILLP_UINT32 curSeqIndex = (curSeq / FILLP_UNACK_HASH_MOD) & hashModSize;
316 
317     // Still need to check if should loop all list
318     if (((curSeq / FILLP_UNACK_HASH_MOD) - (pcb->send.ackSeqNum / FILLP_UNACK_HASH_MOD)) >= unackListSize) {
319         loopCount = unackListSize;
320     } else {
321         loopCount = UTILS_MIN((curSeqIndex + unackListSize - lastSeqIndex) & hashModSize, unackListSize);
322     }
323 
324     for (i = 0; i <= loopCount; i++) {
325         struct Hlist *list = pcb->send.unackList.hashMap;
326         struct Hlist *tempCtl = &list[(i + lastSeqIndex) & hashModSize];
327 
328         while (HLIST_FIRST(tempCtl) != FILLP_NULL_PTR) {
329             struct FillpPcbItem *item = FillpPcbEntry(HLIST_FIRST(tempCtl));
330             if (FillpNumIsbigger(item->seqNum, curSeq) == FILLP_TRUE) {
331                 break;
332             }
333             FreeUnackList(pcb, item, tempCtl);
334             count++;
335             if ((cntLimit > 0) && (count >= cntLimit)) {
336                 goto END;
337             }
338         }
339     }
340 
341 END:
342     if ((count == 0) || (!FillpNumIsbigger(pcb->send.pktSendCache, (curSeq - pcb->send.ackSeqNum)))) {
343         pcb->send.ackSeqNum = curSeq;
344     }
345     SpungeEpollEventCallback(sock, SPUNGE_EPOLLOUT, count);
346 }
347 
FillpAckSendPcb(struct FillpPcb * pcb,FILLP_INT cntLimit)348 IGNORE_OVERFLOW void FillpAckSendPcb(struct FillpPcb *pcb, FILLP_INT cntLimit)
349 {
350     FILLP_UINT32 pktSendCnt;
351     /* ack the item in unackList */
352     FillpAckUnackList(pcb, pcb->send.maxAckNumFromReceiver, cntLimit);
353     pktSendCnt = pcb->send.unackList.count + pcb->send.unrecvList.nodeNum +
354         pcb->send.itemWaitTokenLists.nodeNum + pcb->send.redunList.nodeNum;
355     if (pktSendCnt == 0 && pcb->send.inSendBytes != 0) {
356         FILLP_LOGERR("FillpAckSendPcb  fillp_sock_id:%d   inSendBytes %llu", FILLP_GET_SOCKET(pcb)->index,
357             pcb->send.inSendBytes);
358         pcb->send.inSendBytes = 0;
359     }
360 }
361 
362 #if FILLP_ADHOC_PACK_ENABLE
FillpSendAdhocpack(struct FillpPcb * pcb)363 static void FillpSendAdhocpack(struct FillpPcb *pcb)
364 {
365     struct FillpPktPack pack;
366     struct FtSocket *ftSock;
367 
368     ftSock = FILLP_GET_SOCKET(pcb);
369     (void)memset_s(&pack, sizeof(pack), 0, sizeof(pack));
370     pack.rate = pcb->statistics.pack.periodRecvRate;
371     pack.oppositeSetRate = 0;
372     pack.flag = FILLP_PACK_FLAG_ADHOC;
373     pack.pktLoss = 0;
374     pack.reserved.rtt = 0;
375     pack.lostSeq = pcb->recv.seqNum;
376 
377     FillpBuildAndSendPack(pcb, ftSock, &pack, sizeof(struct FillpPktPack) - FILLP_HLEN);
378 }
379 #endif
380 
FillpUploadRecvBox(struct FillpPcb * pcb)381 IGNORE_OVERFLOW void FillpUploadRecvBox(struct FillpPcb *pcb)
382 {
383     struct FillpPcbItem *item = FILLP_NULL_PTR;
384     struct SkipListNode *node = FILLP_NULL_PTR;
385     struct SkipList *recvList = &pcb->recv.recvList;
386     void *itemPool[FILLP_DEFAULT_RECVBOX_BRUST];
387     FILLP_BOOL needLoopRun = FILLP_TRUE;
388 
389     do {
390         FILLP_INT count = 0;
391 
392         node = SkipListGetPop(recvList);
393         while ((node != FILLP_NULL_PTR) && (count < FILLP_DEFAULT_RECVBOX_BRUST)) {
394             FILLP_UINT32 start_seq;
395             item = (struct FillpPcbItem *)node->item;
396             start_seq = item->seqNum - item->dataLen;
397 
398             /*
399                1.startSeq = recv.seqNum : This pkt is we expected
400                2.startSeq < recv.seqNum : This pkt has been recved
401                3.startSeq > recv.seqNum : There is a gap between this pkt and last recved one
402             */
403             if (start_seq != pcb->recv.seqNum) {
404                 break;
405             }
406 
407             FillpFrameRx(&pcb->frameHandle, item);
408 
409             itemPool[count++] = (void *)item;
410             pcb->recv.seqNum = item->seqNum;
411             pcb->recv.recvBytes -= item->dataLen;
412             (void)SkipListPopValue(recvList);
413             node = SkipListGetPop(recvList);
414         }
415 
416         if (count == 0) {
417             needLoopRun = FILLP_FALSE;
418         }
419 
420         if (count > 0) {
421             if (pcb->recvFunc(FILLP_GET_CONN(pcb), itemPool, count) != ERR_OK) {
422                 FILLP_LOGERR("upload data failed !!!!!!");
423             }
424 
425 #if FILLP_ADHOC_PACK_ENABLE
426             /* if my receive buffer usage goes beyond 5% of the total available
427             buffer occupation, send pack immediately and don't wait for the pack
428             timeout to send it, since it will block the send buffer on sender
429             side */
430             if ((pcb->recv.pktNum - pcb->recv.lastPackPktNum) >= ADHOC_PACK_TRIGGLE_THRESHOLD) {
431                 FILLP_LOGDBG("fillp_sock_id:%d pktNum=%u lastPackPktNum=%u, diff=%u size=%u sending PACK",
432                     FILLP_GET_SOCKET(pcb)->index, pcb->recv.pktNum, pcb->recv.lastPackPktNum,
433                     (pcb->recv.pktNum - pcb->recv.lastPackPktNum), pcb->mpRecvSize);
434 
435                 FillpSendAdhocpack(pcb);
436             }
437 #endif
438         }
439     } while (needLoopRun);
440 }
441 
FillpSendRepaetNack(struct FillpPcb * pcb,struct FillpPktNack * nack)442 static void FillpSendRepaetNack(struct FillpPcb *pcb, struct FillpPktNack *nack)
443 {
444     FILLP_UINT16 i;
445     struct FillpPktNackWithRandnum nackTest;
446     FillpTraceDescriptSt fillpTrcDesc;
447     struct FtSocket *ftSock = (struct FtSocket *)FILLP_GET_CONN(pcb)->sock;
448     fillpTrcDesc.traceDirection = FILLP_TRACE_DIRECT_SEND;
449     (void)memcpy_s(&(nackTest.nack), sizeof(struct FillpPktNack), nack, sizeof(struct FillpPktNack));
450     for (i = 0; i < g_resource.flowControl.nackRepeatTimes; i++) {
451         nackTest.randomNum = FILLP_HTONLL(pcb->send.nackRandomNum + FILLP_RAND());
452         pcb->send.nackRandomNum++;
453         FILLP_INT ret = pcb->sendFunc(FILLP_GET_CONN(pcb), (char *)&nackTest, sizeof(struct FillpPktNackWithRandnum),
454             FILLP_GET_CONN(pcb)->pcb);
455         if (ret <= 0) {
456             pcb->statistics.debugPcb.nackFailed++;
457         } else {
458             /* provide trace without random number, receiver has no logic with this number as it is just added to
459                deceive firewall dropping same packet in short duration */
460             FILLP_LM_FILLPMSGTRACE_OUTPUT(ftSock->traceFlag, FILLP_TRACE_DIRECT_NETWORK, ftSock->traceHandle,
461                 (sizeof(struct FillpPktNackWithRandnum) - sizeof(FILLP_ULLONG)), FILLP_GET_SOCKET(pcb)->index,
462                 (FILLP_UINT8 *)(void *)&fillpTrcDesc, (FILLP_CHAR *)(&nackTest));
463 
464             pcb->statistics.debugPcb.nackSend++;
465         }
466     }
467 }
468 
FillpSendNack(struct FillpPcb * pcb,FILLP_UINT32 startPktNum,FILLP_UINT32 endPktNum)469 void FillpSendNack(struct FillpPcb *pcb, FILLP_UINT32 startPktNum, FILLP_UINT32 endPktNum)
470 {
471     struct FillpPktHead *pktHead = FILLP_NULL_PTR;
472     FILLP_UINT32 pktNum = endPktNum;
473     FILLP_UINT32 lostPktNum = (endPktNum - startPktNum) - 1;
474     struct FillpPktNack *nack = pcb->send.retryNackQueue[pcb->send.retryIndex];
475 
476     if (nack == FILLP_NULL_PTR) {
477         nack = SpungeAlloc(1, sizeof(struct FillpPktNack), SPUNGE_ALLOC_TYPE_CALLOC);
478         if (nack == FILLP_NULL_PTR) {
479             FILLP_LOGERR("fail to allocate memory for retry nack queue");
480             return;
481         }
482         pcb->send.retryNackQueue[pcb->send.retryIndex] = nack;
483     }
484 
485     nack->lastPktNum = FILLP_HTONL(pktNum);
486     pktHead = (struct FillpPktHead *)nack->head;
487     pktHead->flag = 0;
488     FILLP_HEADER_SET_PKT_TYPE(pktHead->flag, FILLP_PKT_TYPE_NACK);
489     FILLP_HEADER_SET_PROTOCOL_VERSION(pktHead->flag, FILLP_PROTOCOL_VERSION_NUMBER);
490     pktHead->flag = FILLP_HTONS(pktHead->flag);
491 
492     pktHead->dataLen = 0;
493     pktHead->dataLen = (FILLP_UINT16)(pktHead->dataLen + sizeof(struct FillpPktNackWithRandnum) - FILLP_HLEN);
494     pktHead->dataLen = FILLP_HTONS(pktHead->dataLen);
495 
496     pktHead->pktNum = FILLP_HTONL(startPktNum);
497     pktHead->seqNum = FILLP_HTONL(pcb->recv.seqNum);
498 
499     FILLP_LOGDBG("fillp_sock_id:%d Send NACK: last : %u, this : %u,  seq: %u", FILLP_GET_SOCKET(pcb)->index, pktNum,
500         (startPktNum - 1), pcb->recv.seqNum);
501 
502     FillpSendRepaetNack(pcb, nack);
503 
504     pcb->send.retryIndex++;
505     if (pcb->send.retryIndex >= pcb->statistics.nack.historyNackQueueLen) {
506         pcb->send.retryIndex = pcb->send.retryIndex % pcb->statistics.nack.historyNackQueueLen;
507     }
508 
509     FillpFcRecvLost(pcb, lostPktNum);
510 }
511 
FillpAddNodeAtDelayNackListTail(struct FillpPcb * pcb,FILLP_UINT32 startPktNum,FILLP_UINT32 endPktNum)512 static void FillpAddNodeAtDelayNackListTail(struct FillpPcb *pcb, FILLP_UINT32 startPktNum, FILLP_UINT32 endPktNum)
513 {
514     struct FtSocket *sock = (struct FtSocket *)((struct FtNetconn *)((struct SpungePcb*)pcb->spcb)->conn)->sock;
515     struct FillpNackNode *nackNode =
516         (struct FillpNackNode *)SpungeAlloc(1, sizeof(struct FillpNackNode), SPUNGE_ALLOC_TYPE_CALLOC);
517     if (nackNode == FILLP_NULL_PTR) {
518         FILLP_LOGERR("Failed allocate memory for FillpNackNode\n");
519         return;
520     }
521     nackNode->startPktNum = startPktNum;
522     nackNode->endPktNum = endPktNum;
523     nackNode->timestamp = pcb->pcbInst->curTime;
524     HlistAddTail(&(pcb->recv.nackList), &(nackNode->hnode));
525     /* Start the delay timer */
526     pcb->delayNackTimerNode.interval = (FILLP_UINT32)sock->resConf.common.nackDelayTimeout;
527     FillpEnableDelayNackTimer(pcb);
528 }
529 
530 /* If the out-of-order packet received, then we need to update the list
531  * Such as the old record is [2,8], some time later , 4 received, then the node should update to [2,4] and [4, 8]
532  */
FillpCheckAndUpdateDelayNackList(struct FillpPcb * pcb,FILLP_UINT32 curRecvPktNum)533 static void FillpCheckAndUpdateDelayNackList(struct FillpPcb *pcb, FILLP_UINT32 curRecvPktNum)
534 {
535     struct HlistNode *node;
536     struct Hlist *list;
537     list = &(pcb->recv.nackList);
538     node = HLIST_FIRST(list);
539 
540     while (node != FILLP_NULL_PTR) {
541         struct FillpNackNode *nackNode = FillpNackNodeEntry(node);
542         FILLP_UINT32 startPktNum = nackNode->startPktNum;
543         FILLP_UINT32 endPktNum = nackNode->endPktNum;
544 
545         if (FillpNumIsbigger(curRecvPktNum, endPktNum)) {
546             node = node->next;
547             continue;
548         } else if (!FillpNumIsbigger(curRecvPktNum, startPktNum)) {
549             break;
550         } else if (curRecvPktNum == endPktNum) {
551             break;
552         }
553 
554         struct FillpNackNode *newNackNode = FILLP_NULL_PTR;
555         if (startPktNum == (FILLP_UINT32)(curRecvPktNum - 1)) {
556             if (startPktNum == (FILLP_UINT32)(endPktNum - FILLP_PACKET_INTER)) {
557                 HlistDelete(list, node);
558                 SpungeFree(nackNode, SPUNGE_ALLOC_TYPE_CALLOC);
559                 nackNode = FILLP_NULL_PTR;
560             } else {
561                 nackNode->startPktNum = curRecvPktNum;
562             }
563             break;
564         }
565 
566         if (curRecvPktNum == (FILLP_UINT32)(endPktNum - 1)) {
567             nackNode->endPktNum = curRecvPktNum;
568             break;
569         }
570 
571         if (pcb->recv.nackList.size >= pcb->mpRecvSize) {
572             break;
573         }
574 
575         newNackNode = (struct FillpNackNode *)SpungeAlloc(1, sizeof(struct FillpNackNode), SPUNGE_ALLOC_TYPE_CALLOC);
576         if (newNackNode == FILLP_NULL_PTR) {
577             FILLP_LOGERR("Failed allocate memory for FillpNackNode\n");
578             return;
579         }
580 
581         newNackNode->startPktNum = curRecvPktNum;
582         newNackNode->endPktNum = nackNode->endPktNum;
583         newNackNode->timestamp = nackNode->timestamp;
584 
585         nackNode->endPktNum = curRecvPktNum;
586 
587         HlistAddAfter(list, node, &(newNackNode->hnode));
588         /* Delay NACK timer is already running, no need to start again here */
589         break;
590     }
591 }
592 
FillBiggerItem(struct FillpPcb * pcb,struct FillpPcbItem * item)593 static void FillBiggerItem(struct FillpPcb *pcb, struct FillpPcbItem *item)
594 {
595     if ((pcb->recv.pktNum + 1) != item->pktNum) {
596         if ((g_appResource.common.enableNackDelay) && (pcb->recv.nackList.size < pcb->mpRecvSize)) {
597             /*
598             1. check if overflow or excess
599             2. check list if full
600             3. try to add this to the list, just the tail
601             4. else
602             one tx_cycle       -------- one rx_cycle
603             send 1,2,3,4,5,6   -------- first recv 1,2,5, nackNode:3,4
604             then recv 3, update nackNode:4,4
605             */
606             FillpAddNodeAtDelayNackListTail(pcb, pcb->recv.pktNum, item->pktNum);
607         } else if (g_appResource.common.enableNackDelay == FILLP_FALSE &&
608             pcb->recv.seqNum != (item->seqNum - item->dataLen)) {
609             FillpSendNack(pcb, pcb->recv.pktNum, item->pktNum);
610             FILLP_LOGDBG("fillp_sock_id:%d seq %u, pktNum : %u, recv.pktNum = %u, deta=%u, dataLen :%u",
611                 FILLP_GET_SOCKET(pcb)->index, item->seqNum, item->pktNum, pcb->recv.pktNum,
612                 item->pktNum - pcb->recv.pktNum, item->dataLen);
613         }
614     }
615 
616     pcb->recv.pktNum = item->pktNum;
617 }
618 
FillpRecvDropItem(struct FillpPcb * pcb,struct FillpPcbItem * item)619 static inline void FillpRecvDropItem(struct FillpPcb *pcb, struct FillpPcbItem *item)
620 {
621     FillpFreeBufItem(item);
622     FillpFcRecvDropOne(pcb);
623 }
624 
FillpDataToStack(struct FillpPcb * pcb,struct FillpPcbItem * item)625 void FillpDataToStack(struct FillpPcb *pcb, struct FillpPcbItem *item)
626 {
627     FILLP_LOGDBG("fillp_sock_id:%d seq %u, pktNum : %u", FILLP_GET_SOCKET(pcb)->index, item->seqNum, item->pktNum);
628 
629     FillpFcDataInput(pcb, (struct FillpPktHead *)(void *)item->buf.p);
630 
631     if (FillpNumIsbigger(item->pktNum, pcb->recv.pktNum)) {
632         FillBiggerItem(pcb, item);
633     } else {
634         if (g_appResource.common.enableNackDelay) {
635             /*
636             pktNum less than lastRecvPktNum
637             1. check this pktNum is legal
638             2. less than the head of list, drop
639             3. greater than head, less than tail of list, update this list
640 
641             the struct member of list node must contain:
642             1. pktNum, current pktNum recv now
643             2. lastPktNum, the pktNum last recv
644             3. timestamp, the time recv, in the main thread check the time past whether more than timeout
645             if more, send the fix list node
646             */
647             if (!FillpNumIsbigger(item->seqNum, pcb->recv.seqNum)) {
648                 FILLP_LOGDBG("fillp_sock_id:%d seq Recved before: start %u, end: %u, pktNum: %u",
649                     FILLP_GET_SOCKET(pcb)->index, pcb->recv.seqNum, item->seqNum, item->pktNum);
650 
651                 FillpRecvDropItem(pcb, item);
652 
653                 return;
654             } else if (pcb->recv.nackList.size) {
655                 FillpCheckAndUpdateDelayNackList(pcb, item->pktNum);
656             }
657         }
658 
659         FillpFcRecvOutOfOrder(pcb);
660     }
661 
662     /* If this seqNum has been recved */
663     if (!FillpNumIsbigger(item->seqNum, pcb->recv.seqNum)) {
664         FILLP_LOGDBG("fillp_sock_id:%d seq Recved before: pcb->recv.seqNum %u, item->seqNum: %u, pktNum: %u",
665             FILLP_GET_SOCKET(pcb)->index, pcb->recv.seqNum, item->seqNum, item->pktNum);
666 
667         FillpRecvDropItem(pcb, item);
668         return;
669     }
670 
671     if (SkipListInsert(&pcb->recv.recvList, (void *)item, &item->skipListNode, FILLP_TRUE)) {
672         FillpRecvDropItem(pcb, item);
673 
674         FILLP_LOGDTL("fillp_sock_id:%d Insert to recvBox error: start %u, end: %u", FILLP_GET_SOCKET(pcb)->index,
675             pcb->recv.seqNum, item->seqNum);
676         return;
677     }
678     pcb->recv.recvBytes += item->dataLen;
679 
680     FillpUploadRecvBox(pcb);
681 }
682 
FillpAjustTlpParameterByRtt(struct FillpPcb * pcb,FILLP_LLONG rtt)683 void FillpAjustTlpParameterByRtt(struct FillpPcb *pcb, FILLP_LLONG rtt)
684 {
685     if (rtt < FILLP_RTT_TIME_LEVEL1) {
686 #ifdef PDT_MIRACAST
687         pcb->send.tailProtect.minJudgeThreshold = FILLP_ONE_THIRD_OF_RTT;
688         pcb->send.tailProtect.maxJudgeThreshold = FILLP_ONE_THIRD_OF_RTT + 1;
689 #else
690         if (rtt < FILLP_RTT_TIME_LEVEL1_HALF) {
691             pcb->send.tailProtect.minJudgeThreshold = FILLP_ONE_THIRD_OF_RTT - 1;
692             pcb->send.tailProtect.maxJudgeThreshold = FILLP_ONE_THIRD_OF_RTT;
693         } else {
694             pcb->send.tailProtect.minJudgeThreshold = FILLP_ONE_THIRD_OF_RTT;
695             pcb->send.tailProtect.maxJudgeThreshold = FILLP_ONE_THIRD_OF_RTT + 1;
696         }
697 #endif
698     } else if (rtt < FILLP_RTT_TIME_LEVEL2) {
699         pcb->send.tailProtect.minJudgeThreshold = FILLP_ONE_FOURTH_OF_RTT;
700         pcb->send.tailProtect.maxJudgeThreshold = FILLP_ONE_FOURTH_OF_RTT + 1;
701     } else {
702         pcb->send.tailProtect.minJudgeThreshold = FILLP_ONE_FIFTH_OF_RTT;
703         pcb->send.tailProtect.maxJudgeThreshold = FILLP_ONE_FIFTH_OF_RTT + 1;
704     }
705 
706     pcb->send.tailProtect.judgeThreshold = pcb->send.tailProtect.minJudgeThreshold;
707 }
708 
FillpCalPackInterval(struct FillpPcb * pcb)709 static void FillpCalPackInterval(struct FillpPcb *pcb)
710 {
711     if (pcb->algFuncs.calPackInterval != FILLP_NULL_PTR) {
712         pcb->algFuncs.calPackInterval(pcb);
713     }
714     pcb->packTimerNode.interval = pcb->statistics.pack.packInterval;
715     pcb->send.retramistRto = pcb->rtt;
716 
717     pcb->statistics.pack.packIntervalBackup = pcb->statistics.pack.packInterval;
718     pcb->statistics.debugPcb.curPackDeltaUs = pcb->statistics.pack.packIntervalBackup;
719 
720     /* Update the fc_pack_timer */
721     FILLP_UINT32 packInterval = FillpGetSockPackInterval(pcb);
722     if ((pcb->rtt / FILLP_FC_RTT_PACK_RATIO) < packInterval) {
723         pcb->FcTimerNode.interval = packInterval;
724     } else {
725         pcb->FcTimerNode.interval = (FILLP_UINT32)(pcb->rtt / FILLP_FC_RTT_PACK_RATIO);
726     }
727 
728     FILLP_LOGDTL("fillp_sock_id:%d, packInterval:%u, fcTime:%u, RTT:%llu, minPackInterval:%u, retransmitRTO:%llu",
729         FILLP_GET_SOCKET(pcb)->index, pcb->packTimerNode.interval, pcb->FcTimerNode.interval, pcb->rtt,
730         packInterval, pcb->send.retramistRto);
731 }
732 
FillpCalNackDelayTimeByPackInterval(struct FillpPcb * pcb)733 static void FillpCalNackDelayTimeByPackInterval(struct FillpPcb *pcb)
734 {
735     struct FtNetconn *conn = FILLP_GET_CONN(pcb);
736     struct FtSocket *sock = FILLP_NULL_PTR;
737     if (conn == FILLP_NULL_PTR) {
738         FILLP_LOGERR("netconn is NULl");
739         return;
740     }
741     sock = (struct FtSocket *)conn->sock;
742     if (sock == FILLP_NULL_PTR) {
743         FILLP_LOGERR("sock is NULL");
744         return;
745     }
746 
747     /* nack_delay timeout depend on pack interval, there threshold is 5000us */
748     if (pcb->statistics.pack.packInterval > 5000) {
749         sock->resConf.common.nackDelayTimeout = pcb->statistics.pack.packInterval - FILLP_INTERVAL_THRESHOLD;
750     }
751     sock->resConf.common.nackDelayTimeout = UTILS_MAX(sock->resConf.common.nackDelayTimeout,
752         FILLP_INTERVAL_DEFAULT);
753 }
754 
FillpAdjustFcParamsByRtt(struct FillpPcb * pcb)755 void FillpAdjustFcParamsByRtt(struct FillpPcb *pcb)
756 {
757     FillpCalPackInterval(pcb);
758     FillpCalNackDelayTimeByPackInterval(pcb);
759 
760     FillpAjustTlpParameterByRtt(pcb, (FILLP_LLONG)pcb->rtt);
761     pcb->statistics.appFcStastics.periodRtt = (FILLP_UINT32)FILLP_UTILS_US2MS(pcb->rtt);
762 }
763 
FillpBuildAndSendPack(struct FillpPcb * pcb,struct FtSocket * ftSock,struct FillpPktPack * pack,FILLP_UINT16 dataLen)764 void FillpBuildAndSendPack(struct FillpPcb *pcb, struct FtSocket *ftSock, struct FillpPktPack *pack,
765     FILLP_UINT16 dataLen)
766 {
767     FILLP_INT ret;
768     FILLP_UINT tmpDataLen;
769     FillpTraceDescriptSt fillpTrcDesc;
770     struct FillpPktHead *pktHead = (struct FillpPktHead *)pack->head;
771     pktHead->seqNum = pcb->recv.seqNum;
772     pktHead->dataLen = dataLen;
773 
774     /* 0 converted to network order is also 0, hence explicit conversion not applied */
775     if ((pack->flag & FILLP_PACK_FLAG_ADHOC) == 0) {
776         pktHead->pktNum = pcb->recv.pktNum;
777     }
778 
779     pktHead->flag = 0;
780     FILLP_HEADER_SET_PKT_TYPE(pktHead->flag, FILLP_PKT_TYPE_PACK);
781     FILLP_HEADER_SET_PROTOCOL_VERSION(pktHead->flag, FILLP_PROTOCOL_VERSION_NUMBER);
782     pktHead->flag = FILLP_HTONS(pktHead->flag);
783     tmpDataLen = pktHead->dataLen;
784     pktHead->dataLen = FILLP_HTONS(pktHead->dataLen);
785     pktHead->seqNum = FILLP_HTONL(pcb->recv.seqNum);
786     pktHead->pktNum = FILLP_HTONL(pcb->recv.pktNum);
787     pcb->recv.lastPackPktNum = pcb->recv.pktNum;
788     pcb->recv.lastPackSeqNum = pcb->recv.seqNum;
789 
790     pack->flag = FILLP_HTONS(pack->flag);
791     pack->pktLoss = FILLP_HTONS(pcb->statistics.pack.periodRecvPktLoss);
792     pack->rate = FILLP_HTONL(pcb->statistics.pack.periodRecvRate);
793     pack->oppositeSetRate = FILLP_HTONL(pack->oppositeSetRate);
794     pack->lostSeq = FILLP_HTONL(pack->lostSeq);
795     pack->reserved.rtt = FILLP_HTONL(pack->reserved.rtt);
796     pack->bgnPktNum = FILLP_HTONL(pack->bgnPktNum);
797     pack->endPktNum = FILLP_HTONL(pack->endPktNum);
798     pack->optsOffset = FILLP_HTONS(pack->optsOffset);
799     pack->rcvListBytes = FILLP_HTONL(pack->rcvListBytes);
800 
801     pcb->send.packRandomNum++;
802     ret = pcb->sendFunc(FILLP_GET_CONN(pcb), (char *)pack, (FILLP_INT)(tmpDataLen + FILLP_HLEN),
803         (struct SpungePcb *)pcb->spcb);
804     if (ret <= 0) {
805         pcb->statistics.debugPcb.packFailed++;
806     } else {
807         fillpTrcDesc.traceDirection = FILLP_TRACE_DIRECT_SEND;
808         if (ftSock != FILLP_NULL_PTR) {
809             FILLP_LM_FILLPMSGTRACE_OUTPUT(ftSock->traceFlag, FILLP_TRACE_DIRECT_NETWORK, ftSock->traceHandle,
810                 sizeof(struct FillpPktPack), FILLP_GET_SOCKET(pcb)->index,
811                 (FILLP_UINT8 *)(void *)&fillpTrcDesc, (FILLP_CHAR *)(pack));
812         }
813         pcb->statistics.debugPcb.packSend++;
814     }
815 }
816 
817 #ifdef __cplusplus
818 }
819 #endif
820