Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "utrace_socket.h"
12 : #include "adiag_lock.h"
13 : #include "adiag_utils.h"
14 : #include "adiag_print.h"
15 : #include "trace_recorder.h"
16 : #include "trace_system_api.h"
17 :
18 : STATIC int32_t g_clientSockFd = -1;
19 : STATIC AdiagLock g_clientSockLock = TRACE_MUTEX_INITIALIZER;
20 :
21 44 : void UtraceSetSocketFd(int32_t fd)
22 : {
23 44 : (void)AdiagLockGet(&g_clientSockLock);
24 44 : g_clientSockFd = fd;
25 44 : (void)AdiagLockRelease(&g_clientSockLock);
26 44 : }
27 :
28 2 : int32_t UtraceGetSocketFd(void)
29 : {
30 2 : (void)AdiagLockGet(&g_clientSockLock);
31 2 : int32_t fd = g_clientSockFd;
32 2 : (void)AdiagLockRelease(&g_clientSockLock);
33 2 : return fd;
34 : }
35 :
36 6 : bool UtraceIsSocketFdValid(void)
37 : {
38 6 : (void)AdiagLockGet(&g_clientSockLock);
39 6 : bool isValid = (g_clientSockFd >= 0);
40 6 : (void)AdiagLockRelease(&g_clientSockLock);
41 6 : return isValid;
42 : }
43 :
44 2 : STATIC TraStatus TraceGetSocketPathByVfid(uint32_t vfid, char* socketPath, uint32_t pathLen)
45 : {
46 2 : int32_t ret = snprintf_s(socketPath, pathLen, pathLen - 1, "%s%s_%u", SOCKET_FILE_DIR, SOCKET_FILE, vfid);
47 2 : if (ret == -1) {
48 1 : ADIAG_ERR("snprintf_s failed, strerr=%s, pid=%d, vfid=%u.", strerror(AdiagGetErrorCode()), getpid(), vfid);
49 1 : return TRACE_FAILURE;
50 : }
51 1 : return TRACE_SUCCESS;
52 : }
53 :
54 13 : STATIC TraStatus TraceGetSocketPathByPfid(char* socketPath, uint32_t pathLen)
55 : {
56 13 : int32_t ret = snprintf_s(socketPath, pathLen, pathLen - 1, "%s%s", SOCKET_FILE_DIR, SOCKET_FILE);
57 13 : if (ret == -1) {
58 1 : ADIAG_ERR("snprintf_s failed, strerr=%s, pid=%d.", strerror(AdiagGetErrorCode()), getpid());
59 1 : return TRACE_FAILURE;
60 : }
61 12 : return TRACE_SUCCESS;
62 : }
63 :
64 : /**
65 : * @brief : get socket path when trace server create socket
66 : * @param [in] : devId device id
67 : * @param [out] : socketPath socket path
68 : * @param [in] : pathLen path length
69 : * @return : !=0 failure; ==0 success
70 : */
71 16 : STATIC TraStatus UtraceGetTraceSocketPath(uint32_t devId, char* socketPath, uint32_t pathLen)
72 : {
73 16 : if ((devId >= MIN_VFID_NUM) && (devId <= MAX_VFID_NUM)) {
74 : // devId(32~63) is vfid, strcat socket path with "socket_trace_vfid"
75 2 : return TraceGetSocketPathByVfid(devId, socketPath, pathLen);
76 14 : } else if (devId < MIN_VFID_NUM) {
77 : // devId(0~31) is pfid, strcat socket path with "socket_trace"
78 13 : return TraceGetSocketPathByPfid(socketPath, pathLen);
79 : } else {
80 1 : return TRACE_FAILURE;
81 : }
82 : }
83 :
84 17 : int32_t UtraceCreateSocket(uint32_t devId)
85 : {
86 : struct sockaddr_un addr;
87 17 : int32_t pid = (int32_t)getpid();
88 17 : int32_t sockFd = TraceSocket(AF_UNIX, (uint32_t)SOCK_DGRAM | (uint32_t)SOCK_NONBLOCK, 0);
89 17 : ADIAG_CHK_EXPR_ACTION(
90 : sockFd == TRACE_FAILURE, return TRACE_FAILURE, "create socket failed, strerr=%s, pid=%d",
91 : strerror(AdiagGetErrorCode()), pid);
92 :
93 17 : const int32_t nSendBuf = 2097152; // 2MB
94 : int32_t ret;
95 : do {
96 17 : ret = setsockopt(sockFd, SOL_SOCKET, SO_SNDBUF, (const char*)&nSendBuf, sizeof(int));
97 17 : if (ret < 0) {
98 1 : ADIAG_ERR("set socket option failed, strerr=%s, pid=%d.", strerror(AdiagGetErrorCode()), pid);
99 1 : break;
100 : }
101 :
102 16 : (void)memset_s(&addr, sizeof(addr), 0, sizeof(addr));
103 :
104 16 : addr.sun_family = AF_UNIX;
105 16 : char socketPath[SOCKET_PATH_MAX_LENGTH + 1U] = {0};
106 16 : ret = UtraceGetTraceSocketPath(devId, socketPath, SOCKET_PATH_MAX_LENGTH);
107 16 : if (ret != TRACE_SUCCESS) {
108 3 : ADIAG_ERR("get socket path failed, ret=%d, pid=%d, devId=%u.", ret, pid, devId);
109 3 : break;
110 : }
111 :
112 13 : ret = strcpy_s(addr.sun_path, sizeof(addr.sun_path), socketPath);
113 13 : if (ret != EOK) {
114 0 : ADIAG_ERR("strcpy failed, ret=%d, pid=%d, devId=%u.", ret, pid, devId);
115 0 : break;
116 : }
117 :
118 13 : ret = TraceConnect(sockFd, (struct sockaddr*)&addr, sizeof(addr));
119 13 : if (ret != TRACE_SUCCESS) {
120 3 : ADIAG_ERR("connect to trace server failed, path %s, ret=%d, pid=%d.", addr.sun_path, ret, pid);
121 3 : break;
122 : }
123 10 : ADIAG_INF("create socket succeed, socket path: %s, fd %d.", addr.sun_path, sockFd);
124 10 : return sockFd;
125 : } while (0);
126 :
127 7 : ret = TraceCloseSocket(sockFd);
128 7 : if (ret != TRACE_SUCCESS) {
129 2 : ADIAG_ERR("close socket failed, strerr=%s, pid=%d.", strerror(AdiagGetErrorCode()), pid);
130 : }
131 7 : return TRACE_FAILURE;
132 : }
133 :
134 14 : void UtraceCloseSocket(void)
135 : {
136 14 : int32_t fd = -1;
137 14 : (void)AdiagLockGet(&g_clientSockLock);
138 14 : if (g_clientSockFd >= 0) {
139 8 : fd = g_clientSockFd;
140 8 : g_clientSockFd = -1;
141 : }
142 14 : (void)AdiagLockRelease(&g_clientSockLock);
143 14 : if (fd >= 0) {
144 8 : (void)TraceCloseSocket(fd);
145 : }
146 14 : }
147 :
148 22 : TraStatus UtraceWriteSocket(uint32_t devId, const char* buffer, uint32_t len)
149 : {
150 22 : if ((buffer == NULL) || (len == 0U)) {
151 2 : return TRACE_FAILURE;
152 : }
153 :
154 20 : int32_t fd = -1;
155 20 : (void)AdiagLockGet(&g_clientSockLock);
156 20 : if (g_clientSockFd < 0) {
157 10 : fd = UtraceCreateSocket(devId);
158 10 : if (fd == TRACE_FAILURE) {
159 3 : (void)AdiagLockRelease(&g_clientSockLock);
160 3 : return TRACE_FAILURE;
161 : }
162 7 : g_clientSockFd = fd;
163 : }
164 17 : fd = g_clientSockFd;
165 17 : TraStatus ret = TraceRecorderWrite(fd, buffer, len);
166 17 : if (ret != TRACE_SUCCESS) {
167 2 : g_clientSockFd = -1;
168 : }
169 17 : (void)AdiagLockRelease(&g_clientSockLock);
170 17 : if ((ret != TRACE_SUCCESS) && (fd >= 0)) {
171 2 : (void)TraceCloseSocket(fd);
172 : }
173 17 : return ret;
174 : }
|