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_output.h"
17 #include "opt.h"
18 #include "skiplist.h"
19 #include "log.h"
20 #include "fillp_buf_item.h"
21 #include "fillp.h"
22 #include "spunge_core.h"
23 #include "fillp_common.h"
24 #include "check_gso_support.h"
25 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29 
FillpMoveRedundantItemToUnrecvList(struct FillpPcb * pcb)30 static void FillpMoveRedundantItemToUnrecvList(struct FillpPcb *pcb)
31 {
32     struct FillpPcbItem *item;
33     struct FillpSendPcb *sendPcb = &pcb->send;
34     item = (struct FillpPcbItem *)SkipListPopValue(&sendPcb->redunList);
35     while (item != FILLP_NULL_PTR) {
36         if (SkipListInsert(&sendPcb->unrecvList, item, &item->skipListNode, FILLP_TRUE) != ERR_OK) {
37             FILLP_LOGERR("fillp_sock_id:%d Can't move redundant item <%u,%u> to unrecvList",
38                 FILLP_GET_SOCKET(pcb)->index, item->seqNum, item->dataLen);
39             sendPcb->unrecvRedunListBytes -= item->dataLen;
40             FillpFreeBufItem(item);
41             (void)SYS_ARCH_ATOMIC_INC(&(FILLP_GET_SOCKET(pcb)->sendEventCount), 1);
42 #ifdef SOCK_SEND_SEM
43             (void)SYS_ARCH_SEM_POST(&pcb->send.send_sem);
44 #endif /* SOCK_SEND_SEM */
45             break;
46         }
47         item = (struct FillpPcbItem *)SkipListPopValue(&sendPcb->redunList);
48     }
49 }
50 
FillpGetSendItem(struct FillpSendPcb * sendPcb,struct FillpPcb * pcb)51 IGNORE_OVERFLOW static struct FillpPcbItem *FillpGetSendItem(struct FillpSendPcb *sendPcb,
52     struct FillpPcb *pcb)
53 {
54     struct FillpPcbItem *item = (struct FillpPcbItem *)SkipListPopValue(&sendPcb->unrecvList);
55     if (item != FILLP_NULL_PTR) {
56         return item;
57     }
58     struct HlistNode *unsendNode = HLIST_FIRST(&sendPcb->unSendList);
59     if (unsendNode == FILLP_NULL_PTR) {
60         return FILLP_NULL_PTR;
61     }
62     item = FillpPcbUnsendNodeEntry(unsendNode);
63     HlistDelete(&sendPcb->unSendList, unsendNode);
64     sendPcb->seqNum = sendPcb->seqNum + (FILLP_UINT32)item->dataLen;
65     item->seqNum = pcb->send.seqNum;
66     item->sendCount = 0;
67     item->infCount = 0;
68     item->resendTrigger = 0;
69 
70     if (UTILS_FLAGS_CHECK(item->flags, FILLP_ITEM_FLAGS_FIRST_PKT_FOR_CAL_COST)) {
71         FILLP_LOGINF("cost between thread: first seq:%u, last seq:%u, cost:%lld, size:%u",
72             item->seqNum, (item->seqNum + item->appSendSize - item->dataLen),
73             (SYS_ARCH_GET_CUR_TIME_LONGLONG() - (FILLP_LLONG)item->appSendTimestamp), item->appSendSize);
74     } else if (UTILS_FLAGS_CHECK(item->flags, FILLP_ITEM_FLAGS_LAST_PKT_FOR_CAL_COST)) {
75         FILLP_LOGINF("send expand: last seq:%u, cost:%lld, size:%u", item->seqNum,
76             (SYS_ARCH_GET_CUR_TIME_LONGLONG() - (FILLP_LLONG)item->appSendTimestamp), item->appSendSize);
77     }
78     return item;
79 }
80 
FillpIsAskMoreBuf(struct FillpSendPcb * sendPcb,struct FillpPcb * pcb)81 static FILLP_BOOL FillpIsAskMoreBuf(struct FillpSendPcb *sendPcb, struct FillpPcb *pcb)
82 {
83     if (sendPcb->unackList.count < (FILLP_UINT32)DYMP_GET_CUR_SIZE(sendPcb->itemPool)) {
84         return FILLP_FALSE;
85     }
86     int askMoreRet = FillpAskMoreBufItem(sendPcb->itemPool, FILLP_DYMM_INCREASE_STEP_SEND, FILLP_TRUE);
87     if (askMoreRet <= 0) {
88         return FILLP_FALSE;
89     }
90 
91     struct FtSocket *sock = FILLP_GET_SOCKET(pcb);
92 #ifdef SOCK_SEND_SEM
93     for (int inx = 0; inx < askMoreRet; inx++) {
94         (void)SYS_ARCH_SEM_POST(&sendPcb->send_sem);
95     }
96 #endif /* SOCK_SEND_SEM */
97     (void)SYS_ARCH_ATOMIC_INC(&sock->sendEventCount, askMoreRet);
98     sendPcb->curItemCount = (FILLP_UINT32)DYMP_GET_CUR_SIZE(sendPcb->itemPool);
99     FILLP_LOGDBG("Ask more buffer for send success, fillp_sock_id:%d", sock->index);
100     return FILLP_TRUE;
101 }
102 
FillpDoneSendAllData(struct FillpSendPcb * sendPcb,struct FillpPcb * pcb,FILLP_UINT32 sentBytes,FILLP_UINT32 sendPktNum)103 static void FillpDoneSendAllData(struct FillpSendPcb *sendPcb, struct FillpPcb *pcb,
104     FILLP_UINT32 sentBytes, FILLP_UINT32 sendPktNum)
105 {
106     /* Done sending all data */
107     if (sendPcb->preItem != FILLP_NULL_PTR) {
108         struct FillpPcbItem *item = (struct FillpPcbItem *)sendPcb->preItem;
109         UTILS_FLAGS_SET(item->flags, FILLP_ITEM_FLAGS_APP_LIMITED);
110         FILLP_LOGDBG("fillp_sock_id:%d, appLimited triggle, pktNum:%u, seqNum:%u, sc:%u, "
111             "unSendList:%u, unackList:%u, unrecvList:%u, redunList:%u, itemWaitTokenLists:%u, "
112             "curItemCount:%u",
113             FILLP_GET_SOCKET(pcb)->index, item->pktNum, item->seqNum, item->sendCount,
114             pcb->send.unSendList.size, pcb->send.unackList.count, pcb->send.unrecvList.nodeNum,
115             pcb->send.redunList.nodeNum, pcb->send.itemWaitTokenLists.nodeNum,
116             pcb->send.curItemCount);
117     }
118     sendPcb->appLimited = FILLP_TRUE;
119 
120     FILLP_LOGDBG("fillp_sock_id:%d NO_ENOUGH_DATA, expected_send:%u, actual_send:%u, set to appLimited",
121         FILLP_GET_SOCKET(pcb)->index, sendPktNum, (sentBytes / (FILLP_UINT32)pcb->pktSize));
122     sendPcb->flowControl.lastCycleNoEnoughData = FILLP_TRUE;
123     sendPcb->flowControl.remainBytes = FILLP_NULL;
124     sendPcb->flowControl.sendOneNoData = FILLP_TRUE;
125 #ifdef FILLP_SUPPORT_GSO
126     if (g_gsoSupport == FILLP_TRUE && pcb->sendmsgEio == FILLP_FALSE) {
127         pcb->sendmsgFunc(FILLP_NULL_PTR, FILLP_NULL_PTR, 0, pcb);
128     }
129 #endif
130 }
131 
FillpBeforeSendItem(struct FillpPcbItem * item,struct FillpPcb * pcb,FILLP_UINT32 sentBytes,FILLP_UINT32 totalBytes)132 static FILLP_UINT32 FillpBeforeSendItem(struct FillpPcbItem *item, struct FillpPcb *pcb,
133     FILLP_UINT32 sentBytes, FILLP_UINT32 totalBytes)
134 {
135     struct FillpSendPcb *sendPcb = &pcb->send;
136     if (item->sendCount > 0) { /* resend item */
137         sendPcb->unrecvRedunListBytes -= item->dataLen;
138     }
139     /*
140     * 1) no matter the number of need_send_count, we just add one time for send_cycle
141     * 2) we should always add one time to the send_cycle even if it send fail
142     * for flowControl, we must care the real_send_bytes
143     * so we should add all the packets be sent into the packIntervalSendPkt
144     */
145     sentBytes = (sentBytes + (FILLP_UINT32)item->dataLen);
146     if (sendPcb->appLimited) {
147         UTILS_FLAGS_SET(item->flags, FILLP_ITEM_FLAGS_APP_LIMITED);
148     } else {
149         UTILS_FLAGS_CLEAN(item->flags, FILLP_ITEM_FLAGS_APP_LIMITED);
150     }
151     sendPcb->appLimited = FILLP_FALSE;
152     if ((sentBytes >= totalBytes) || (item->resendTrigger == FILLP_ITEM_RESEND_TRIGGER_HNACK) ||
153         UTILS_FLAGS_CHECK(item->flags, FILLP_ITEM_FLAGS_LAST_PKT)) {
154         pcb->isLast = FILLP_TRUE;
155     } else {
156         pcb->isLast = FILLP_FALSE;
157     }
158     return sentBytes;
159 }
160 
FillpSendOne(struct FillpPcb * pcb,FILLP_UINT32 totalBytes,FILLP_UINT32 sendPktNum)161 FILLP_UINT32 FillpSendOne(struct FillpPcb *pcb, FILLP_UINT32 totalBytes, FILLP_UINT32 sendPktNum)
162 {
163     FILLP_INT ret;
164     struct FillpPcbItem *item = FILLP_NULL_PTR;
165     struct FillpSendPcb *sendPcb = &pcb->send;
166     FILLP_UINT32 sentBytes = FILLP_NULL;
167 
168     FillpMoveRedundantItemToUnrecvList(pcb);
169     /* We don't ack all the data in unSendPCB when received ack, because that may costs big time
170      * and make the send period not sending enough data out
171      *
172      * So here we ack the unackList every beginning of send
173      *
174      * Don't need to ack in when send buffer is less than FILLP_MAXIMAL_ACK_NUM_LIMITATION,
175      * because the items could be fully acked in recv pack
176      */
177     if (pcb->mpSendSize > FILLP_MAXIMAL_ACK_NUM_LIMITATION) {
178         FillpAckSendPcb(pcb, (FILLP_INT)UTILS_MAX(sendPktNum << 1, FILLP_SEND_ONE_ACK_NUM));
179     }
180 
181     while (sentBytes <= totalBytes) {
182         item = FillpGetSendItem(sendPcb, pcb);
183         if (item == FILLP_NULL_PTR) {
184             if (FillpIsAskMoreBuf(sendPcb, pcb) == FILLP_TRUE) {
185                 continue;
186             }
187             FillpDoneSendAllData(sendPcb, pcb, sentBytes, sendPktNum);
188             return sentBytes;
189         }
190         sendPcb->flowControl.sendOneNoData = FILLP_FALSE;
191 
192         sentBytes = FillpBeforeSendItem(item, pcb, sentBytes, totalBytes);
193         ret = SpungeItemRouteByToken(item, pcb);
194         if (ret != ERR_OK) {
195             break;
196         }
197     }
198     return sentBytes;
199 }
200 
FillpBuildTimestamp(FILLP_CHAR * dataOptionPtr)201 static FILLP_UINT16 FillpBuildTimestamp(FILLP_CHAR *dataOptionPtr)
202 {
203     FillpErrorType err;
204     FillpDataOption *dataOption = FILLP_NULL_PTR;
205 
206     FILLP_LLONG curTime = SYS_ARCH_GET_CUR_TIME_LONGLONG();
207     curTime = (FILLP_LLONG)FILLP_HTONLL((FILLP_ULLONG)curTime);
208     dataOption = (FillpDataOption *)dataOptionPtr;
209     dataOption->type = FILLP_OPT_TIMESTAMP;
210     dataOption->len = FILLP_OPT_TIMESTAMP_LEN;
211     err = memcpy_s(&(dataOption->value[0]), sizeof(FILLP_LLONG), &curTime, sizeof(FILLP_LLONG));
212     if (err != EOK) {
213         FILLP_LOGERR("fillp_build_pkt_data_options memcpy_s failed:%d", err);
214     }
215 
216     return (FILLP_UINT16)(FILLP_DATA_OPT_HLEN + FILLP_OPT_TIMESTAMP_LEN);
217 }
218 
FillpBuildPktDataOptions(FILLP_CONST struct FillpPcb * pcb,struct FillpPcbItem * item,FILLP_CHAR * dataOptionAddr)219 static void FillpBuildPktDataOptions(FILLP_CONST struct FillpPcb *pcb,
220     struct FillpPcbItem *item, FILLP_CHAR *dataOptionAddr)
221 {
222     FILLP_UINT16 offset = 0;
223     FILLP_CHAR *option = dataOptionAddr + FILLP_DATA_OFFSET_LEN;
224 
225     if (UTILS_FLAGS_CHECK(item->dataOptFlag, FILLP_OPT_FLAG_TIMESTAMP)) {
226         offset += FillpBuildTimestamp(option);
227     }
228 
229     if (UTILS_FLAGS_CHECK(item->dataOptFlag, FILLP_OPT_FLAG_FRAME_INFO)) {
230         offset += FillpFrameBuildOption(item, (FILLP_UINT8 *)&option[offset]);
231     }
232 
233     *(FILLP_UINT16 *)(dataOptionAddr) = FILLP_HTONS(offset);
234     FILLP_UNUSED_PARA(pcb);
235 }
236 
FillpBuildDataPkt(struct FillpPcb * pcb,struct FillpPcbItem * item)237 static void FillpBuildDataPkt(struct FillpPcb *pcb, struct FillpPcbItem *item)
238 {
239     struct NetBuf *sendBuf;
240     struct FillpPktHead *pktHdr;
241     struct FillpSendPcb *sendPcb = &pcb->send;
242     FILLP_UINT16 flag = 0;
243     struct FtSocket *sock = FILLP_GET_SOCKET(pcb);
244     FillpTraceDescriptSt fillpTrcDesc;
245 
246     sendBuf = &item->buf;
247     pktHdr = (struct FillpPktHead *)(void *)sendBuf->p;
248 
249     item->pktNum = ++sendPcb->pktNum;
250 
251     FILLP_HEADER_SET_PKT_TYPE(flag, FILLP_PKT_TYPE_DATA);
252     FILLP_HEADER_SET_PROTOCOL_VERSION(flag, FILLP_PROTOCOL_VERSION_NUMBER);
253     if (item->dataOptFlag && item->dataOptLen) {
254         FILLP_HEADER_SET_DAT_WITH_OPTION(flag);
255         FillpBuildPktDataOptions(pcb, item, sendBuf->p + (FILLP_UINT16)FILLP_HLEN);
256     }
257 
258     if (UTILS_FLAGS_CHECK(item->flags, FILLP_ITEM_FLAGS_LAST_PKT_FOR_CAL_COST)) {
259         FILLP_HEADER_SET_DAT_WITH_LAST_FLAG(flag);
260     } else if (UTILS_FLAGS_CHECK(item->flags, FILLP_ITEM_FLAGS_FIRST_PKT_FOR_CAL_COST)) {
261         FILLP_HEADER_SET_DAT_WITH_FIRST_FLAG(flag);
262     }
263     pktHdr->flag = FILLP_HTONS(flag);
264 
265     pktHdr->pktNum = FILLP_HTONL(item->pktNum);
266     pktHdr->seqNum = FILLP_HTONL(item->seqNum);
267     pktHdr->dataLen = FILLP_HTONS(item->dataLen);
268 
269     /* Log the first data sending out of this connection */
270     if (pcb->statistics.traffic.totalSend == 0) {
271         FILLP_LOGINF("FirstData!!! fillp_sock_id:%d send seq num:%u, send pkt num:%u", sock->index, pcb->send.seqNum,
272             pcb->send.pktNum);
273     }
274 
275     FILLP_LM_TRACE_SEND_MSG(sock->traceFlag, FILLP_TRACE_DIRECT_NETWORK, sock->traceHandle, FILLP_HLEN, sock->index,
276         fillpTrcDesc, (FILLP_CHAR *)pktHdr);
277 }
278 
UpdateStatisticsWhenSendOne(struct FillpStatisticsPcb * stats,FILLP_UINT32 bufLen)279 static void UpdateStatisticsWhenSendOne(struct FillpStatisticsPcb *stats, FILLP_UINT32 bufLen)
280 {
281     stats->debugPcb.packIntervalSendBytes += bufLen;
282     stats->debugPcb.packIntervalSendPkt++;
283     stats->traffic.totalSend++;
284     stats->traffic.totalSendBytes += bufLen;
285 
286     stats->appFcStastics.periodSendPkts++;
287     stats->appFcStastics.periodSendBits += (FILLP_ULLONG)FILLP_FC_VAL_IN_BITS(((FILLP_ULLONG)bufLen));
288 }
289 
FillpAddtoListBySeqNum(struct Hlist * list,struct FillpPcbItem * item)290 static FillpErrorType FillpAddtoListBySeqNum(struct Hlist *list, struct FillpPcbItem *item)
291 {
292     struct HlistNode *pos = FILLP_NULL_PTR;
293     struct FillpPcbItem *posItem = FILLP_NULL_PTR;
294     if (HLIST_EMPTY(list)) {
295         HlistAddHead(list, &item->node);
296         return ERR_OK;
297     }
298 
299     pos = HLIST_TAIL(list);
300     posItem = FILLP_NULL_PTR;
301 
302     while (pos != FILLP_NULL_PTR) {
303         posItem = FillpPcbEntry(pos);
304         if (posItem->seqNum == item->seqNum) {
305             return ERR_COMM;
306         } else if (FillpNumIsbigger(posItem->seqNum, item->seqNum)) {
307             pos = (struct HlistNode *)(void *)pos->pprev;
308             if (pos == &list->head) { // Back to the head, no more data
309                 pos = FILLP_NULL_PTR;
310             }
311         } else {
312             break; /* Insert before pos */
313         }
314     }
315 
316     if (pos != FILLP_NULL_PTR) {
317         HlistAddAfter(list, pos, &item->node);
318     } else {
319         /* Smaller than the first one */
320         HlistAddHead(list, &item->node);
321     }
322 
323     return ERR_OK;
324 }
325 
FillpAddToUnackList(struct FillpPcb * pcb,struct FillpPcbItem * item)326 static FillpErrorType FillpAddToUnackList(struct FillpPcb *pcb, struct FillpPcbItem *item)
327 {
328     FILLP_UINT32 unackIndex = FILLP_UNACKLIST_HASHINDEX(item->seqNum, pcb);
329     if (FillpAddtoListBySeqNum(&pcb->send.unackList.hashMap[unackIndex], item) != ERR_OK) {
330         if (SkipListInsert(&pcb->send.unrecvList, item, &item->skipListNode, FILLP_TRUE) != ERR_OK) {
331             FILLP_LOGERR("fillp_sock_id:%d Can't add send ones to SkipList", FILLP_GET_SOCKET(pcb)->index);
332             return ERR_NOBUFS;
333         }
334         if (item->sendCount > 0) {
335             pcb->send.unrecvRedunListBytes += item->dataLen;
336         }
337         FillpEnableSendTimer(pcb);
338     } else {
339         pcb->send.unackList.count++;
340     }
341     return ERR_OK;
342 }
343 
FillpAddToPktSeqHash(FILLP_CONST struct FillpPcb * pcb,struct FillpPcbItem * item)344 static void FillpAddToPktSeqHash(FILLP_CONST struct FillpPcb *pcb, struct FillpPcbItem *item)
345 {
346     struct Hlist *list = &pcb->send.pktSeqMap.hashMap[item->pktNum & pcb->send.pktSeqMap.hashModSize];
347     HlistAddTail(list, &item->pktSeqMapNode);
348 }
349 
FillpItemRetrans(struct FillpPcbItem * item,struct FillpPcb * fpcb,struct FillpSendPcb * sendPcb)350 static FILLP_INT FillpItemRetrans(struct FillpPcbItem *item, struct FillpPcb *fpcb, struct FillpSendPcb *sendPcb)
351 {
352     /* First retransmit packet which sent but not received */
353     if (item->sendCount > 0) {
354         fpcb->statistics.traffic.totalRetryed++;
355     }
356 
357     sendPcb->lastSendTs = fpcb->pcbInst->curTime;
358     item->infCount++;
359     sendPcb->inSendBytes += item->dataLen;
360 
361     if (FillpAddToUnackList(fpcb, item) != ERR_OK) {
362         FILLP_LOGERR("FillpAddToUnackList error!seqNum:%u,insert to redunList", item->seqNum);
363         /* fillp_add_to_unAckList will fail is seq number matches so calling SkipListInsert for unrecv list will again
364         fail, so just free and continue, if lucky peer will receive this packet will be permantly lost, application need
365         to recreate connection this failure should not happen until some bug in code */
366         FillpFreeItemAndEvent(fpcb, item);
367     } else {
368         fpcb->send.preItem = (void *)item;
369         FillpAddToPktSeqHash(fpcb, item);
370     }
371     return ERR_OK;
372 }
373 
FillpSendItem(struct FillpPcbItem * item,struct FillpPcb * fpcb)374 FILLP_INT FillpSendItem(struct FillpPcbItem *item, struct FillpPcb *fpcb)
375 {
376     struct FtNetconn *conn = (struct FtNetconn *)FILLP_GET_CONN(fpcb);
377     struct FillpStatisticsPcb *stats = &(fpcb->statistics);
378     struct FillpSendPcb *sendPcb = &fpcb->send;
379     FILLP_INT sentBytes;
380 
381     if (item->sendCount == 0) {
382         item->firstSendTimestamp = fpcb->pcbInst->curTime;
383         item->lastSendTimestamp = item->firstSendTimestamp;
384     } else {
385         item->lastSendTimestamp = fpcb->pcbInst->curTime;
386         if (item->sendCount > stats->debugPcb.onePktMaxSendCount) {
387             stats->debugPcb.onePktMaxSendCount = item->sendCount;
388         }
389     }
390 
391     FillpBuildDataPkt(fpcb, item);
392 
393     /*
394      * for flowControl, we must care the real_send_bytes
395      * so we should add all the packets be sent into the packIntervalSendPkt
396      */
397     UpdateStatisticsWhenSendOne(stats, (FILLP_UINT32)item->dataLen);
398 
399     /*
400      * calculate loss rate by pktNum at recv endpoint,
401      * so pktNum should be incresed when need_send_count more than 1
402      */
403 #ifdef FILLP_SUPPORT_GSO
404     if (g_gsoSupport == FILLP_FALSE || fpcb->sendmsgEio == FILLP_TRUE) {
405 #endif
406         sentBytes = fpcb->sendFunc(conn, (void *)item->buf.p, (FILLP_INT)(item->buf.len + FILLP_HLEN), fpcb->spcb);
407 #ifdef FILLP_SUPPORT_GSO
408     } else {
409         sentBytes = fpcb->sendmsgFunc(conn, (void *)item->buf.p, (FILLP_INT)(item->buf.len + FILLP_HLEN), fpcb);
410     }
411 #endif
412     if (sentBytes <= 0) {
413         stats->traffic.totalSendFailed++;
414         /* Add to unrecvList */
415         if (SkipListInsert(&sendPcb->unrecvList, (void *)item, &item->skipListNode, FILLP_TRUE) != ERR_OK) {
416             InsertUnrecvListFail(fpcb, item);
417         } else {
418             if (item->sendCount > 0) {
419                 sendPcb->unrecvRedunListBytes += item->dataLen;
420             }
421         }
422         /*
423          * this is used to roll-back the pktNum which increased in func FillpBuildDataPkt,
424          * if the increase role for sendPcb->pktNum or role to set item->pktNum is changed
425          * this roll-back operation should be pay attention to
426          */
427         sendPcb->pktNum--;
428         FillpEnableSendTimer(fpcb);
429         return -1;
430     }
431     return FillpItemRetrans(item, fpcb, sendPcb);
432 }
433 
FillpSendAdhocpackToDetectRtt(struct FillpPcb * pcb)434 void FillpSendAdhocpackToDetectRtt(struct FillpPcb *pcb)
435 {
436     struct FillpPktPack pack;
437     struct FtSocket *ftSock = FILLP_NULL_PTR;
438     FILLP_LLONG curTime = SYS_ARCH_GET_CUR_TIME_LONGLONG();
439 
440     (void)memset_s(&pack, sizeof(pack), 0, sizeof(pack));
441     pack.rate = pcb->statistics.pack.periodRecvRate;
442     pack.oppositeSetRate = 0;
443     pack.flag = FILLP_PACK_FLAG_ADHOC;
444     pack.flag |= FILLP_PACK_FLAG_REQURE_RTT;
445     pack.pktLoss = 0;
446     pack.reserved.rtt =
447         (FILLP_UINT32)((FILLP_ULLONG)curTime & 0xFFFFFFFF); /* rtt isn't much large, so only use the low 32bit is ok */
448     pack.lostSeq = pcb->recv.seqNum;
449 
450     ftSock = FILLP_GET_SOCKET(pcb);
451     FillpBuildAndSendPack(pcb, ftSock, &pack, sizeof(struct FillpPktPack) - FILLP_HLEN);
452 }
453 
FillpSetSimplePack(FILLP_CONST struct FillpPcb * pcb,struct FillpPktPack * pack,FILLP_CONST struct FtSocket * ftSock)454 static void FillpSetSimplePack(FILLP_CONST struct FillpPcb *pcb, struct FillpPktPack *pack,
455     FILLP_CONST struct FtSocket *ftSock)
456 {
457     (void)memset_s(pack, sizeof(struct FillpPktPack), 0, sizeof(struct FillpPktPack));
458     pack->rate = pcb->statistics.pack.periodRecvRate;
459     pack->oppositeSetRate = 0;
460     pack->flag = FILLP_NULL_NUM;
461     pack->oppositeSetRate = pcb->recv.oppositeSetRate;
462     if (pack->oppositeSetRate != 0) {
463         pack->flag |= FILLP_PACK_FLAG_WITH_RATE_LIMIT;
464     }
465 
466     if (ftSock->resConf.common.enlargePackIntervalFlag) {
467         if (!(FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->sendTimerNode)) &&
468             (!pcb->send.unackList.count)) {
469             pack->flag |= FILLP_PACK_FLAG_NO_DATA_SEND;
470         }
471     }
472     pack->pktLoss = pcb->statistics.pack.periodRecvPktLoss;
473 
474     pack->reserved.rtt = 0;
475     if ((!pcb->statistics.pack.peerRtt) && pcb->rtt) {
476         pack->flag |= FILLP_PACK_FLAG_WITH_RTT;
477         pack->reserved.rtt = (FILLP_UINT32)pcb->rtt;
478     }
479 
480     if (!pcb->rtt) {
481         pack->flag |= FILLP_PACK_FLAG_REQURE_RTT;
482     }
483 }
484 
FillpSendPack(struct FillpPcb * pcb,struct FillpPktPack * pack)485 static FILLP_BOOL FillpSendPack(struct FillpPcb *pcb, struct FillpPktPack *pack)
486 {
487     struct FillpPcbItem *item = FILLP_NULL_PTR;
488     struct SkipListNode *node = FILLP_NULL_PTR;
489     FILLP_UINT16 dataLen = 0;
490 
491     struct FtSocket *ftSock = FILLP_GET_SOCKET(pcb);
492     if (ftSock == FILLP_NULL_PTR) {
493         FILLP_LOGERR("sock is NULL");
494         return FILLP_TRUE;
495     }
496 
497     FillpSetSimplePack(pcb, pack, ftSock);
498     node = SkipListGetPop(&pcb->recv.recvList);
499     if (node != FILLP_NULL_PTR) {
500         item = (struct FillpPcbItem *)node->item;
501         pack->lostSeq = (item->seqNum - item->dataLen);
502     } else {
503         pack->lostSeq = pcb->recv.seqNum;
504     }
505 
506     dataLen = sizeof(struct FillpPktPack) + dataLen - FILLP_HLEN;
507     FillpBuildAndSendPack(pcb, ftSock, pack, dataLen);
508 
509     return FILLP_TRUE;
510 }
511 
FillpSendPackWithPcbBuffer(struct FillpPcb * pcb)512 FILLP_BOOL FillpSendPackWithPcbBuffer(struct FillpPcb *pcb)
513 {
514     FILLP_CHAR *buf = pcb->pcbInst->tmpBuf[0];
515     struct FillpPktPack *pack = (struct FillpPktPack *)buf;
516 
517     return FillpSendPack(pcb, pack);
518 }
519 
520 #ifdef __cplusplus
521 }
522 #endif
523