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_log.h"
25 #include "lnn_map.h"
26 #include "softbus_adapter_mem.h"
27 #include "softbus_def.h"
28 #include "softbus_errcode.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 uint64_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 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(uint64_t laneId,LaneModel * laneModel)72 static void AddLaneIdNode(uint64_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 LNN_LOGE(LNN_LANE, "laneId has been added");
78 return;
79 }
80 }
81 LaneIdInfo *newNode = (LaneIdInfo *)SoftBusCalloc(sizeof(LaneIdInfo));
82 if (newNode == NULL) {
83 LNN_LOGE(LNN_LANE, "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(uint64_t laneId,LaneModel * laneModel)92 static void DeleteLaneIdNode(uint64_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(uint64_t laneId,uint32_t profileId,LaneProfile * laneProfile)106 static int32_t AddLaneModel(uint64_t laneId, uint32_t profileId, LaneProfile *laneProfile)
107 {
108 if (ModelLock() != SOFTBUS_OK) {
109 LNN_LOGE(LNN_LANE, "get lock fail");
110 return SOFTBUS_LOCK_ERR;
111 }
112 LaneModel *laneModel = (LaneModel *)LnnReadData(&g_profileMap, profileId);
113 if (laneModel != NULL) {
114 AddLaneIdNode(laneId, laneModel);
115 ModelUnlock();
116 return SOFTBUS_OK;
117 }
118
119 LaneModel newModel;
120 (void)memset_s(&newModel, sizeof(LaneModel), 0, sizeof(LaneModel));
121 if (memcpy_s(&newModel.profile, sizeof(LaneProfile), laneProfile, sizeof(LaneProfile)) != EOK) {
122 LNN_LOGE(LNN_LANE, "addLaneModel memcpy fail");
123 ModelUnlock();
124 return SOFTBUS_MEM_ERR;
125 }
126
127 int32_t ret = LnnCreateData(&g_profileMap, profileId, &newModel, sizeof(LaneModel));
128 if (ret != SOFTBUS_OK) {
129 ModelUnlock();
130 return ret;
131 }
132 laneModel = (LaneModel *)LnnReadData(&g_profileMap, profileId);
133 if (laneModel != NULL) {
134 ListInit(&(laneModel->laneIdList));
135 AddLaneIdNode(laneId, laneModel);
136 }
137 ModelUnlock();
138 return SOFTBUS_OK;
139 }
140
BindLaneIdToProfile(uint64_t laneId,LaneProfile * profile)141 int32_t BindLaneIdToProfile(uint64_t laneId, LaneProfile *profile)
142 {
143 if (profile == NULL) {
144 LNN_LOGE(LNN_LANE, "profile is null");
145 return SOFTBUS_INVALID_PARAM;
146 }
147 LaneGenerateParam param;
148 param.linkType = profile->linkType;
149 param.transType = profile->content;
150 param.priority = profile->priority;
151 uint32_t profileId = GenerateLaneProfileId(¶m);
152 profile->serialNum = profileId;
153 int32_t ret = AddLaneModel(laneId, profileId, profile);
154 if (ret != SOFTBUS_OK) {
155 return ret;
156 }
157 return SOFTBUS_OK;
158 }
159
UnbindLaneIdFromProfile(uint64_t laneId,uint32_t profileId)160 void UnbindLaneIdFromProfile(uint64_t laneId, uint32_t profileId)
161 {
162 if (ModelLock() != SOFTBUS_OK) {
163 LNN_LOGE(LNN_LANE, "get lock fail");
164 return;
165 }
166 LaneModel *laneModel = (LaneModel *)LnnReadData(&g_profileMap, profileId);
167 if (laneModel == NULL) {
168 ModelUnlock();
169 return;
170 }
171 DeleteLaneIdNode(laneId, laneModel);
172 if (laneModel->ref == 0) {
173 LnnDeleteData(&g_profileMap, profileId);
174 }
175 ModelUnlock();
176 }
177
GetLaneProfile(uint32_t profileId,LaneProfile * profile)178 int32_t GetLaneProfile(uint32_t profileId, LaneProfile *profile)
179 {
180 if (profile == NULL) {
181 LNN_LOGE(LNN_LANE, "profile is null");
182 return SOFTBUS_INVALID_PARAM;
183 }
184 if (ModelLock() != SOFTBUS_OK) {
185 return SOFTBUS_LOCK_ERR;
186 }
187 LaneModel *laneModel = (LaneModel *)LnnReadData(&g_profileMap, profileId);
188 if (laneModel == NULL) {
189 ModelUnlock();
190 LNN_LOGE(LNN_LANE, "read laneModel fail");
191 return SOFTBUS_INVALID_PARAM;
192 }
193 if (memcpy_s(profile, sizeof(LaneProfile), &laneModel->profile, sizeof(LaneProfile)) != EOK) {
194 LNN_LOGE(LNN_LANE, "profile memcpy fail");
195 ModelUnlock();
196 return SOFTBUS_MEM_ERR;
197 }
198 ModelUnlock();
199 return SOFTBUS_OK;
200 }
201
GetLaneIdList(uint32_t profileId,uint64_t ** laneIdList,uint32_t * listSize)202 int32_t GetLaneIdList(uint32_t profileId, uint64_t **laneIdList, uint32_t *listSize)
203 {
204 if (ModelLock() != SOFTBUS_OK) {
205 LNN_LOGE(LNN_LANE, "get lock fail");
206 return SOFTBUS_LOCK_ERR;
207 }
208 LaneModel *laneModel = (LaneModel *)LnnReadData(&g_profileMap, profileId);
209 if (laneModel == NULL) {
210 ModelUnlock();
211 LNN_LOGE(LNN_LANE, "read laneModel fail");
212 return SOFTBUS_INVALID_PARAM;
213 }
214 if (laneModel->ref == 0) {
215 LNN_LOGE(LNN_LANE, "ref count is zero");
216 ModelUnlock();
217 return SOFTBUS_INVALID_PARAM;
218 }
219 *laneIdList = (uint64_t *)SoftBusCalloc(sizeof(uint64_t) * laneModel->ref);
220 if (*laneIdList == NULL) {
221 LNN_LOGE(LNN_LANE, "laneIdList malloc fail");
222 ModelUnlock();
223 return SOFTBUS_MALLOC_ERR;
224 }
225 uint32_t cnt = 0;
226 LaneIdInfo *infoNode = NULL;
227 LIST_FOR_EACH_ENTRY(infoNode, &laneModel->laneIdList, LaneIdInfo, node) {
228 (*laneIdList)[cnt] = infoNode->laneId;
229 cnt++;
230 }
231 *listSize = cnt;
232 ModelUnlock();
233 return SOFTBUS_OK;
234 }
235
GetActiveProfileNum(void)236 uint32_t GetActiveProfileNum(void)
237 {
238 uint32_t num = 0;
239 if (ModelLock() != SOFTBUS_OK) {
240 LNN_LOGE(LNN_LANE, "get lock fail");
241 return num;
242 }
243 num = g_profileMap.nodeSize;
244 ModelUnlock();
245 return num;
246 }
247
InitLaneModel(void)248 int32_t InitLaneModel(void)
249 {
250 LnnMapInit(&g_profileMap);
251 if (SoftBusMutexInit(&g_laneModelMutex, NULL) != SOFTBUS_OK) {
252 LNN_LOGE(LNN_LANE, "laneModel mutex init fail");
253 return SOFTBUS_NO_INIT;
254 }
255 return SOFTBUS_OK;
256 }
257
ClearProfileMap(void)258 static void ClearProfileMap(void)
259 {
260 MapIterator *it = LnnMapInitIterator(&g_profileMap);
261 if (it == NULL) {
262 LNN_LOGE(LNN_LANE, "clear profileMap fail");
263 return;
264 }
265 while (LnnMapHasNext(it)) {
266 it = LnnMapNext(it);
267 if (it == NULL || it->node->value == NULL) {
268 break;
269 }
270 LaneModel *laneModel = (LaneModel *)it->node->value;
271 LaneIdInfo *infoNode = NULL;
272 LaneIdInfo *nextNode = NULL;
273 LIST_FOR_EACH_ENTRY_SAFE(infoNode, nextNode, &laneModel->laneIdList, LaneIdInfo, node) {
274 ListDelete(&infoNode->node);
275 SoftBusFree(infoNode);
276 laneModel->ref--;
277 }
278 }
279 LnnMapDeinitIterator(it);
280 LnnMapDelete(&g_profileMap);
281 }
282
DeinitLaneModel(void)283 void DeinitLaneModel(void)
284 {
285 ClearProfileMap();
286 (void)SoftBusMutexDestroy(&g_laneModelMutex);
287 }