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