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