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_dfx.h"
17 #include <limits.h>
18 #include "sockets.h"
19 #include "socket_common.h"
20 #include "log.h"
21 #include "res.h"
22 #include "spunge.h"
23 #include "securec.h"
24 #include "log.h"
25 #include "spunge_message.h"
26 #include "nstackx_getopt.h"
27 #include "nstackx_util.h"
28 #include "nstackx_error.h"
29
30 #define FILLP_DFX_PKT_EVT_DROP_THRESHOLD 1000
31 static struct Hlist g_fillpDfxPktPraseFailList = {
32 {
33 .pprev = (struct HlistNode **)&g_fillpDfxPktPraseFailList,
34 },
35 .size = 0,
36 };
37 static FillpDfxEventCb g_fillpDfxEvtCb = FILLP_NULL_PTR;
38 static void *g_fillpDfxSoftObj = FILLP_NULL_PTR;
39
40 typedef struct {
41 struct HlistNode node;
42 FILLP_INT sockIdx;
43 FILLP_UINT32 dropCnt;
44 FILLP_UINT32 lastReportCnt;
45 } FillpDfxPktParseFailNode;
46
47 typedef union {
48 struct {
49 FILLP_UINT32 sockIdx;
50 FillpDfxLinkEvtType linkEvtType;
51 } linkEvt;
52 struct {
53 FILLP_UINT32 sockIdx;
54 FillpDfxPktEvtType pktEvtType;
55 /* FILLP_DFX_PKT_PARSE_FAIL: dropCnt means pkt count */
56 /* FILLP_DFX_PKT_SEMI_RELIABLE_DROP: dropCnt means frame count */
57 FILLP_UINT32 dropCnt;
58 } pktEvt;
59 struct {
60 FILLP_UINT32 sockIdx;
61 FILLP_UINT32 rtt;
62 FILLP_UINT32 totalReceivedPkt;
63 FILLP_UINT32 totalReceivedBytes;
64 FILLP_UINT32 totalSendPkt;
65 FILLP_UINT32 totalSendBytes;
66 FILLP_UINT32 jitter; /* ms */
67 } sockQos;
68 } FillpDfxEvtArgs;
69
70 #define FILLP_DFX_LINK_EVT_PARA_NUM 2
71 #define FILLP_DFX_PKT_EVT_PARA_NUM 3
72 #define FILLP_DFX_SOCK_QOS_EVT_PARA_NUM 7
73 #define FILLP_EVT_MAX_PARA_NUM FILLP_DFX_SOCK_QOS_EVT_PARA_NUM
74
75 typedef enum {
76 FILLP_DFX_EVT_LINK_EXCEPTION,
77 FILLP_DFX_EVT_PKT_EXCEPTION,
78 FILLP_DFX_EVT_SOCK_QOS_STATUS,
79 FILLP_DFX_EVT_DFX_MAX,
80 } FillpDfxEvt;
81
82 static const FillpDfxEvent g_fillpDfxEvtMsg[FILLP_DFX_EVT_DFX_MAX] = {
83 [FILLP_DFX_EVT_LINK_EXCEPTION] = {
84 .eventName = "FILLP_LINK_EVT",
85 .type = FILLP_DFX_EVENT_TYPE_FAULT,
86 .level = FILLP_DFX_EVENT_LEVEL_MINOR,
87 .paramNum = FILLP_DFX_LINK_EVT_PARA_NUM,
88 },
89 [FILLP_DFX_EVT_PKT_EXCEPTION] = {
90 .eventName = "FILLP_PKT_EVT",
91 .type = FILLP_DFX_EVENT_TYPE_STATISTIC,
92 .level = FILLP_DFX_EVENT_LEVEL_MINOR,
93 .paramNum = FILLP_DFX_PKT_EVT_PARA_NUM,
94 },
95 [FILLP_DFX_EVT_SOCK_QOS_STATUS] = {
96 .eventName = "FILLP_SOCK_QOS_EVT",
97 .type = FILLP_DFX_EVENT_TYPE_STATISTIC,
98 .level = FILLP_DFX_EVENT_LEVEL_MINOR,
99 .paramNum = FILLP_DFX_SOCK_QOS_EVT_PARA_NUM,
100 },
101 };
102
103 static const FillpDfxEventParam g_fillpDfxEvtParam[FILLP_DFX_EVT_DFX_MAX][FILLP_EVT_MAX_PARA_NUM] = {
104 [FILLP_DFX_EVT_LINK_EXCEPTION] = {
105 {
106 .type = FILLP_DFX_PARAM_TYPE_UINT32,
107 .paramName = "SOCK_IDX",
108 },
109 {
110 .type = FILLP_DFX_PARAM_TYPE_UINT8,
111 .paramName = "LINK_EVT_TYPE",
112 },
113 },
114 [FILLP_DFX_EVT_PKT_EXCEPTION] = {
115 {
116 .type = FILLP_DFX_PARAM_TYPE_UINT32,
117 .paramName = "SOCK_IDX",
118 },
119 {
120 .type = FILLP_DFX_PARAM_TYPE_UINT8,
121 .paramName = "PKT_EVT_TYPE",
122 },
123 {
124 .type = FILLP_DFX_PARAM_TYPE_UINT32,
125 .paramName = "DROP_CNT",
126 },
127 },
128 [FILLP_DFX_EVT_SOCK_QOS_STATUS] = {
129 {
130 .type = FILLP_DFX_PARAM_TYPE_UINT32,
131 .paramName = "SOCK_IDX",
132 },
133 {
134 .type = FILLP_DFX_PARAM_TYPE_UINT32,
135 .paramName = "RTT",
136 },
137 {
138 .type = FILLP_DFX_PARAM_TYPE_UINT32,
139 .paramName = "TOTAL_RECV_PKT",
140 },
141 {
142 .type = FILLP_DFX_PARAM_TYPE_UINT32,
143 .paramName = "TOTAL_RECV_BYTES",
144 },
145 {
146 .type = FILLP_DFX_PARAM_TYPE_UINT32,
147 .paramName = "TOTAL_SEND_PKT",
148 },
149 {
150 .type = FILLP_DFX_PARAM_TYPE_UINT32,
151 .paramName = "TOTAL_SEND_BYTES",
152 },
153 {
154 .type = FILLP_DFX_PARAM_TYPE_UINT32,
155 .paramName = "JITTER",
156 },
157 },
158 };
159
DfxEvtGetParamAddr(const FillpDfxEvtArgs * args,FillpDfxEvt evt,const void * paramVal[])160 static void DfxEvtGetParamAddr(const FillpDfxEvtArgs *args, FillpDfxEvt evt, const void *paramVal[])
161 {
162 const void *paramValTmp[FILLP_DFX_EVT_DFX_MAX][FILLP_EVT_MAX_PARA_NUM] = {
163 [FILLP_DFX_EVT_LINK_EXCEPTION] = {
164 &args->linkEvt.sockIdx,
165 &args->linkEvt.linkEvtType,
166 },
167 [FILLP_DFX_EVT_PKT_EXCEPTION] = {
168 &args->pktEvt.sockIdx,
169 &args->pktEvt.pktEvtType,
170 &args->pktEvt.dropCnt,
171 },
172 [FILLP_DFX_EVT_SOCK_QOS_STATUS] = {
173 &args->sockQos.sockIdx,
174 &args->sockQos.rtt,
175 &args->sockQos.totalReceivedPkt,
176 &args->sockQos.totalReceivedBytes,
177 &args->sockQos.totalSendPkt,
178 &args->sockQos.totalSendBytes,
179 &args->sockQos.jitter,
180 },
181 };
182 (void)memcpy_s((void *)paramVal, sizeof(void *) * FILLP_EVT_MAX_PARA_NUM,
183 (void *)paramValTmp[evt], sizeof(void *) * FILLP_EVT_MAX_PARA_NUM);
184 }
185
FillpDfxDoEvtCbSet(void * softObj,FillpDfxEventCb evtCb)186 void FillpDfxDoEvtCbSet(void *softObj, FillpDfxEventCb evtCb)
187 {
188 g_fillpDfxEvtCb = evtCb;
189 g_fillpDfxSoftObj = softObj;
190 }
191
FillpDfxEvtCbSet(void * softObj,FillpDfxEventCb evtCb)192 FILLP_INT FillpDfxEvtCbSet(void *softObj, FillpDfxEventCb evtCb)
193 {
194 if ((g_spunge == FILLP_NULL_PTR) || (!g_spunge->hasInited)) {
195 FILLP_LOGERR("Fillp not init!");
196 return -1;
197 }
198 FILLP_INT err;
199 struct SpungeHiEventCbMsg msg;
200
201 msg.softObj = softObj;
202 msg.cb = evtCb;
203
204 err = SpungePostMsg(SPUNGE_GET_CUR_INSTANCE(), &msg, MSG_TYPE_SET_HIEVENT_CB, FILLP_TRUE);
205 if (err != ERR_OK) {
206 FILLP_LOGERR("Failed to post msg to fillp to set Hievent callback");
207 return -1;
208 }
209 return 0;
210 }
211
DfxEvtParamValCpy(void * dstVal,const void * srcVal,FillpDfxEventParamType type)212 static void DfxEvtParamValCpy(void *dstVal, const void *srcVal, FillpDfxEventParamType type)
213 {
214 switch (type) {
215 case FILLP_DFX_PARAM_TYPE_BOOL:
216 case FILLP_DFX_PARAM_TYPE_UINT8:
217 *(FILLP_UINT8 *)dstVal = *(FILLP_UINT8 *)srcVal;
218 break;
219 case FILLP_DFX_PARAM_TYPE_UINT16:
220 *(FILLP_UINT16 *)dstVal = *(FILLP_UINT16 *)srcVal;
221 break;
222 case FILLP_DFX_PARAM_TYPE_INT32:
223 case FILLP_DFX_PARAM_TYPE_UINT32:
224 case FILLP_DFX_PARAM_TYPE_FLOAT:
225 *(FILLP_UINT32 *)dstVal = *(FILLP_UINT32 *)srcVal;
226 break;
227 case FILLP_DFX_PARAM_TYPE_UINT64:
228 case FILLP_DFX_PARAM_TYPE_DOUBLE:
229 *(FILLP_ULLONG *)dstVal = *(FILLP_ULLONG *)srcVal;
230 break;
231 case FILLP_DFX_PARAM_TYPE_STRING:
232 if (strcpy_s(dstVal, FILLP_DFX_EVENT_NAME_LEN, srcVal) != EOK) {
233 FILLP_LOGERR("strcpy_s failed");
234 }
235 break;
236 default:
237 FILLP_LOGERR("unknow param type!");
238 break;
239 }
240 }
241
FillpCreateDfxEvtParam(const FillpDfxEvtArgs * args,FillpDfxEvt evt,FILLP_UINT32 paramNum)242 static FillpDfxEventParam *FillpCreateDfxEvtParam(const FillpDfxEvtArgs *args, FillpDfxEvt evt, FILLP_UINT32 paramNum)
243 {
244 FILLP_UINT8 i;
245 const void *paramVal[FILLP_EVT_MAX_PARA_NUM];
246 (void)memset_s(paramVal, sizeof(paramVal), 0, sizeof(paramVal));
247 DfxEvtGetParamAddr(args, evt, ¶mVal[0]);
248 FillpDfxEventParam *param = (FillpDfxEventParam *)calloc(paramNum, sizeof(FillpDfxEventParam));
249 if (param == FILLP_NULL_PTR) {
250 FILLP_LOGERR("calloc param failed!");
251 return FILLP_NULL_PTR;
252 }
253 (void)memcpy_s(param, paramNum * sizeof(FillpDfxEventParam),
254 &g_fillpDfxEvtParam[evt], paramNum * sizeof(FillpDfxEventParam));
255 for (i = 0; i < paramNum; i++) {
256 DfxEvtParamValCpy(¶m[i].val, paramVal[i], param[i].type);
257 }
258 return param;
259 }
260
FillpDfxEvtNotify(const FillpDfxEvtArgs * args,FillpDfxEvt evt)261 static void FillpDfxEvtNotify(const FillpDfxEvtArgs *args, FillpDfxEvt evt)
262 {
263 if (g_fillpDfxEvtCb == FILLP_NULL_PTR) {
264 return;
265 }
266 FillpDfxEvent msg;
267 (void)memcpy_s(&msg, sizeof(FillpDfxEvent), &g_fillpDfxEvtMsg[evt], sizeof(FillpDfxEvent));
268
269 msg.paramArray = FillpCreateDfxEvtParam(args, evt, msg.paramNum);
270 if (msg.paramArray == FILLP_NULL_PTR) {
271 return;
272 }
273 g_fillpDfxEvtCb(g_fillpDfxSoftObj, &msg);
274 free(msg.paramArray);
275 }
276
FillpDfxSockQosNotify(const struct FtSocket * sock)277 static void FillpDfxSockQosNotify(const struct FtSocket *sock)
278 {
279 FillpDfxEvtArgs args;
280 (void)memset_s(&args, sizeof(args), 0, sizeof(args));
281 args.sockQos.sockIdx = (FILLP_UINT32)sock->index;
282
283 const struct FillpPcb *pcb = &sock->netconn->pcb->fpcb;
284 const struct FillpStatisticsTraffic *traffic = &(pcb->statistics.traffic);
285 const struct FillAppFcStastics *appFcStastics = &(pcb->statistics.appFcStastics);
286
287 args.sockQos.rtt = appFcStastics->periodRtt;
288 args.sockQos.totalReceivedPkt = traffic->totalRecved;
289 args.sockQos.totalReceivedBytes = traffic->totalRecvedBytes;
290
291 args.sockQos.totalSendPkt = traffic->totalSend;
292 args.sockQos.totalSendBytes = traffic->totalSendBytes;
293 args.sockQos.jitter = (FILLP_UINT32)FILLP_UTILS_US2MS(sock->jitter);
294
295 FillpDfxEvtNotify(&args, FILLP_DFX_EVT_SOCK_QOS_STATUS);
296 }
297
DfxGetPktPraseFailNode(FILLP_INT sockIdx)298 static FillpDfxPktParseFailNode *DfxGetPktPraseFailNode(FILLP_INT sockIdx)
299 {
300 struct HlistNode *pos = FILLP_NULL_PTR;
301 struct HlistNode *next = FILLP_NULL_PTR;
302 HLIST_FOREACH_SAFE(pos, next, &g_fillpDfxPktPraseFailList) {
303 FillpDfxPktParseFailNode *node = (FillpDfxPktParseFailNode *)pos;
304 if (node->sockIdx == sockIdx) {
305 return node;
306 }
307 }
308 return FILLP_NULL_PTR;
309 }
310
FillpDfxSockLinkAndQosNotify(const struct FtSocket * sock,FillpDfxLinkEvtType evtType)311 void FillpDfxSockLinkAndQosNotify(const struct FtSocket *sock, FillpDfxLinkEvtType evtType)
312 {
313 FillpDfxEvtArgs args;
314 (void)memset_s(&args, sizeof(args), 0, sizeof(args));
315 args.linkEvt.sockIdx = (FILLP_UINT32)sock->index;
316 args.linkEvt.linkEvtType = evtType;
317 FillpDfxEvtNotify(&args, FILLP_DFX_EVT_LINK_EXCEPTION);
318
319 if (sock->netconn->state == CONN_STATE_CONNECTED) {
320 FillpDfxSockQosNotify(sock);
321 }
322
323 FillpDfxPktParseFailNode *node = DfxGetPktPraseFailNode(sock->index);
324 if (node == FILLP_NULL_PTR) {
325 return;
326 }
327 if (node->dropCnt == node->lastReportCnt) {
328 HlistDelNode(&node->node);
329 free(node);
330 return;
331 }
332 (void)memset_s(&args, sizeof(args), 0, sizeof(args));
333 args.pktEvt.sockIdx = (FILLP_UINT32)sock->index;
334 args.pktEvt.pktEvtType = FILLP_DFX_PKT_PARSE_FAIL;
335 args.pktEvt.dropCnt = node->dropCnt;
336 HlistDelNode(&node->node);
337 free(node);
338 FillpDfxEvtNotify(&args, FILLP_DFX_EVT_PKT_EXCEPTION);
339 }
340
FillpDfxPktNotify(FILLP_INT sockIdx,FillpDfxPktEvtType evtType,FILLP_UINT32 dropCnt)341 void FillpDfxPktNotify(FILLP_INT sockIdx, FillpDfxPktEvtType evtType, FILLP_UINT32 dropCnt)
342 {
343 FillpDfxPktParseFailNode *node = FILLP_NULL_PTR;
344 if (evtType == FILLP_DFX_PKT_PARSE_FAIL) {
345 node = DfxGetPktPraseFailNode(sockIdx);
346 if (node == FILLP_NULL_PTR) {
347 node = (FillpDfxPktParseFailNode *)calloc(1U, sizeof(FillpDfxPktParseFailNode));
348 if (node == FILLP_NULL_PTR) {
349 FILLP_LOGERR("calloc node failed!");
350 return;
351 }
352 HlistAddTail(&g_fillpDfxPktPraseFailList, &node->node);
353 }
354 node->dropCnt += dropCnt;
355 if (node->dropCnt - node->lastReportCnt < FILLP_DFX_PKT_EVT_DROP_THRESHOLD) {
356 return;
357 }
358 }
359 FillpDfxEvtArgs args;
360 (void)memset_s(&args, sizeof(args), 0, sizeof(args));
361 args.pktEvt.sockIdx = (FILLP_UINT32)sockIdx;
362 args.pktEvt.pktEvtType = evtType;
363 if (evtType == FILLP_DFX_PKT_PARSE_FAIL) {
364 args.pktEvt.dropCnt = node->dropCnt;
365 node->lastReportCnt = node->dropCnt;
366 } else {
367 args.pktEvt.dropCnt = dropCnt;
368 }
369 FillpDfxEvtNotify(&args, FILLP_DFX_EVT_PKT_EXCEPTION);
370 }
371
372 #ifdef FILLP_ENABLE_DFX_HIDUMPER
373 #define CRLF "\r\n"
374 #define FILLP_DFX_DUMP_BUF_LEN (2048U)
375 #define FILLP_DFX_DUMP_ONE_SOCK_BUF (102U)
376 #define FILLP_DFX_DUMP_MAX_ARGC (20U)
377 #define FILLP_DFX_DUMP_STRTOL_BASE (10)
378 #define FILLP_DFX_DUMP_MAX_OPT_ARG_LEN (10U)
379
380 #define FILLP_DUMP_MSG_ADD_CHECK(data, len, fmt, ...) do { \
381 FILLP_INT ret = sprintf_s(data + len, FILLP_DFX_DUMP_BUF_LEN - len, fmt, ##__VA_ARGS__); \
382 if (ret < 0) { \
383 FILLP_LOGERR("dumper buffer over %u bytes", FILLP_DFX_DUMP_BUF_LEN); \
384 return FILLP_FAILURE; \
385 } \
386 len += (FILLP_UINT32)ret; \
387 } while (0)
388
DoShowHelp(FILLP_CHAR * data,FILLP_UINT32 * len)389 static FILLP_INT DoShowHelp(FILLP_CHAR *data, FILLP_UINT32 *len)
390 {
391 FILLP_DUMP_MSG_ADD_CHECK(data, *len, CRLF"Usage: dstream <opt>"CRLF);
392 FILLP_DUMP_MSG_ADD_CHECK(data, *len, " -h show this help"CRLF);
393 FILLP_DUMP_MSG_ADD_CHECK(data, *len, " -V show version"CRLF);
394 FILLP_DUMP_MSG_ADD_CHECK(data, *len, " -l show debug log level"CRLF);
395 FILLP_DUMP_MSG_ADD_CHECK(data, *len, " -n show socket list, and info of socket"CRLF);
396 FILLP_DUMP_MSG_ADD_CHECK(data, *len, " -s <fd> show socket <fd> common config and flow config"CRLF);
397 FILLP_DUMP_MSG_ADD_CHECK(data, *len, " -q <fd> show socket <fd> qos"CRLF);
398 FILLP_DUMP_MSG_ADD_CHECK(data, *len, " -f <fd> show socket <fd> frame info"CRLF);
399 FILLP_DUMP_MSG_ADD_CHECK(data, *len, " -m <0/1> disable/enable management message"CRLF);
400 return FILLP_SUCCESS;
401 }
402
FillpDumpShowHelp(void * softObj,FillpDfxDumpFunc dump)403 static FILLP_INT FillpDumpShowHelp(void *softObj, FillpDfxDumpFunc dump)
404 {
405 FILLP_CHAR data[FILLP_DFX_DUMP_BUF_LEN];
406 FILLP_UINT32 len = 0;
407 if (DoShowHelp(data, &len) != FILLP_SUCCESS) {
408 return FILLP_FAILURE;
409 }
410 dump(softObj, data, len);
411 return FILLP_SUCCESS;
412 }
413
DoShowVersion(FILLP_CHAR * data,FILLP_UINT32 * len)414 static inline FILLP_INT DoShowVersion(FILLP_CHAR *data, FILLP_UINT32 *len)
415 {
416 FILLP_DUMP_MSG_ADD_CHECK(data, *len, CRLF FILLP_VERSION CRLF);
417 return FILLP_SUCCESS;
418 }
419
FillpDumpShowVer(void * softObj,FillpDfxDumpFunc dump)420 static FILLP_INT FillpDumpShowVer(void *softObj, FillpDfxDumpFunc dump)
421 {
422 FILLP_CHAR data[FILLP_DFX_DUMP_BUF_LEN];
423 FILLP_UINT32 len = 0;
424 if (DoShowVersion(data, &len) != FILLP_SUCCESS) {
425 return FILLP_FAILURE;
426 }
427 dump(softObj, data, len);
428 return FILLP_SUCCESS;
429 }
430
DoShowLogLevel(FILLP_CHAR * data,FILLP_UINT32 * len)431 static inline FILLP_INT DoShowLogLevel(FILLP_CHAR *data, FILLP_UINT32 *len)
432 {
433 FILLP_DUMP_MSG_ADD_CHECK(data, *len, CRLF"Current log level: %hhu"CRLF, g_fillpLmGlobal.debugLevel);
434 return FILLP_SUCCESS;
435 }
436
FillpDumpShowLogLevel(void * softObj,FillpDfxDumpFunc dump)437 static FILLP_INT FillpDumpShowLogLevel(void *softObj, FillpDfxDumpFunc dump)
438 {
439 FILLP_CHAR data[FILLP_DFX_DUMP_BUF_LEN];
440 FILLP_UINT32 len = 0;
441 if (DoShowLogLevel(data, &len) != FILLP_SUCCESS) {
442 return FILLP_FAILURE;
443 }
444 dump(softObj, data, len);
445 return FILLP_SUCCESS;
446 }
447
DoShowSockConfigRes(FILLP_INT sockIndex,FILLP_CONST struct GlobalAppResource * resource,FILLP_CHAR * data,FILLP_UINT32 * len)448 static FILLP_INT32 DoShowSockConfigRes(FILLP_INT sockIndex, FILLP_CONST struct GlobalAppResource *resource,
449 FILLP_CHAR *data, FILLP_UINT32 *len)
450 {
451 FILLP_CONST struct GlobalAppCommon *common = &resource->common;
452 FILLP_CONST struct GlobalAppFlowControl *fc = &resource->flowControl;
453 FILLP_DUMP_MSG_ADD_CHECK(data, *len, CRLF"Following are config resource data for socket %d:"CRLF, sockIndex);
454 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "Max udp tx burst number: %u"CRLF, resource->udp.txBurst);
455 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "Keep alive timeout: %u"CRLF, common->keepAliveTime);
456 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "Max server allow send cache: %u"CRLF, common->maxServerAllowSendCache);
457 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "Max server allow receive cache: %u"CRLF, common->maxServerAllowRecvCache);
458 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "Max send cache: %u"CRLF, common->sendCache);
459 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "Max receive cache: %u"CRLF, common->recvCache);
460 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "Max send buffer size: %u"CRLF, common->udpSendBufSize);
461 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "Enable nack delay flag: %hhu"CRLF, common->enableNackDelay);
462 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "Nack delay timeout: %lld"CRLF, common->nackDelayTimeout);
463 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "Enlarge pack interval falg: %hhu"CRLF, common->enlargePackIntervalFlag);
464 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "Max receive buffer size: %u"CRLF, common->recvBufSize);
465 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "Flow control: opposite set rate: %u"CRLF, fc->oppositeSetRate);
466 FILLP_DUMP_MSG_ADD_CHECK(data, *len, " use const stack send rate: %hhu"CRLF, fc->constRateEnbale);
467 FILLP_DUMP_MSG_ADD_CHECK(data, *len, " max send rate: %u Kbps"CRLF, fc->maxRate);
468 FILLP_DUMP_MSG_ADD_CHECK(data, *len, " max recv rate: %u Kbps"CRLF, fc->maxRecvRate);
469 FILLP_DUMP_MSG_ADD_CHECK(data, *len, " packet size: %hu"CRLF, fc->pktSize);
470 FILLP_DUMP_MSG_ADD_CHECK(data, *len, " slow start: %hhu"CRLF, fc->slowStart);
471 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "Timer config: connection timeout: %u(s)"CRLF, common->connectTimeout);
472 FILLP_DUMP_MSG_ADD_CHECK(data, *len, " retry timeout: %hu(s)"CRLF, common->connRetryTimeout);
473 FILLP_DUMP_MSG_ADD_CHECK(data, *len, " disconnect retry timeout: %u(s)"CRLF,
474 common->disconnectRetryTimeout);
475 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "------- End of socket config resource data -------"CRLF);
476 return FILLP_SUCCESS;
477 }
478
DumpInvalidSock(FILLP_INT sockIndex,FILLP_CHAR * data,FILLP_UINT32 * len)479 static inline FILLP_INT DumpInvalidSock(FILLP_INT sockIndex, FILLP_CHAR *data, FILLP_UINT32 *len)
480 {
481 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "Invalid socket index %d"CRLF, sockIndex);
482 return FILLP_SUCCESS;
483 }
484
FillpDumpShowSockResource(FILLP_INT sockIndex,void * softObj,FillpDfxDumpFunc dump)485 static FILLP_INT FillpDumpShowSockResource(FILLP_INT sockIndex, void *softObj, FillpDfxDumpFunc dump)
486 {
487 FILLP_CHAR data[FILLP_DFX_DUMP_BUF_LEN];
488 FILLP_UINT32 len = 0;
489 struct FtSocket *sock = SockApiGetAndCheck(sockIndex);
490 if (sock == FILLP_NULL_PTR) {
491 if (DumpInvalidSock(sockIndex, data, &len) == FILLP_SUCCESS) {
492 dump(softObj, data, len);
493 }
494 return FILLP_FAILURE;
495 }
496
497 FILLP_INT32 isOk = DoShowSockConfigRes(sockIndex, &sock->resConf, data, &len);
498 (void)SYS_ARCH_RWSEM_RDPOST(&sock->sockConnSem);
499 if (isOk != FILLP_SUCCESS) {
500 return FILLP_FAILURE;
501 }
502 dump(softObj, data, len);
503 return FILLP_SUCCESS;
504 }
505
DoShowSockListTitle(FILLP_CHAR * data,FILLP_UINT32 * len)506 static inline FILLP_INT32 DoShowSockListTitle(FILLP_CHAR *data, FILLP_UINT32 *len)
507 {
508 FILLP_DUMP_MSG_ADD_CHECK(data, *len, CRLF"%5s\t %6s\t %6s\t %6s\t %6s\t %30s\t %5s\t %30s\t %5s\t %12s"CRLF,
509 "Sock", "Unsend", "Unack", "Redun", "Unrecv", "LocalIP", "Port", "PeerIP", "Port", "State");
510 return FILLP_SUCCESS;
511 }
512
513 static const char *g_sockStateStr[CONN_STATE_CLOSED + 1] = {
514 "IDLE",
515 "LISTENING",
516 "CONNECTING",
517 "CONNECTED",
518 "CLOSING",
519 "CLOSED",
520 };
521
DoShowSockList(FILLP_CONST struct FtSocket * sock,FILLP_CHAR * data,FILLP_UINT32 * len)522 static FILLP_INT32 DoShowSockList(FILLP_CONST struct FtSocket *sock, FILLP_CHAR *data, FILLP_UINT32 *len)
523 {
524 struct sockaddr_in *local = (struct sockaddr_in *)&sock->netconn->pcb->localAddr;
525 struct sockaddr_in *peer = (struct sockaddr_in *)&sock->netconn->pcb->remoteAddr;
526 const struct FillpSendPcb *sendPcb = &sock->netconn->pcb->fpcb.send;
527 FILLP_CHAR localAddr[INET6_ADDRSTRLEN];
528 FILLP_CHAR peerAddr[INET6_ADDRSTRLEN];
529
530 FILLP_INT ipLen = IpAddrAnonymousFormat(localAddr, sizeof(localAddr),
531 (const struct sockaddr *)local, sizeof(struct sockaddr_in6));
532 if (ipLen == NSTACKX_EFAILED) {
533 (void)strcpy_s(localAddr, INET6_ADDRSTRLEN, "NONE");
534 }
535
536 if (sock->netconn->state > CONN_STATE_LISTENING) {
537 ipLen = IpAddrAnonymousFormat(peerAddr, sizeof(peerAddr),
538 (const struct sockaddr *)peer, sizeof(struct sockaddr_in6));
539 if (ipLen == NSTACKX_EFAILED) {
540 FILLP_LOGERR("Anonymous remoteAddr failed");
541 return FILLP_FAILURE;
542 }
543 } else {
544 (void)strcpy_s(peerAddr, INET6_ADDRSTRLEN, "NONE");
545 }
546
547 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "%5d\t %6u\t %6u\t %6u\t %6u\t %30s\t %5hu\t %30s\t %5hu\t %12s"CRLF,
548 sock->index, sendPcb->unSendList.size, sendPcb->unackList.count, sendPcb->redunList.nodeNum,
549 sendPcb->unrecvList.nodeNum, localAddr, FILLP_NTOHS(local->sin_port), peerAddr, FILLP_NTOHS(peer->sin_port),
550 g_sockStateStr[sock->netconn->state]);
551 return FILLP_SUCCESS;
552 }
553
FillpDumpShowSockList(void * softObj,FillpDfxDumpFunc dump)554 static FILLP_INT FillpDumpShowSockList(void *softObj, FillpDfxDumpFunc dump)
555 {
556 if ((g_spunge == FILLP_NULL_PTR) || (!g_spunge->hasInited) || (g_spunge->sockTable == FILLP_NULL_PTR)) {
557 FILLP_LOGERR("Fillp not init!");
558 return FILLP_FAILURE;
559 }
560 struct FtSocket *sock = FILLP_NULL_PTR;
561 FILLP_UINT32 len = 0;
562
563 FILLP_CHAR *data = (FILLP_CHAR *)calloc(1U, g_spunge->resConf.maxSockNum * FILLP_DFX_DUMP_ONE_SOCK_BUF);
564 if (data == FILLP_NULL_PTR) {
565 const FILLP_CHAR *errMsg = "socket list dump buffer calloc failed!";
566 dump(softObj, errMsg, strlen(errMsg) + 1);
567 return FILLP_FAILURE;
568 }
569 if (DoShowSockListTitle(data, &len) != FILLP_SUCCESS) {
570 free(data);
571 return FILLP_FAILURE;
572 }
573
574 FILLP_UINT16 i;
575 for (i = 0; i < SYS_ARCH_ATOMIC_READ(&g_spunge->sockTable->used); i++) {
576 sock = SockApiGetAndCheck(i);
577 if (sock == FILLP_NULL_PTR) {
578 continue;
579 }
580 if (sock->netconn == FILLP_NULL_PTR || sock->netconn->pcb == FILLP_NULL_PTR) {
581 (void)SYS_ARCH_RWSEM_RDPOST(&sock->sockConnSem);
582 continue;
583 }
584 FILLP_INT isOk = DoShowSockList(sock, data, &len);
585 (void)SYS_ARCH_RWSEM_RDPOST(&sock->sockConnSem);
586 if (isOk != FILLP_SUCCESS) {
587 free(data);
588 return FILLP_FAILURE;
589 }
590 }
591 dump(softObj, data, len);
592 free(data);
593 return FILLP_SUCCESS;
594 }
595
DoShowSockQos(FILLP_CONST struct FtSocket * sock,FILLP_CHAR * data,FILLP_UINT32 * len)596 static FILLP_INT DoShowSockQos(FILLP_CONST struct FtSocket *sock, FILLP_CHAR *data, FILLP_UINT32 *len)
597 {
598 const struct FillpPcb *pcb = &sock->netconn->pcb->fpcb;
599 const struct FillpStatisticsTraffic *traffic = &(pcb->statistics.traffic);
600 const struct FillAppFcStastics *appFcStastics = &(pcb->statistics.appFcStastics);
601 FILLP_UINT32 trafficLiveTime = (FILLP_UINT32)FILLP_UTILS_US2S(SYS_ARCH_GET_CUR_TIME_LONGLONG() -
602 pcb->connTimestamp);
603 trafficLiveTime = (trafficLiveTime == 0) ? 1 : trafficLiveTime;
604
605 FILLP_DUMP_MSG_ADD_CHECK(data, *len, CRLF"%8s\t %12s\t %13s\t %19s\t %18s\t %10s\t %10s\t %19s\t %19s\t %10s"CRLF,
606 "Rtt(ms)", "ReceivedPkt", "ReceivedBytes", "RecvPktLoss(0.01%)", "RecvBytesRate(Bps)",
607 "SendPkt", "SendBytes", "SendPktLoss(0.01%)", "SendBytesRate(Bps)", "Jetter(us)");
608 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "%8u\t %12u\t %13u\t %19u\t %18u\t %10u\t %10u\t %19u\t %19u\t %10lld\t"CRLF,
609 appFcStastics->periodRtt,
610 traffic->totalRecved,
611 traffic->totalRecvedBytes,
612 (traffic->totalRecved == 0) ? 0 :
613 (traffic->totalRecvLost * FILLP_RECV_PKT_LOSS_H_PERCISION * FILLP_RECV_PKT_LOSS_MAX / traffic->totalRecved),
614 traffic->totalRecvedBytes / trafficLiveTime,
615
616 traffic->totalSend,
617 traffic->totalSendBytes,
618 (traffic->totalSend == 0) ? 0 :
619 (traffic->totalRetryed * FILLP_RECV_PKT_LOSS_H_PERCISION * FILLP_RECV_PKT_LOSS_MAX / traffic->totalSend),
620 traffic->totalSendBytes / trafficLiveTime,
621 sock->jitter);
622 return FILLP_SUCCESS;
623 }
624
FillpDfxGetSock(FILLP_INT sockIndex,void * softObj,FillpDfxDumpFunc dump,FILLP_CHAR * data,FILLP_UINT32 * len)625 static struct FtSocket *FillpDfxGetSock(FILLP_INT sockIndex, void *softObj, FillpDfxDumpFunc dump,
626 FILLP_CHAR *data, FILLP_UINT32 *len)
627 {
628 struct FtSocket *sock = SockApiGetAndCheck(sockIndex);
629 if (sock == FILLP_NULL_PTR || sock->netconn == FILLP_NULL_PTR || sock->netconn->pcb == FILLP_NULL_PTR) {
630 if (sock != FILLP_NULL_PTR) {
631 (void)SYS_ARCH_RWSEM_RDPOST(&sock->sockConnSem);
632 }
633 if (DumpInvalidSock(sockIndex, data, len) == FILLP_SUCCESS) {
634 dump(softObj, data, *len);
635 }
636 return FILLP_NULL_PTR;
637 }
638 return sock;
639 }
640
641 typedef FILLP_INT (*FillpDumpSockDataShowCb)(FILLP_CONST struct FtSocket *sock, FILLP_CHAR *data, FILLP_UINT32 *len);
642
FillpDumpShowSockData(FILLP_INT sockIndex,void * softObj,FillpDfxDumpFunc dump,FillpDumpSockDataShowCb showCb)643 static FILLP_INT FillpDumpShowSockData(FILLP_INT sockIndex, void *softObj, FillpDfxDumpFunc dump,
644 FillpDumpSockDataShowCb showCb)
645 {
646 FILLP_CHAR data[FILLP_DFX_DUMP_BUF_LEN];
647 FILLP_UINT32 len = 0;
648 struct FtSocket *sock = FillpDfxGetSock(sockIndex, softObj, dump, data, &len);
649 if (sock == FILLP_NULL_PTR) {
650 return FILLP_FAILURE;
651 }
652
653 FILLP_INT isOk = showCb(sock, data, &len);
654 (void)SYS_ARCH_RWSEM_RDPOST(&sock->sockConnSem);
655 if (isOk != FILLP_SUCCESS) {
656 return FILLP_FAILURE;
657 }
658 dump(softObj, data, len);
659 return FILLP_SUCCESS;
660 }
661
FillpDumpShowSockQos(FILLP_INT sockIndex,void * softObj,FillpDfxDumpFunc dump)662 static FILLP_INT FillpDumpShowSockQos(FILLP_INT sockIndex, void *softObj, FillpDfxDumpFunc dump)
663 {
664 return FillpDumpShowSockData(sockIndex, softObj, dump, DoShowSockQos);
665 }
666
DoShowFrameStats(FILLP_CONST struct FtSocket * sock,FILLP_CHAR * data,FILLP_UINT32 * len)667 static FILLP_INT DoShowFrameStats(FILLP_CONST struct FtSocket *sock, FILLP_CHAR *data, FILLP_UINT32 *len)
668 {
669 struct FillpFrameStats *stats = &sock->netconn->pcb->fpcb.frameHandle.stats;
670 FILLP_DUMP_MSG_ADD_CHECK(data, *len, CRLF"%20s\t %20s\t %20s\t %20s"CRLF,
671 "iFrameCount", "iFrameTotalSize", "pFrameCount", "pFrameTotalSize");
672 FILLP_DUMP_MSG_ADD_CHECK(data, *len, "%20u\t %20llu\t %20u\t %20llu"CRLF,
673 stats->iFrameCount, stats->iFrameTotalSize, stats->pFrameCount, stats->pFrameTotalSize);
674 return FILLP_SUCCESS;
675 }
676
FillpDumpShowFrameStats(FILLP_INT sockIndex,void * softObj,FillpDfxDumpFunc dump)677 static FILLP_INT FillpDumpShowFrameStats(FILLP_INT sockIndex, void *softObj, FillpDfxDumpFunc dump)
678 {
679 return FillpDumpShowSockData(sockIndex, softObj, dump, DoShowFrameStats);
680 }
681
FillpDumpMgtMsgCb(FILLP_INT optVal,void * softObj,FillpDfxDumpFunc dump)682 static FILLP_INT FillpDumpMgtMsgCb(FILLP_INT optVal, void *softObj, FillpDfxDumpFunc dump)
683 {
684 const FILLP_CHAR *successMsg = "management message set success";
685 const FILLP_CHAR *failMsg = "management message set fail";
686 if (FillpApiSetMgtMsgLog(optVal) != EOK) {
687 dump(softObj, failMsg, strlen(failMsg) + 1);
688 return FILLP_FAILURE;
689 }
690 dump(softObj, successMsg, strlen(successMsg) + 1);
691 return FILLP_SUCCESS;
692 }
693
694 static const FILLP_CHAR *g_optString = "hlns:q:f:m:V";
695 static const FILLP_CHAR *g_optErrMsg = "Parse option fail, please check your option!";
696 typedef FILLP_INT (*FillpDumpOptCb)(FILLP_INT sockIndex, void *softObj, FillpDfxDumpFunc dump);
697 typedef struct {
698 FILLP_INT opt;
699 const NstackGetOptMsg *optMsg;
700 void *softObj;
701 FillpDfxDumpFunc dump;
702 } FillpDfxDumpOptArgs;
703
FillpDfxCheckArg(FILLP_UINT32 argc,const FILLP_CHAR ** argv,FillpDfxDumpFunc dump)704 static FILLP_INT FillpDfxCheckArg(FILLP_UINT32 argc, const FILLP_CHAR **argv, FillpDfxDumpFunc dump)
705 {
706 if (dump == NULL) {
707 FILLP_LOGERR("dump is null");
708 return FILLP_FAILURE;
709 }
710 if (argc <= 1 || argc > FILLP_DFX_DUMP_MAX_ARGC) {
711 FILLP_LOGERR("argc is invalid %u", argc);
712 return FILLP_FAILURE;
713 }
714 if (argv == FILLP_NULL_PTR) {
715 FILLP_LOGERR("argv is NULL");
716 return FILLP_FAILURE;
717 }
718 FILLP_UINT32 i;
719 for (i = 0; i < argc; i++) {
720 if (argv[i] == FILLP_NULL_PTR) {
721 FILLP_LOGERR("argv[%d] is NULL", i);
722 return FILLP_FAILURE;
723 }
724 }
725 return FILLP_SUCCESS;
726 }
727
IsCommonOptArgLegal(const FILLP_CHAR * optArgs,FILLP_INT opt)728 static FILLP_INT IsCommonOptArgLegal(const FILLP_CHAR *optArgs, FILLP_INT opt)
729 {
730 if (optArgs == FILLP_NULL_PTR) {
731 return FILLP_FAILURE;
732 }
733 size_t len = strnlen(optArgs, FILLP_DFX_DUMP_MAX_OPT_ARG_LEN + 1);
734 if (len == 0 || len > FILLP_DFX_DUMP_MAX_OPT_ARG_LEN) {
735 return FILLP_FAILURE;
736 }
737 if (opt == 'm' && (len != 1 || (optArgs[0] != '0' && optArgs[0] != '1'))) {
738 return FILLP_FAILURE;
739 }
740
741 FILLP_UINT8 i;
742 for (i = 0; i < len; i++) {
743 if (optArgs[i] < '0' || optArgs[i] > '9') {
744 return FILLP_FAILURE;
745 }
746 }
747
748 return FILLP_SUCCESS;
749 }
750
FillpDfxDumpGetOptVal(const FillpDfxDumpOptArgs * optArgStr,FILLP_INT * optVal)751 static FILLP_INT FillpDfxDumpGetOptVal(const FillpDfxDumpOptArgs *optArgStr, FILLP_INT *optVal)
752 {
753 const FILLP_CHAR *optArgs = NstackGetOptArgs(optArgStr->optMsg);
754 if (IsCommonOptArgLegal(optArgs, optArgStr->opt) != FILLP_SUCCESS) {
755 goto INVALID_ARG;
756 }
757 FILLP_LLONG val = strtoll(optArgs, FILLP_NULL_PTR, FILLP_DFX_DUMP_STRTOL_BASE);
758 if (val > INT_MAX) {
759 goto INVALID_ARG;
760 }
761 *optVal = (FILLP_INT)val;
762 return FILLP_SUCCESS;
763
764 INVALID_ARG:
765 optArgStr->dump(optArgStr->softObj, g_optErrMsg, strlen(g_optErrMsg) + 1);
766 (void)FillpDumpShowHelp(optArgStr->softObj, optArgStr->dump);
767 return FILLP_FAILURE;
768 }
769
FillpDfxDumpDealOptWithArgs(const FillpDfxDumpOptArgs * optArgStr,FillpDumpOptCb cb)770 static FILLP_INT FillpDfxDumpDealOptWithArgs(const FillpDfxDumpOptArgs *optArgStr, FillpDumpOptCb cb)
771 {
772 FILLP_INT optVal;
773 if (FillpDfxDumpGetOptVal(optArgStr, &optVal) != FILLP_SUCCESS) {
774 return FILLP_FAILURE;
775 }
776 return cb(optVal, optArgStr->softObj, optArgStr->dump);
777 }
778
FillpDfxDumpDoParseOpt(const FillpDfxDumpOptArgs * optArgStr)779 static FILLP_INT FillpDfxDumpDoParseOpt(const FillpDfxDumpOptArgs *optArgStr)
780 {
781 FILLP_INT ret;
782 switch (optArgStr->opt) {
783 case 'h':
784 ret = FillpDumpShowHelp(optArgStr->softObj, optArgStr->dump);
785 break;
786 case 'l':
787 ret = FillpDumpShowLogLevel(optArgStr->softObj, optArgStr->dump);
788 break;
789 case 'n':
790 ret = FillpDumpShowSockList(optArgStr->softObj, optArgStr->dump);
791 break;
792 case 's':
793 ret = FillpDfxDumpDealOptWithArgs(optArgStr, FillpDumpShowSockResource);
794 break;
795 case 'q':
796 ret = FillpDfxDumpDealOptWithArgs(optArgStr, FillpDumpShowSockQos);
797 break;
798 case 'f':
799 ret = FillpDfxDumpDealOptWithArgs(optArgStr, FillpDumpShowFrameStats);
800 break;
801 case 'V':
802 ret = FillpDumpShowVer(optArgStr->softObj, optArgStr->dump);
803 break;
804 case 'm':
805 ret = FillpDfxDumpDealOptWithArgs(optArgStr, FillpDumpMgtMsgCb);
806 break;
807 default:
808 optArgStr->dump(optArgStr->softObj, g_optErrMsg, strlen(g_optErrMsg) + 1);
809 (void)FillpDumpShowHelp(optArgStr->softObj, optArgStr->dump);
810 ret = FILLP_FAILURE;
811 }
812 return ret;
813 }
814
FillpDfxDump(FILLP_UINT32 argc,const FILLP_CHAR ** argv,void * softObj,FillpDfxDumpFunc dump)815 FILLP_INT FillpDfxDump(FILLP_UINT32 argc, const FILLP_CHAR **argv, void *softObj, FillpDfxDumpFunc dump)
816 {
817 FILLP_INT opt = 0;
818 const FILLP_CHAR *dumpFailMsg = "dump show failed!";
819 if (FillpDfxCheckArg(argc, argv, dump) != FILLP_SUCCESS) {
820 if (dump != NULL) {
821 dump(softObj, g_optErrMsg, strlen(g_optErrMsg) + 1);
822 (void)FillpDumpShowHelp(softObj, dump);
823 }
824 return -1;
825 }
826
827 FILLP_BOOL isParseOpt = FILLP_FALSE;
828 NstackGetOptMsg optMsg;
829 (void)NstackInitGetOptMsg(&optMsg);
830 while ((opt = NstackGetOpt(&optMsg, (FILLP_INT32)argc, argv, g_optString)) != NSTACK_GETOPT_END_OF_STR) {
831 isParseOpt = FILLP_TRUE;
832 FillpDfxDumpOptArgs optArgStr = {opt, &optMsg, softObj, dump};
833 if (FillpDfxDumpDoParseOpt(&optArgStr) != FILLP_SUCCESS) {
834 dump(softObj, dumpFailMsg, strlen(dumpFailMsg) + 1);
835 return -1;
836 }
837 }
838 if (!isParseOpt) {
839 dump(softObj, g_optErrMsg, strlen(g_optErrMsg) + 1);
840 (void)FillpDumpShowHelp(softObj, dump);
841 return -1;
842 }
843 return 0;
844 }
845
846 #endif /* FILLP_ENABLE_DFX_HIDUMPER */
847
848