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