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 "lnn_lane_model.h"
17
18 #include <securec.h>
19
20 #include "common_list.h"
21 #include "lnn_lane.h"
22 #include "lnn_lane_common.h"
23 #include "lnn_lane_def.h"
24 #include "lnn_map.h"
25 #include "softbus_adapter_mem.h"
26 #include "softbus_def.h"
27 #include "softbus_errcode.h"
28 #include "softbus_log.h"
29
30 #define LINK_TYPE_SHIFT 26
31 #define TRANS_TYPE_SHIFT 22
32 #define PRIORITY_SHIFT 18
33
34 typedef struct {
35 ListNode node;
36 uint32_t laneId;
37 } LaneIdInfo;
38
39 typedef struct {
40 LaneProfile profile;
41 uint32_t ref;
42 ListNode laneIdList;
43 } LaneModel;
44
45 static Map g_profileMap;
46 static SoftBusMutex g_laneModelMutex;
47
ModelLock(void)48 static int32_t ModelLock(void)
49 {
50 return SoftBusMutexLock(&g_laneModelMutex);
51 }
52
ModelUnlock(void)53 static void ModelUnlock(void)
54 {
55 (void)SoftBusMutexUnlock(&g_laneModelMutex);
56 }
57
58 /*
59 * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
60 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61 * | LinkType |TxType | Pri | Reserved |
62 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63 */
GenerateLaneProfileId(const LaneGenerateParam * param)64 NO_SANITIZE("cfi") uint32_t GenerateLaneProfileId(const LaneGenerateParam *param)
65 {
66 uint32_t laneProfileId = 0;
67 laneProfileId |= ((param->linkType << LINK_TYPE_SHIFT) |
68 (param->transType << TRANS_TYPE_SHIFT) | (param->priority << PRIORITY_SHIFT));
69 return laneProfileId;
70 }
71
AddLaneIdNode(uint32_t laneId,LaneModel * laneModel)72 static void AddLaneIdNode(uint32_t laneId, LaneModel *laneModel)
73 {
74 LaneIdInfo *infoNode = NULL;
75 LIST_FOR_EACH_ENTRY(infoNode, &laneModel->laneIdList, LaneIdInfo, node) {
76 if (infoNode->laneId == laneId) {
77 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "laneId has been added");
78 return;
79 }
80 }
81 LaneIdInfo *newNode = (LaneIdInfo *)SoftBusCalloc(sizeof(LaneIdInfo));
82 if (newNode == NULL) {
83 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "laneId add to list fail");
84 return;
85 }
86 ListInit(&newNode->node);
87 newNode->laneId = laneId;
88 ListAdd(&laneModel->laneIdList, &newNode->node);
89 laneModel->ref++;
90 }
91
DeleteLaneIdNode(uint32_t laneId,LaneModel * laneModel)92 static void DeleteLaneIdNode(uint32_t laneId, LaneModel *laneModel)
93 {
94 LaneIdInfo *item = NULL;
95 LaneIdInfo *next = NULL;
96 LIST_FOR_EACH_ENTRY_SAFE(item, next, &laneModel->laneIdList, LaneIdInfo, node) {
97 if (item->laneId == laneId) {
98 ListDelete(&item->node);
99 SoftBusFree(item);
100 laneModel->ref--;
101 return;
102 }
103 }
104 }
105
AddLaneModel(uint32_t laneId,uint32_t profileId,LaneProfile * laneProfile)106 static int32_t AddLaneModel(uint32_t laneId, uint32_t profileId, LaneProfile *laneProfile)
107 {
108 if (ModelLock() != SOFTBUS_OK) {
109 return SOFTBUS_ERR;
110 }
111 LaneModel *laneModel = (LaneModel *)LnnReadData(&g_profileMap, profileId);
112 if (laneModel != NULL) {
113 AddLaneIdNode(laneId, laneModel);
114 ModelUnlock();
115 return SOFTBUS_OK;
116 }
117
118 LaneModel newModel;
119 (void)memset_s(&newModel, sizeof(LaneModel), 0, sizeof(LaneModel));
120 if (memcpy_s(&newModel.profile, sizeof(LaneProfile), laneProfile, sizeof(LaneProfile)) != EOK) {
121 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "addLaneModel memcpy fail");
122 ModelUnlock();
123 return SOFTBUS_ERR;
124 }
125
126 if (LnnCreateData(&g_profileMap, profileId, &newModel, sizeof(LaneModel)) != SOFTBUS_OK) {
127 ModelUnlock();
128 return SOFTBUS_ERR;
129 }
130 laneModel = (LaneModel *)LnnReadData(&g_profileMap, profileId);
131 if (laneModel != NULL) {
132 ListInit(&(laneModel->laneIdList));
133 AddLaneIdNode(laneId, laneModel);
134 }
135 ModelUnlock();
136 return SOFTBUS_OK;
137 }
138
BindLaneIdToProfile(uint32_t laneId,LaneProfile * profile)139 NO_SANITIZE("cfi") int32_t BindLaneIdToProfile(uint32_t laneId, LaneProfile *profile)
140 {
141 if (profile == NULL) {
142 return SOFTBUS_ERR;
143 }
144 LaneGenerateParam param;
145 param.linkType = profile->linkType;
146 param.transType = profile->content;
147 param.priority = profile->priority;
148 uint32_t profileId = GenerateLaneProfileId(¶m);
149 profile->serialNum = profileId;
150 if (AddLaneModel(laneId, profileId, profile) != SOFTBUS_OK) {
151 return SOFTBUS_ERR;
152 }
153 return SOFTBUS_OK;
154 }
155
UnbindLaneIdFromProfile(uint32_t laneId,uint32_t profileId)156 NO_SANITIZE("cfi") void UnbindLaneIdFromProfile(uint32_t laneId, uint32_t profileId)
157 {
158 if (ModelLock() != SOFTBUS_OK) {
159 return;
160 }
161 LaneModel *laneModel = (LaneModel *)LnnReadData(&g_profileMap, profileId);
162 if (laneModel == NULL) {
163 ModelUnlock();
164 return;
165 }
166 DeleteLaneIdNode(laneId, laneModel);
167 if (laneModel->ref == 0) {
168 LnnDeleteData(&g_profileMap, profileId);
169 }
170 ModelUnlock();
171 }
172
GetLaneProfile(uint32_t profileId,LaneProfile * profile)173 NO_SANITIZE("cfi") int32_t GetLaneProfile(uint32_t profileId, LaneProfile *profile)
174 {
175 if (profile == NULL) {
176 return SOFTBUS_ERR;
177 }
178 if (ModelLock() != SOFTBUS_OK) {
179 return SOFTBUS_ERR;
180 }
181 LaneModel *laneModel = (LaneModel *)LnnReadData(&g_profileMap, profileId);
182 if (laneModel == NULL) {
183 ModelUnlock();
184 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "read laneModel fail");
185 return SOFTBUS_ERR;
186 }
187 if (memcpy_s(profile, sizeof(LaneProfile), &laneModel->profile, sizeof(LaneProfile)) != EOK) {
188 ModelUnlock();
189 return SOFTBUS_ERR;
190 }
191 ModelUnlock();
192 return SOFTBUS_OK;
193 }
194
GetLaneIdList(uint32_t profileId,uint32_t ** laneIdList,uint32_t * listSize)195 NO_SANITIZE("cfi") int32_t GetLaneIdList(uint32_t profileId, uint32_t **laneIdList, uint32_t *listSize)
196 {
197 if (ModelLock() != SOFTBUS_OK) {
198 return SOFTBUS_ERR;
199 }
200 LaneModel *laneModel = (LaneModel *)LnnReadData(&g_profileMap, profileId);
201 if (laneModel == NULL) {
202 ModelUnlock();
203 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "read laneModel fail");
204 return SOFTBUS_ERR;
205 }
206 if (laneModel->ref == 0) {
207 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "ref count is zero");
208 ModelUnlock();
209 return SOFTBUS_ERR;
210 }
211 *laneIdList = (uint32_t *)SoftBusCalloc(sizeof(uint32_t) * laneModel->ref);
212 if (*laneIdList == NULL) {
213 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "laneIdList malloc fail");
214 ModelUnlock();
215 return SOFTBUS_ERR;
216 }
217 uint32_t cnt = 0;
218 LaneIdInfo *infoNode = NULL;
219 LIST_FOR_EACH_ENTRY(infoNode, &laneModel->laneIdList, LaneIdInfo, node) {
220 (*laneIdList)[cnt] = infoNode->laneId;
221 cnt++;
222 }
223 *listSize = cnt;
224 ModelUnlock();
225 return SOFTBUS_OK;
226 }
227
GetActiveProfileNum(void)228 NO_SANITIZE("cfi") uint32_t GetActiveProfileNum(void)
229 {
230 uint32_t num = 0;
231 if (ModelLock() != SOFTBUS_OK) {
232 return num;
233 }
234 num = g_profileMap.nodeSize;
235 ModelUnlock();
236 return num;
237 }
238
InitLaneModel(void)239 NO_SANITIZE("cfi") int32_t InitLaneModel(void)
240 {
241 LnnMapInit(&g_profileMap);
242 if (SoftBusMutexInit(&g_laneModelMutex, NULL) != SOFTBUS_OK) {
243 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "laneModel mutex init fail");
244 return SOFTBUS_ERR;
245 }
246 return SOFTBUS_OK;
247 }
248
ClearProfileMap(void)249 static void ClearProfileMap(void)
250 {
251 MapIterator *it = LnnMapInitIterator(&g_profileMap);
252 if (it == NULL) {
253 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "clear profileMap fail");
254 return;
255 }
256 while (LnnMapHasNext(it)) {
257 it = LnnMapNext(it);
258 if (it == NULL || it->node->value == NULL) {
259 break;
260 }
261 LaneModel *laneModel = (LaneModel *)it->node->value;
262 LaneIdInfo *infoNode = NULL;
263 LaneIdInfo *nextNode = NULL;
264 LIST_FOR_EACH_ENTRY_SAFE(infoNode, nextNode, &laneModel->laneIdList, LaneIdInfo, node) {
265 ListDelete(&infoNode->node);
266 SoftBusFree(infoNode);
267 laneModel->ref--;
268 }
269 }
270 LnnMapDeinitIterator(it);
271 LnnMapDelete(&g_profileMap);
272 }
273
DeinitLaneModel(void)274 NO_SANITIZE("cfi") void DeinitLaneModel(void)
275 {
276 ClearProfileMap();
277 (void)SoftBusMutexDestroy(&g_laneModelMutex);
278 }