• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "fillp_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     return;
50 }
51 
FillpGetSendItem(struct FillpSendPcb * sendPcb,struct FillpPcb * pcb)52 static struct FillpPcbItem *FillpGetSendItem(struct FillpSendPcb *sendPcb, 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     int inx = 0;
91     struct FtSocket *sock = FILLP_GET_SOCKET(pcb);
92     for (; inx < askMoreRet; inx++) {
93 #ifdef SOCK_SEND_SEM
94         (void)SYS_ARCH_SEM_POST(&sendPcb->send_sem);
95 #endif /* SOCK_SEND_SEM */
96     }
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     return;
236 }
237 
FillpBuildDataPkt(struct FillpPcb * pcb,struct FillpPcbItem * item)238 static void FillpBuildDataPkt(struct FillpPcb *pcb, struct FillpPcbItem *item)
239 {
240     struct NetBuf *sendBuf;
241     struct FillpPktHead *pktHdr;
242     struct FillpSendPcb *sendPcb = &pcb->send;
243     FILLP_UINT16 flag = 0;
244     struct FtSocket *sock = FILLP_GET_SOCKET(pcb);
245     FillpTraceDescriptSt fillpTrcDesc;
246 
247     sendBuf = &item->buf;
248     pktHdr = (struct FillpPktHead *)(void *)sendBuf->p;
249 
250     item->pktNum = ++sendPcb->pktNum;
251 
252     FILLP_HEADER_SET_PKT_TYPE(flag, FILLP_PKT_TYPE_DATA);
253     FILLP_HEADER_SET_PROTOCOL_VERSION(flag, FILLP_PROTOCOL_VERSION_NUMBER);
254     if (item->dataOptFlag && item->dataOptLen) {
255         FILLP_HEADER_SET_DAT_WITH_OPTION(flag);
256         FillpBuildPktDataOptions(pcb, item, sendBuf->p + (FILLP_UINT16)FILLP_HLEN);
257     }
258 
259     if (UTILS_FLAGS_CHECK(item->flags, FILLP_ITEM_FLAGS_LAST_PKT_FOR_CAL_COST)) {
260         FILLP_HEADER_SET_DAT_WITH_LAST_FLAG(flag);
261     } else if (UTILS_FLAGS_CHECK(item->flags, FILLP_ITEM_FLAGS_FIRST_PKT_FOR_CAL_COST)) {
262         FILLP_HEADER_SET_DAT_WITH_FIRST_FLAG(flag);
263     }
264     pktHdr->flag = FILLP_HTONS(flag);
265 
266     pktHdr->pktNum = FILLP_HTONL(item->pktNum);
267     pktHdr->seqNum = FILLP_HTONL(item->seqNum);
268     pktHdr->dataLen = FILLP_HTONS(item->dataLen);
269 
270     /* Log the first data sending out of this connection */
271     if (pcb->statistics.traffic.totalSend == 0) {
272         FILLP_LOGINF("FirstData!!! fillp_sock_id:%d send seq num:%u, send pkt num:%u", sock->index, pcb->send.seqNum,
273             pcb->send.pktNum);
274     }
275 
276     FILLP_LM_TRACE_SEND_MSG(sock->traceFlag, FILLP_TRACE_DIRECT_NETWORK, sock->traceHandle, FILLP_HLEN, sock->index,
277         fillpTrcDesc, (FILLP_CHAR *)pktHdr);
278 
279     return;
280 }
281 
UpdateStatisticsWhenSendOne(struct FillpStatisticsPcb * stats,FILLP_UINT32 bufLen)282 static void UpdateStatisticsWhenSendOne(struct FillpStatisticsPcb *stats, FILLP_UINT32 bufLen)
283 {
284     stats->debugPcb.packIntervalSendBytes += bufLen;
285     stats->debugPcb.packIntervalSendPkt++;
286     stats->traffic.totalSend++;
287     stats->traffic.totalSendBytes += bufLen;
288 
289     stats->appFcStastics.periodSendPkts++;
290     stats->appFcStastics.periodSendBits =
291     stats->appFcStastics.periodSendBits + (FILLP_ULLONG)FILLP_FC_VAL_IN_BITS(((FILLP_ULLONG)bufLen));
292 }
293 
FillpAddtoListBySeqNum(struct Hlist * list,struct FillpPcbItem * item)294 static FillpErrorType FillpAddtoListBySeqNum(struct Hlist *list, struct FillpPcbItem *item)
295 {
296     struct HlistNode *pos = FILLP_NULL_PTR;
297     struct FillpPcbItem *posItem = FILLP_NULL_PTR;
298     if (HLIST_EMPTY(list)) {
299         HlistAddHead(list, &item->node);
300         return ERR_OK;
301     }
302 
303     pos = HLIST_TAIL(list);
304     posItem = FILLP_NULL_PTR;
305 
306     while (pos != FILLP_NULL_PTR) {
307         posItem = FillpPcbEntry(pos);
308         if (posItem->seqNum == item->seqNum) {
309             return ERR_COMM;
310         } else if (FillpNumIsbigger(posItem->seqNum, item->seqNum)) {
311             pos = (struct HlistNode *)(void *)pos->pprev;
312             if (pos == &list->head) { // Back to the head, no more data
313                 pos = FILLP_NULL_PTR;
314             }
315         } else {
316             break; /* Insert before pos */
317         }
318     }
319 
320     if (pos != FILLP_NULL_PTR) {
321         HlistAddAfter(list, pos, &item->node);
322     } else {
323         /* Smaller than the first one */
324         HlistAddHead(list, &item->node);
325     }
326 
327     return ERR_OK;
328 }
329 
FillpAddToUnackList(struct FillpPcb * pcb,struct FillpPcbItem * item)330 static FillpErrorType FillpAddToUnackList(struct FillpPcb *pcb, struct FillpPcbItem *item)
331 {
332     FILLP_UINT32 unackIndex = FILLP_UNACKLIST_HASHINDEX(item->seqNum, pcb);
333     if (FillpAddtoListBySeqNum(&pcb->send.unackList.hashMap[unackIndex], item) != ERR_OK) {
334         if (SkipListInsert(&pcb->send.unrecvList, item, &item->skipListNode, FILLP_TRUE) != ERR_OK) {
335             FILLP_LOGERR("fillp_sock_id:%d Can't add send ones to SkipList", FILLP_GET_SOCKET(pcb)->index);
336             return ERR_NOBUFS;
337         }
338         if (item->sendCount > 0) {
339             pcb->send.unrecvRedunListBytes += item->dataLen;
340         }
341         FillpEnableSendTimer(pcb);
342     } else {
343         pcb->send.unackList.count++;
344     }
345     return ERR_OK;
346 }
347 
FillpAddToPktSeqHash(FILLP_CONST struct FillpPcb * pcb,struct FillpPcbItem * item)348 static void FillpAddToPktSeqHash(FILLP_CONST struct FillpPcb *pcb, struct FillpPcbItem *item)
349 {
350     struct Hlist *list = &pcb->send.pktSeqMap.hashMap[item->pktNum & pcb->send.pktSeqMap.hashModSize];
351     HlistAddTail(list, &item->pktSeqMapNode);
352 
353     return;
354 }
355 
FillpItemRetrans(struct FillpPcbItem * item,struct FillpPcb * fpcb,struct FillpSendPcb * sendPcb)356 static FILLP_INT FillpItemRetrans(struct FillpPcbItem *item, struct FillpPcb *fpcb, struct FillpSendPcb *sendPcb)
357 {
358     /* First retransmit packet which sent but not received */
359     if (item->sendCount > 0) {
360         fpcb->statistics.traffic.totalRetryed++;
361     }
362 
363     sendPcb->lastSendTs = fpcb->pcbInst->curTime;
364     item->infCount++;
365     sendPcb->inSendBytes += item->dataLen;
366 
367     if (FillpAddToUnackList(fpcb, item) != ERR_OK) {
368         FILLP_LOGERR("FillpAddToUnackList error!seqNum:%u,insert to redunList", item->seqNum);
369         /* fillp_add_to_unAckList will fail is seq number matches so calling SkipListInsert for unrecv list will again
370         fail, so just free and continue, if lucky peer will receive this packet will be permantly lost, application need
371         to recreate connection this failure should not happen until some bug in code */
372         FillpFreeItemAndEvent(fpcb, item);
373     } else {
374         fpcb->send.preItem = (void *)item;
375         FillpAddToPktSeqHash(fpcb, item);
376     }
377     return ERR_OK;
378 }
379 
FillpSendItem(struct FillpPcbItem * item,struct FillpPcb * fpcb)380 FILLP_INT FillpSendItem(struct FillpPcbItem *item, struct FillpPcb *fpcb)
381 {
382     struct FtNetconn *conn = (struct FtNetconn *)FILLP_GET_CONN(fpcb);
383     struct FillpStatisticsPcb *stats = &(fpcb->statistics);
384     struct FillpSendPcb *sendPcb = &fpcb->send;
385     FILLP_INT sentBytes;
386 
387     if (item->sendCount == 0) {
388         item->firstSendTimestamp = fpcb->pcbInst->curTime;
389         item->lastSendTimestamp = item->firstSendTimestamp;
390     } else {
391         item->lastSendTimestamp = fpcb->pcbInst->curTime;
392         if (item->sendCount > stats->debugPcb.onePktMaxSendCount) {
393             stats->debugPcb.onePktMaxSendCount = item->sendCount;
394         }
395     }
396 
397     FillpBuildDataPkt(fpcb, item);
398 
399     /*
400      * for flowControl, we must care the real_send_bytes
401      * so we should add all the packets be sent into the packIntervalSendPkt
402      */
403     UpdateStatisticsWhenSendOne(stats, (FILLP_UINT32)item->dataLen);
404 
405     /*
406      * calculate loss rate by pktNum at recv endpoint,
407      * so pktNum should be incresed when need_send_count more than 1
408      */
409 #ifdef FILLP_SUPPORT_GSO
410     if (g_gsoSupport == FILLP_FALSE || fpcb->sendmsgEio == FILLP_TRUE) {
411 #endif
412         sentBytes = fpcb->sendFunc(conn, (void *)item->buf.p, (FILLP_INT)(item->buf.len + FILLP_HLEN), fpcb->spcb);
413 #ifdef FILLP_SUPPORT_GSO
414     } else {
415         sentBytes = fpcb->sendmsgFunc(conn, (void *)item->buf.p, (FILLP_INT)(item->buf.len + FILLP_HLEN), fpcb);
416     }
417 #endif
418     if (sentBytes <= 0) {
419         stats->traffic.totalSendFailed++;
420         /* Add to unrecvList */
421         if (SkipListInsert(&sendPcb->unrecvList, (void *)item, &item->skipListNode, FILLP_TRUE) != ERR_OK) {
422             InsertUnrecvListFail(fpcb, item);
423         } else {
424             if (item->sendCount > 0) {
425                 sendPcb->unrecvRedunListBytes += item->dataLen;
426             }
427         }
428         /*
429          * this is used to roll-back the pktNum which increased in func FillpBuildDataPkt,
430          * if the increase role for sendPcb->pktNum or role to set item->pktNum is changed
431          * this roll-back operation should be pay attention to
432          */
433         sendPcb->pktNum--;
434         FillpEnableSendTimer(fpcb);
435         return -1;
436     }
437     return FillpItemRetrans(item, fpcb, sendPcb);
438 }
439 
FillpSendAdhocpackToDetectRtt(struct FillpPcb * pcb)440 void FillpSendAdhocpackToDetectRtt(struct FillpPcb *pcb)
441 {
442     struct FillpPktPack pack;
443     struct FtSocket *ftSock = FILLP_NULL_PTR;
444     FILLP_LLONG curTime = SYS_ARCH_GET_CUR_TIME_LONGLONG();
445 
446     (void)memset_s(&pack, sizeof(pack), 0, sizeof(pack));
447     pack.rate = pcb->statistics.pack.periodRecvRate;
448     pack.oppositeSetRate = 0;
449     pack.flag = FILLP_PACK_FLAG_ADHOC;
450     pack.flag |= FILLP_PACK_FLAG_REQURE_RTT;
451     pack.pktLoss = 0;
452     pack.reserved.rtt =
453         (FILLP_UINT32)((FILLP_ULLONG)curTime & 0xFFFFFFFF); /* rtt isn't much large, so only use the low 32bit is ok */
454     pack.lostSeq = pcb->recv.seqNum;
455 
456     ftSock = FILLP_GET_SOCKET(pcb);
457     FillpBuildAndSendPack(pcb, ftSock, &pack, sizeof(struct FillpPktPack) - FILLP_HLEN);
458 
459     return;
460 }
461 
FillpSetSimplePack(FILLP_CONST struct FillpPcb * pcb,struct FillpPktPack * pack,FILLP_CONST struct FtSocket * ftSock)462 static void FillpSetSimplePack(FILLP_CONST struct FillpPcb *pcb, struct FillpPktPack *pack,
463     FILLP_CONST struct FtSocket *ftSock)
464 {
465     (void)memset_s(pack, sizeof(struct FillpPktPack), 0, sizeof(struct FillpPktPack));
466     pack->rate = pcb->statistics.pack.periodRecvRate;
467     pack->oppositeSetRate = 0;
468     pack->flag = FILLP_NULL_NUM;
469     pack->oppositeSetRate = pcb->recv.oppositeSetRate;
470     if (pack->oppositeSetRate != 0) {
471         pack->flag |= FILLP_PACK_FLAG_WITH_RATE_LIMIT;
472     }
473 
474     if (ftSock->resConf.common.enlargePackIntervalFlag) {
475         if (!(FILLP_TIMING_WHEEL_IS_NODE_ENABLED(&pcb->sendTimerNode)) &&
476             (!pcb->send.unackList.count)) {
477             pack->flag |= FILLP_PACK_FLAG_NO_DATA_SEND;
478         }
479     }
480     pack->pktLoss = pcb->statistics.pack.periodRecvPktLoss;
481 
482     pack->reserved.rtt = 0;
483     if ((!pcb->statistics.pack.peerRtt) && pcb->rtt) {
484         pack->flag |= FILLP_PACK_FLAG_WITH_RTT;
485         pack->reserved.rtt = (FILLP_UINT32)pcb->rtt;
486     }
487 
488     if (!pcb->rtt) {
489         pack->flag |= FILLP_PACK_FLAG_REQURE_RTT;
490     }
491 }
492 
FillpSendPack(struct FillpPcb * pcb,struct FillpPktPack * pack)493 static FILLP_BOOL FillpSendPack(struct FillpPcb *pcb, struct FillpPktPack *pack)
494 {
495     struct FillpPcbItem *item = FILLP_NULL_PTR;
496     struct SkipListNode *node = FILLP_NULL_PTR;
497     FILLP_UINT16 dataLen = 0;
498 
499     struct FtSocket *ftSock = FILLP_GET_SOCKET(pcb);
500     if (ftSock == FILLP_NULL_PTR) {
501         FILLP_LOGERR("sock is NULL");
502         return FILLP_TRUE;
503     }
504 
505     FillpSetSimplePack(pcb, pack, ftSock);
506     node = SkipListGetPop(&pcb->recv.recvList);
507     if (node != FILLP_NULL_PTR) {
508         item = (struct FillpPcbItem *)node->item;
509         pack->lostSeq = (item->seqNum - item->dataLen);
510     } else {
511         pack->lostSeq = pcb->recv.seqNum;
512     }
513 
514     dataLen = sizeof(struct FillpPktPack) + dataLen - FILLP_HLEN;
515     FillpBuildAndSendPack(pcb, ftSock, pack, dataLen);
516 
517     return FILLP_TRUE;
518 }
519 
FillpSendPackWithPcbBuffer(struct FillpPcb * pcb)520 FILLP_BOOL FillpSendPackWithPcbBuffer(struct FillpPcb *pcb)
521 {
522     FILLP_CHAR *buf = pcb->pcbInst->tmpBuf[0];
523     struct FillpPktPack *pack = (struct FillpPktPack *)buf;
524 
525     return FillpSendPack(pcb, pack);
526 }
527 
528 #ifdef __cplusplus
529 }
530 #endif
531