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