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(&param);
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 }