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