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, &paramVal[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(&param[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