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