• 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 
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 static void FillpAckUnackList(struct FillpPcb *pcb, FILLP_UINT32 curSeq, FILLP_INT cntLimit)
287 {
288     FILLP_UINT32 i, loopCount;
289 
290     struct FtNetconn *conn = FILLP_GET_CONN(pcb);
291     struct FtSocket *sock = (struct FtSocket *)conn->sock;
292 
293     if (!FillpNumIsbigger(curSeq, pcb->send.ackSeqNum)) {
294         return;
295     }
296 
297     FillpAckRedunlist(pcb, curSeq);
298     FillpAckItemWaitTklist(pcb, curSeq);
299 
300     /* 1) First , we ack all unrecvList
301        2) Then , we just try to ack limited unACK items
302        3) If all items acked, then we can set the pcb->send.ackSeqNum = curSeq
303     */
304     FILLP_INT count = FillpAckUnrecvList(pcb, curSeq);
305     if ((cntLimit > 0) && (count >= cntLimit)) {
306         goto END;
307     }
308 
309     struct FillpHashLlist *unackList = &(pcb->send.unackList);
310     FILLP_UINT32 unackListSize = unackList->size;
311     FILLP_UINT32 hashModSize = unackList->hashModSize;
312 
313     FILLP_UINT32 lastSeqIndex = (pcb->send.ackSeqNum / FILLP_UNACK_HASH_MOD) & hashModSize;
314     FILLP_UINT32 curSeqIndex = (curSeq / FILLP_UNACK_HASH_MOD) & hashModSize;
315 
316     // Still need to check if should loop all list
317     if (((curSeq / FILLP_UNACK_HASH_MOD) - (pcb->send.ackSeqNum / FILLP_UNACK_HASH_MOD)) >= unackListSize) {
318         loopCount = unackListSize;
319     } else {
320         loopCount = UTILS_MIN((curSeqIndex + unackListSize - lastSeqIndex) & hashModSize, unackListSize);
321     }
322 
323     for (i = 0; i <= loopCount; i++) {
324         struct Hlist *list = pcb->send.unackList.hashMap;
325         struct Hlist *tempCtl = &list[(i + lastSeqIndex) & hashModSize];
326 
327         while (HLIST_FIRST(tempCtl) != FILLP_NULL_PTR) {
328             struct FillpPcbItem *item = FillpPcbEntry(HLIST_FIRST(tempCtl));
329             if (FillpNumIsbigger(item->seqNum, curSeq) == FILLP_TRUE) {
330                 break;
331             }
332             FreeUnackList(pcb, item, tempCtl);
333             count++;
334             if ((cntLimit > 0) && (count >= cntLimit)) {
335                 goto END;
336             }
337         }
338     }
339 
340 END:
341     if ((count == 0) || (!FillpNumIsbigger(pcb->send.pktSendCache, (curSeq - pcb->send.ackSeqNum)))) {
342         pcb->send.ackSeqNum = curSeq;
343     }
344     SpungeEpollEventCallback(sock, SPUNGE_EPOLLOUT, count);
345 }
346 
FillpAckSendPcb(struct FillpPcb * pcb,FILLP_INT cntLimit)347 void FillpAckSendPcb(struct FillpPcb *pcb, FILLP_INT cntLimit)
348 {
349     FILLP_UINT32 pktSendCnt;
350     /* ack the item in unackList */
351     FillpAckUnackList(pcb, pcb->send.maxAckNumFromReceiver, cntLimit);
352     pktSendCnt = pcb->send.unackList.count + pcb->send.unrecvList.nodeNum +
353         pcb->send.itemWaitTokenLists.nodeNum + pcb->send.redunList.nodeNum;
354     if (pktSendCnt == 0 && pcb->send.inSendBytes != 0) {
355         FILLP_LOGERR("FillpAckSendPcb  fillp_sock_id:%d   inSendBytes %llu", FILLP_GET_SOCKET(pcb)->index,
356             pcb->send.inSendBytes);
357         pcb->send.inSendBytes = 0;
358     }
359 }
360 
361 #if FILLP_ADHOC_PACK_ENABLE
FillpSendAdhocpack(struct FillpPcb * pcb)362 static void FillpSendAdhocpack(struct FillpPcb *pcb)
363 {
364     struct FillpPktPack pack;
365     struct FtSocket *ftSock;
366 
367     ftSock = FILLP_GET_SOCKET(pcb);
368     (void)memset_s(&pack, sizeof(pack), 0, sizeof(pack));
369     pack.rate = pcb->statistics.pack.periodRecvRate;
370     pack.oppositeSetRate = 0;
371     pack.flag = FILLP_PACK_FLAG_ADHOC;
372     pack.pktLoss = 0;
373     pack.reserved.rtt = 0;
374     pack.lostSeq = pcb->recv.seqNum;
375 
376     FillpBuildAndSendPack(pcb, ftSock, &pack, sizeof(struct FillpPktPack) - FILLP_HLEN);
377 }
378 #endif
379 
FillpUploadRecvBox(struct FillpPcb * pcb)380 void FillpUploadRecvBox(struct FillpPcb *pcb)
381 {
382     struct FillpPcbItem *item = FILLP_NULL_PTR;
383     struct SkipListNode *node = FILLP_NULL_PTR;
384     struct SkipList *recvList = &pcb->recv.recvList;
385     void *itemPool[FILLP_DEFAULT_RECVBOX_BRUST];
386     FILLP_BOOL needLoopRun = FILLP_TRUE;
387 
388     do {
389         FILLP_INT count = 0;
390 
391         node = SkipListGetPop(recvList);
392         while ((node != FILLP_NULL_PTR) && (count < FILLP_DEFAULT_RECVBOX_BRUST)) {
393             FILLP_UINT32 start_seq;
394             item = (struct FillpPcbItem *)node->item;
395             start_seq = item->seqNum - item->dataLen;
396 
397             /*
398                1.startSeq = recv.seqNum : This pkt is we expected
399                2.startSeq < recv.seqNum : This pkt has been recved
400                3.startSeq > recv.seqNum : There is a gap between this pkt and last recved one
401             */
402             if (start_seq != pcb->recv.seqNum) {
403                 break;
404             }
405 
406             FillpFrameRx(&pcb->frameHandle, item);
407 
408             itemPool[count++] = (void *)item;
409             pcb->recv.seqNum = item->seqNum;
410             pcb->recv.recvBytes -= item->dataLen;
411             (void)SkipListPopValue(recvList);
412             node = SkipListGetPop(recvList);
413         }
414 
415         if (count == 0) {
416             needLoopRun = FILLP_FALSE;
417         }
418 
419         if (count > 0) {
420             if (pcb->recvFunc(FILLP_GET_CONN(pcb), itemPool, count) != ERR_OK) {
421                 FILLP_LOGERR("upload data failed !!!!!!");
422             }
423 
424 #if FILLP_ADHOC_PACK_ENABLE
425             /* if my receive buffer usage goes beyond 5% of the total available
426             buffer occupation, send pack immediately and don't wait for the pack
427             timeout to send it, since it will block the send buffer on sender
428             side */
429             if ((pcb->recv.pktNum - pcb->recv.lastPackPktNum) >= ADHOC_PACK_TRIGGLE_THRESHOLD) {
430                 FILLP_LOGDBG("fillp_sock_id:%d pktNum=%u lastPackPktNum=%u, diff=%u size=%u sending PACK",
431                     FILLP_GET_SOCKET(pcb)->index, pcb->recv.pktNum, pcb->recv.lastPackPktNum,
432                     (pcb->recv.pktNum - pcb->recv.lastPackPktNum), pcb->mpRecvSize);
433 
434                 FillpSendAdhocpack(pcb);
435             }
436 #endif
437         }
438     } while (needLoopRun);
439 }
440 
FillpSendRepaetNack(struct FillpPcb * pcb,struct FillpPktNack * nack)441 static void FillpSendRepaetNack(struct FillpPcb *pcb, struct FillpPktNack *nack)
442 {
443     FILLP_UINT16 i;
444     struct FillpPktNackWithRandnum nackTest;
445     FillpTraceDescriptSt fillpTrcDesc;
446     struct FtSocket *ftSock = (struct FtSocket *)FILLP_GET_CONN(pcb)->sock;
447     fillpTrcDesc.traceDirection = FILLP_TRACE_DIRECT_SEND;
448     (void)memcpy_s(&(nackTest.nack), sizeof(struct FillpPktNack), nack, sizeof(struct FillpPktNack));
449     for (i = 0; i < g_resource.flowControl.nackRepeatTimes; i++) {
450         nackTest.randomNum = FILLP_HTONLL(pcb->send.nackRandomNum + FILLP_RAND());
451         pcb->send.nackRandomNum++;
452         FILLP_INT ret = pcb->sendFunc(FILLP_GET_CONN(pcb), (char *)&nackTest, sizeof(struct FillpPktNackWithRandnum),
453             FILLP_GET_CONN(pcb)->pcb);
454         if (ret <= 0) {
455             pcb->statistics.debugPcb.nackFailed++;
456         } else {
457             /* provide trace without random number, receiver has no logic with this number as it is just added to
458                deceive firewall dropping same packet in short duration */
459             FILLP_LM_FILLPMSGTRACE_OUTPUT(ftSock->traceFlag, FILLP_TRACE_DIRECT_NETWORK, ftSock->traceHandle,
460                 (sizeof(struct FillpPktNackWithRandnum) - sizeof(FILLP_ULLONG)), FILLP_GET_SOCKET(pcb)->index,
461                 (FILLP_UINT8 *)(void *)&fillpTrcDesc, (FILLP_CHAR *)(&nackTest));
462 
463             pcb->statistics.debugPcb.nackSend++;
464         }
465     }
466 }
467 
FillpSendNack(struct FillpPcb * pcb,FILLP_UINT32 startPktNum,FILLP_UINT32 endPktNum)468 void FillpSendNack(struct FillpPcb *pcb, FILLP_UINT32 startPktNum, FILLP_UINT32 endPktNum)
469 {
470     struct FillpPktHead *pktHead = FILLP_NULL_PTR;
471     FILLP_UINT32 pktNum = endPktNum;
472     FILLP_UINT32 lostPktNum = (endPktNum - startPktNum) - 1;
473     struct FillpPktNack *nack = pcb->send.retryNackQueue[pcb->send.retryIndex];
474 
475     if (nack == FILLP_NULL_PTR) {
476         nack = SpungeAlloc(1, sizeof(struct FillpPktNack), SPUNGE_ALLOC_TYPE_CALLOC);
477         if (nack == FILLP_NULL_PTR) {
478             FILLP_LOGERR("fail to allocate memory for retry nack queue");
479             return;
480         }
481         pcb->send.retryNackQueue[pcb->send.retryIndex] = nack;
482     }
483 
484     nack->lastPktNum = FILLP_HTONL(pktNum);
485     pktHead = (struct FillpPktHead *)nack->head;
486     pktHead->flag = 0;
487     FILLP_HEADER_SET_PKT_TYPE(pktHead->flag, FILLP_PKT_TYPE_NACK);
488     FILLP_HEADER_SET_PROTOCOL_VERSION(pktHead->flag, FILLP_PROTOCOL_VERSION_NUMBER);
489     pktHead->flag = FILLP_HTONS(pktHead->flag);
490 
491     pktHead->dataLen = 0;
492     pktHead->dataLen = (FILLP_UINT16)(pktHead->dataLen + sizeof(struct FillpPktNackWithRandnum) - FILLP_HLEN);
493     pktHead->dataLen = FILLP_HTONS(pktHead->dataLen);
494 
495     pktHead->pktNum = FILLP_HTONL(startPktNum);
496     pktHead->seqNum = FILLP_HTONL(pcb->recv.seqNum);
497 
498     FILLP_LOGDBG("fillp_sock_id:%d Send NACK: last : %u, this : %u,  seq: %u", FILLP_GET_SOCKET(pcb)->index, pktNum,
499         (startPktNum - 1), pcb->recv.seqNum);
500 
501     FillpSendRepaetNack(pcb, nack);
502 
503     pcb->send.retryIndex++;
504     if (pcb->send.retryIndex >= pcb->statistics.nack.historyNackQueueLen) {
505         pcb->send.retryIndex = pcb->send.retryIndex % pcb->statistics.nack.historyNackQueueLen;
506     }
507 
508     FillpFcRecvLost(pcb, lostPktNum);
509 }
510 
FillpAddNodeAtDelayNackListTail(struct FillpPcb * pcb,FILLP_UINT32 startPktNum,FILLP_UINT32 endPktNum)511 static void FillpAddNodeAtDelayNackListTail(struct FillpPcb *pcb, FILLP_UINT32 startPktNum, FILLP_UINT32 endPktNum)
512 {
513     struct FtSocket *sock = (struct FtSocket *)((struct FtNetconn *)((struct SpungePcb*)pcb->spcb)->conn)->sock;
514     struct FillpNackNode *nackNode =
515         (struct FillpNackNode *)SpungeAlloc(1, sizeof(struct FillpNackNode), SPUNGE_ALLOC_TYPE_CALLOC);
516     if (nackNode == FILLP_NULL_PTR) {
517         FILLP_LOGERR("Failed allocate memory for FillpNackNode\n");
518         return;
519     }
520     nackNode->startPktNum = startPktNum;
521     nackNode->endPktNum = endPktNum;
522     nackNode->timestamp = pcb->pcbInst->curTime;
523     HlistAddTail(&(pcb->recv.nackList), &(nackNode->hnode));
524     /* Start the delay timer */
525     pcb->delayNackTimerNode.interval = (FILLP_UINT32)sock->resConf.common.nackDelayTimeout;
526     FillpEnableDelayNackTimer(pcb);
527 }
528 
529 /* If the out-of-order packet received, then we need to update the list
530  * Such as the old record is [2,8], some time later , 4 received, then the node should update to [2,4] and [4, 8]
531  */
FillpCheckAndUpdateDelayNackList(struct FillpPcb * pcb,FILLP_UINT32 curRecvPktNum)532 static void FillpCheckAndUpdateDelayNackList(struct FillpPcb *pcb, FILLP_UINT32 curRecvPktNum)
533 {
534     struct HlistNode *node;
535     struct Hlist *list;
536     list = &(pcb->recv.nackList);
537     node = HLIST_FIRST(list);
538 
539     while (node != FILLP_NULL_PTR) {
540         struct FillpNackNode *nackNode = FillpNackNodeEntry(node);
541         FILLP_UINT32 startPktNum = nackNode->startPktNum;
542         FILLP_UINT32 endPktNum = nackNode->endPktNum;
543 
544         if (FillpNumIsbigger(curRecvPktNum, endPktNum)) {
545             node = node->next;
546             continue;
547         } else if (!FillpNumIsbigger(curRecvPktNum, startPktNum)) {
548             break;
549         } else if (curRecvPktNum == endPktNum) {
550             break;
551         }
552 
553         struct FillpNackNode *newNackNode = FILLP_NULL_PTR;
554         if (startPktNum == (FILLP_UINT32)(curRecvPktNum - 1)) {
555             if (startPktNum == (FILLP_UINT32)(endPktNum - FILLP_PACKET_INTER)) {
556                 HlistDelete(list, node);
557                 SpungeFree(nackNode, SPUNGE_ALLOC_TYPE_CALLOC);
558                 nackNode = FILLP_NULL_PTR;
559             } else {
560                 nackNode->startPktNum = curRecvPktNum;
561             }
562             break;
563         }
564 
565         if (curRecvPktNum == (FILLP_UINT32)(endPktNum - 1)) {
566             nackNode->endPktNum = curRecvPktNum;
567             break;
568         }
569 
570         if (pcb->recv.nackList.size >= pcb->mpRecvSize) {
571             break;
572         }
573 
574         newNackNode = (struct FillpNackNode *)SpungeAlloc(1, sizeof(struct FillpNackNode), SPUNGE_ALLOC_TYPE_CALLOC);
575         if (newNackNode == FILLP_NULL_PTR) {
576             FILLP_LOGERR("Failed allocate memory for FillpNackNode\n");
577             return;
578         }
579 
580         newNackNode->startPktNum = curRecvPktNum;
581         newNackNode->endPktNum = nackNode->endPktNum;
582         newNackNode->timestamp = nackNode->timestamp;
583 
584         nackNode->endPktNum = curRecvPktNum;
585 
586         HlistAddAfter(list, node, &(newNackNode->hnode));
587         /* Delay NACK timer is already running, no need to start again here */
588         break;
589     }
590 }
591 
FillBiggerItem(struct FillpPcb * pcb,struct FillpPcbItem * item)592 static void FillBiggerItem(struct FillpPcb *pcb, struct FillpPcbItem *item)
593 {
594     if ((pcb->recv.pktNum + 1) != item->pktNum) {
595         if ((g_appResource.common.enableNackDelay) && (pcb->recv.nackList.size < pcb->mpRecvSize)) {
596             /*
597             1. check if overflow or excess
598             2. check list if full
599             3. try to add this to the list, just the tail
600             4. else
601             one tx_cycle       -------- one rx_cycle
602             send 1,2,3,4,5,6   -------- first recv 1,2,5, nackNode:3,4
603             then recv 3, update nackNode:4,4
604             */
605             FillpAddNodeAtDelayNackListTail(pcb, pcb->recv.pktNum, item->pktNum);
606         } else if (g_appResource.common.enableNackDelay == FILLP_FALSE &&
607             pcb->recv.seqNum != (item->seqNum - item->dataLen)) {
608             FillpSendNack(pcb, pcb->recv.pktNum, item->pktNum);
609             FILLP_LOGDBG("fillp_sock_id:%d seq %u, pktNum : %u, recv.pktNum = %u, deta=%u, dataLen :%u",
610                 FILLP_GET_SOCKET(pcb)->index, item->seqNum, item->pktNum, pcb->recv.pktNum,
611                 item->pktNum - pcb->recv.pktNum, item->dataLen);
612         }
613     }
614 
615     pcb->recv.pktNum = item->pktNum;
616 }
617 
FillpRecvDropItem(struct FillpPcb * pcb,struct FillpPcbItem * item)618 static inline void FillpRecvDropItem(struct FillpPcb *pcb, struct FillpPcbItem *item)
619 {
620     FillpFreeBufItem(item);
621     FillpFcRecvDropOne(pcb);
622 }
623 
FillpDataToStack(struct FillpPcb * pcb,struct FillpPcbItem * item)624 void FillpDataToStack(struct FillpPcb *pcb, struct FillpPcbItem *item)
625 {
626     FILLP_LOGDBG("fillp_sock_id:%d seq %u, pktNum : %u", FILLP_GET_SOCKET(pcb)->index, item->seqNum, item->pktNum);
627 
628     FillpFcDataInput(pcb, (struct FillpPktHead *)(void *)item->buf.p);
629 
630     if (FillpNumIsbigger(item->pktNum, pcb->recv.pktNum)) {
631         FillBiggerItem(pcb, item);
632     } else {
633         if (g_appResource.common.enableNackDelay) {
634             /*
635             pktNum less than lastRecvPktNum
636             1. check this pktNum is legal
637             2. less than the head of list, drop
638             3. greater than head, less than tail of list, update this list
639 
640             the struct member of list node must contain:
641             1. pktNum, current pktNum recv now
642             2. lastPktNum, the pktNum last recv
643             3. timestamp, the time recv, in the main thread check the time past whether more than timeout
644             if more, send the fix list node
645             */
646             if (!FillpNumIsbigger(item->seqNum, pcb->recv.seqNum)) {
647                 FILLP_LOGDBG("fillp_sock_id:%d seq Recved before: start %u, end: %u, pktNum: %u",
648                     FILLP_GET_SOCKET(pcb)->index, pcb->recv.seqNum, item->seqNum, item->pktNum);
649 
650                 FillpRecvDropItem(pcb, item);
651 
652                 return;
653             } else if (pcb->recv.nackList.size) {
654                 FillpCheckAndUpdateDelayNackList(pcb, item->pktNum);
655             }
656         }
657 
658         FillpFcRecvOutOfOrder(pcb);
659     }
660 
661     /* If this seqNum has been recved */
662     if (!FillpNumIsbigger(item->seqNum, pcb->recv.seqNum)) {
663         FILLP_LOGDBG("fillp_sock_id:%d seq Recved before: pcb->recv.seqNum %u, item->seqNum: %u, pktNum: %u",
664             FILLP_GET_SOCKET(pcb)->index, pcb->recv.seqNum, item->seqNum, item->pktNum);
665 
666         FillpRecvDropItem(pcb, item);
667         return;
668     }
669 
670     if (SkipListInsert(&pcb->recv.recvList, (void *)item, &item->skipListNode, FILLP_TRUE)) {
671         FillpRecvDropItem(pcb, item);
672 
673         FILLP_LOGDTL("fillp_sock_id:%d Insert to recvBox error: start %u, end: %u", FILLP_GET_SOCKET(pcb)->index,
674             pcb->recv.seqNum, item->seqNum);
675         return;
676     }
677     pcb->recv.recvBytes += item->dataLen;
678 
679     FillpUploadRecvBox(pcb);
680 }
681 
FillpAjustTlpParameterByRtt(struct FillpPcb * pcb,FILLP_LLONG rtt)682 void FillpAjustTlpParameterByRtt(struct FillpPcb *pcb, FILLP_LLONG rtt)
683 {
684     if (rtt < FILLP_RTT_TIME_LEVEL1) {
685 #ifdef PDT_MIRACAST
686         pcb->send.tailProtect.minJudgeThreshold = FILLP_ONE_THIRD_OF_RTT;
687         pcb->send.tailProtect.maxJudgeThreshold = FILLP_ONE_THIRD_OF_RTT + 1;
688 #else
689         if (rtt < FILLP_RTT_TIME_LEVEL1_HALF) {
690             pcb->send.tailProtect.minJudgeThreshold = FILLP_ONE_THIRD_OF_RTT - 1;
691             pcb->send.tailProtect.maxJudgeThreshold = FILLP_ONE_THIRD_OF_RTT;
692         } else {
693             pcb->send.tailProtect.minJudgeThreshold = FILLP_ONE_THIRD_OF_RTT;
694             pcb->send.tailProtect.maxJudgeThreshold = FILLP_ONE_THIRD_OF_RTT + 1;
695         }
696 #endif
697     } else if (rtt < FILLP_RTT_TIME_LEVEL2) {
698         pcb->send.tailProtect.minJudgeThreshold = FILLP_ONE_FOURTH_OF_RTT;
699         pcb->send.tailProtect.maxJudgeThreshold = FILLP_ONE_FOURTH_OF_RTT + 1;
700     } else {
701         pcb->send.tailProtect.minJudgeThreshold = FILLP_ONE_FIFTH_OF_RTT;
702         pcb->send.tailProtect.maxJudgeThreshold = FILLP_ONE_FIFTH_OF_RTT + 1;
703     }
704 
705     pcb->send.tailProtect.judgeThreshold = pcb->send.tailProtect.minJudgeThreshold;
706 }
707 
FillpCalPackInterval(struct FillpPcb * pcb)708 static void FillpCalPackInterval(struct FillpPcb *pcb)
709 {
710     if (pcb->algFuncs.calPackInterval != FILLP_NULL_PTR) {
711         pcb->algFuncs.calPackInterval(pcb);
712     }
713     pcb->packTimerNode.interval = pcb->statistics.pack.packInterval;
714     pcb->send.retramistRto = pcb->rtt;
715 
716     pcb->statistics.pack.packIntervalBackup = pcb->statistics.pack.packInterval;
717     pcb->statistics.debugPcb.curPackDeltaUs = pcb->statistics.pack.packIntervalBackup;
718 
719     /* Update the fc_pack_timer */
720     FILLP_UINT32 packInterval = FillpGetSockPackInterval(pcb);
721     if ((pcb->rtt / FILLP_FC_RTT_PACK_RATIO) < packInterval) {
722         pcb->FcTimerNode.interval = packInterval;
723     } else {
724         pcb->FcTimerNode.interval = (FILLP_UINT32)(pcb->rtt / FILLP_FC_RTT_PACK_RATIO);
725     }
726 
727     FILLP_LOGDTL("fillp_sock_id:%d, packInterval:%u, fcTime:%u, RTT:%llu, minPackInterval:%u, retransmitRTO:%llu",
728         FILLP_GET_SOCKET(pcb)->index, pcb->packTimerNode.interval, pcb->FcTimerNode.interval, pcb->rtt,
729         packInterval, pcb->send.retramistRto);
730 }
731 
FillpCalNackDelayTimeByPackInterval(struct FillpPcb * pcb)732 static void FillpCalNackDelayTimeByPackInterval(struct FillpPcb *pcb)
733 {
734     struct FtNetconn *conn = FILLP_GET_CONN(pcb);
735     struct FtSocket *sock = FILLP_NULL_PTR;
736     if (conn == FILLP_NULL_PTR) {
737         FILLP_LOGERR("netconn is NULl");
738         return;
739     }
740     sock = (struct FtSocket *)conn->sock;
741     if (sock == FILLP_NULL_PTR) {
742         FILLP_LOGERR("sock is NULL");
743         return;
744     }
745 
746     /* nack_delay timeout depend on pack interval, there threshold is 5000us */
747     if (pcb->statistics.pack.packInterval > 5000) {
748         sock->resConf.common.nackDelayTimeout = pcb->statistics.pack.packInterval - FILLP_INTERVAL_THRESHOLD;
749     }
750     sock->resConf.common.nackDelayTimeout = UTILS_MAX(sock->resConf.common.nackDelayTimeout,
751         FILLP_INTERVAL_DEFAULT);
752 }
753 
FillpAdjustFcParamsByRtt(struct FillpPcb * pcb)754 void FillpAdjustFcParamsByRtt(struct FillpPcb *pcb)
755 {
756     FillpCalPackInterval(pcb);
757     FillpCalNackDelayTimeByPackInterval(pcb);
758 
759     FillpAjustTlpParameterByRtt(pcb, (FILLP_LLONG)pcb->rtt);
760     pcb->statistics.appFcStastics.periodRtt = (FILLP_UINT32)FILLP_UTILS_US2MS(pcb->rtt);
761 }
762 
FillpBuildAndSendPack(struct FillpPcb * pcb,struct FtSocket * ftSock,struct FillpPktPack * pack,FILLP_UINT16 dataLen)763 void FillpBuildAndSendPack(struct FillpPcb *pcb, struct FtSocket *ftSock, struct FillpPktPack *pack,
764     FILLP_UINT16 dataLen)
765 {
766     FILLP_INT ret;
767     FILLP_UINT tmpDataLen;
768     FillpTraceDescriptSt fillpTrcDesc;
769     struct FillpPktHead *pktHead = (struct FillpPktHead *)pack->head;
770     pktHead->seqNum = pcb->recv.seqNum;
771     pktHead->dataLen = dataLen;
772 
773     /* 0 converted to network order is also 0, hence explicit conversion not applied */
774     if ((pack->flag & FILLP_PACK_FLAG_ADHOC) == 0) {
775         pktHead->pktNum = pcb->recv.pktNum;
776     }
777 
778     pktHead->flag = 0;
779     FILLP_HEADER_SET_PKT_TYPE(pktHead->flag, FILLP_PKT_TYPE_PACK);
780     FILLP_HEADER_SET_PROTOCOL_VERSION(pktHead->flag, FILLP_PROTOCOL_VERSION_NUMBER);
781     pktHead->flag = FILLP_HTONS(pktHead->flag);
782     tmpDataLen = pktHead->dataLen;
783     pktHead->dataLen = FILLP_HTONS(pktHead->dataLen);
784     pktHead->seqNum = FILLP_HTONL(pcb->recv.seqNum);
785     pktHead->pktNum = FILLP_HTONL(pcb->recv.pktNum);
786     pcb->recv.lastPackPktNum = pcb->recv.pktNum;
787     pcb->recv.lastPackSeqNum = pcb->recv.seqNum;
788 
789     pack->flag = FILLP_HTONS(pack->flag);
790     pack->pktLoss = FILLP_HTONS(pcb->statistics.pack.periodRecvPktLoss);
791     pack->rate = FILLP_HTONL(pcb->statistics.pack.periodRecvRate);
792     pack->oppositeSetRate = FILLP_HTONL(pack->oppositeSetRate);
793     pack->lostSeq = FILLP_HTONL(pack->lostSeq);
794     pack->reserved.rtt = FILLP_HTONL(pack->reserved.rtt);
795     pack->bgnPktNum = FILLP_HTONL(pack->bgnPktNum);
796     pack->endPktNum = FILLP_HTONL(pack->endPktNum);
797     pack->optsOffset = FILLP_HTONS(pack->optsOffset);
798     pack->rcvListBytes = FILLP_HTONL(pack->rcvListBytes);
799 
800     pcb->send.packRandomNum++;
801     ret = pcb->sendFunc(FILLP_GET_CONN(pcb), (char *)pack, (FILLP_INT)(tmpDataLen + FILLP_HLEN),
802         (struct SpungePcb *)pcb->spcb);
803     if (ret <= 0) {
804         pcb->statistics.debugPcb.packFailed++;
805     } else {
806         fillpTrcDesc.traceDirection = FILLP_TRACE_DIRECT_SEND;
807         if (ftSock != FILLP_NULL_PTR) {
808             FILLP_LM_FILLPMSGTRACE_OUTPUT(ftSock->traceFlag, FILLP_TRACE_DIRECT_NETWORK, ftSock->traceHandle,
809                 sizeof(struct FillpPktPack), FILLP_GET_SOCKET(pcb)->index,
810                 (FILLP_UINT8 *)(void *)&fillpTrcDesc, (FILLP_CHAR *)(pack));
811         }
812         pcb->statistics.debugPcb.packSend++;
813     }
814 }
815 
816 #ifdef __cplusplus
817 }
818 #endif
819