1 /*
2  * Copyright (c) 2024 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_ctrl_lane.h"
17 
18 #include <securec.h>
19 
20 #include "auth_interface.h"
21 #include "bus_center_manager.h"
22 #include "lnn_lane_common.h"
23 #include "lnn_lane_interface.h"
24 #include "lnn_log.h"
25 #include "lnn_lane_select.h"
26 #include "softbus_adapter_mem.h"
27 #include "softbus_errcode.h"
28 #include "wifi_direct_manager.h"
29 
30 typedef struct {
31     ListNode node;
32     uint32_t laneHandle;
33     uint64_t laneId;
34     uint32_t linkListIdx;
35     LaneAllocInfo allocInfo;
36     LanePreferredLinkList linkList;
37     LaneAllocListener listener;
38 } CtrlReqInfo;
39 
40 typedef struct {
41     uint32_t cnt;
42     ListNode list;
43 } CtrlLaneList;
44 
45 static SoftBusMutex g_ctrlLaneMutex;
46 static CtrlLaneList *g_ctrlReqList = NULL;
47 
48 static int32_t CtrlTriggerLink(uint32_t laneHandle);
49 
Lock(void)50 static int32_t Lock(void)
51 {
52     return SoftBusMutexLock(&g_ctrlLaneMutex);
53 }
54 
Unlock(void)55 static void Unlock(void)
56 {
57     (void)SoftBusMutexUnlock(&g_ctrlLaneMutex);
58 }
59 
ConvertAuthLinkToLaneLink(AuthLinkTypeList * authLinkType,LanePreferredLinkList * laneLinkType)60 static int32_t ConvertAuthLinkToLaneLink(AuthLinkTypeList *authLinkType, LanePreferredLinkList *laneLinkType)
61 {
62     if (authLinkType == NULL || laneLinkType == NULL) {
63         LNN_LOGE(LNN_LANE, "param invalid");
64         return SOFTBUS_INVALID_PARAM;
65     }
66     laneLinkType->linkTypeNum = 0;
67     for (uint32_t i = 0; i < authLinkType->linkTypeNum; ++i) {
68         switch (authLinkType->linkType[i]) {
69             case AUTH_LINK_TYPE_WIFI:
70                 laneLinkType->linkType[laneLinkType->linkTypeNum++] = LANE_WLAN_5G;
71                 laneLinkType->linkType[laneLinkType->linkTypeNum++] = LANE_WLAN_2P4G;
72                 break;
73             case AUTH_LINK_TYPE_BR:
74                 laneLinkType->linkType[laneLinkType->linkTypeNum++] = LANE_BR;
75                 break;
76             case AUTH_LINK_TYPE_BLE:
77                 laneLinkType->linkType[laneLinkType->linkTypeNum++] = LANE_BLE;
78                 break;
79             case AUTH_LINK_TYPE_P2P:
80                 laneLinkType->linkType[laneLinkType->linkTypeNum++] = LANE_P2P;
81                 break;
82             case AUTH_LINK_TYPE_ENHANCED_P2P:
83                 laneLinkType->linkType[laneLinkType->linkTypeNum++] = LANE_HML;
84                 break;
85             default:
86                 break;
87         }
88     }
89     return SOFTBUS_OK;
90 }
91 
IsAuthReuseP2p(const char * networkId,const char * udid,AuthLinkType authType)92 bool IsAuthReuseP2p(const char *networkId, const char *udid, AuthLinkType authType)
93 {
94     LaneResource resoureItem;
95     if (memset_s(&resoureItem, sizeof(LaneResource), 0, sizeof(LaneResource)) != EOK) {
96         LNN_LOGE(LNN_LANE, "memset_s LaneResource fail");
97         return false;
98     }
99     if (authType == AUTH_LINK_TYPE_ENHANCED_P2P &&
100         FindLaneResourceByLinkType(udid, LANE_HML, &resoureItem) == SOFTBUS_OK &&
101         !GetWifiDirectManager()->isNegotiateChannelNeeded(networkId, WIFI_DIRECT_LINK_TYPE_HML)) {
102         LNN_LOGI(LNN_LANE, "can use HML");
103         return true;
104     } else if (authType == AUTH_LINK_TYPE_P2P &&
105         FindLaneResourceByLinkType(udid, LANE_P2P, &resoureItem) == SOFTBUS_OK &&
106         !GetWifiDirectManager()->isNegotiateChannelNeeded(networkId, WIFI_DIRECT_LINK_TYPE_P2P)) {
107         LNN_LOGI(LNN_LANE, "can use P2P");
108         return true;
109     } else {
110         return false;
111     }
112 }
113 
GetCtrlReqInfo(uint32_t laneHandle,CtrlReqInfo * reqInfo)114 static int32_t GetCtrlReqInfo(uint32_t laneHandle, CtrlReqInfo *reqInfo)
115 {
116     if (reqInfo == NULL || laneHandle == INVALID_LANE_REQ_ID) {
117         return SOFTBUS_INVALID_PARAM;
118     }
119     if (Lock() != SOFTBUS_OK) {
120         LNN_LOGE(LNN_LANE, "get lock fail");
121         return SOFTBUS_LOCK_ERR;
122     }
123     CtrlReqInfo *item = NULL;
124     LIST_FOR_EACH_ENTRY(item, &g_ctrlReqList->list, CtrlReqInfo, node) {
125         if (item->laneHandle == laneHandle) {
126             if (memcpy_s(reqInfo, sizeof(CtrlReqInfo), item, sizeof(CtrlReqInfo)) != EOK) {
127                 LNN_LOGE(LNN_LANE, "memcpy CtrlReqInfo fail");
128                 Unlock();
129                 return SOFTBUS_MEM_ERR;
130             }
131             Unlock();
132             return SOFTBUS_OK;
133         }
134     }
135     Unlock();
136     return SOFTBUS_LANE_NOT_FOUND;
137 }
138 
DeleteCtrlRequestNode(uint32_t laneHandle)139 static void DeleteCtrlRequestNode(uint32_t laneHandle)
140 {
141     if (Lock() != SOFTBUS_OK) {
142         LNN_LOGE(LNN_LANE, "get lock fail");
143         return;
144     }
145     CtrlReqInfo *item = NULL;
146     CtrlReqInfo *next = NULL;
147     LIST_FOR_EACH_ENTRY_SAFE(item, next, &g_ctrlReqList->list, CtrlReqInfo, node) {
148         if (item->laneHandle == laneHandle) {
149             ListDelete(&item->node);
150             SoftBusFree(item);
151             g_ctrlReqList->cnt--;
152             break;
153         }
154     }
155     Unlock();
156 }
157 
CtrlLinkFail(uint32_t laneHandle,int32_t reason,LaneLinkType linkType)158 static void CtrlLinkFail(uint32_t laneHandle, int32_t reason, LaneLinkType linkType)
159 {
160     (void)linkType;
161     CtrlReqInfo reqInfo;
162     (void)memset_s(&reqInfo, sizeof(CtrlReqInfo), 0, sizeof(CtrlReqInfo));
163     if (GetCtrlReqInfo(laneHandle, &reqInfo) != SOFTBUS_OK) {
164         LNN_LOGE(LNN_LANE, "get lane reqInfo fail");
165         return;
166     }
167     if (reqInfo.linkListIdx >= reqInfo.linkList.linkTypeNum) {
168         reqInfo.listener.onLaneAllocFail(laneHandle, reason);
169         FreeLaneReqId(laneHandle);
170         DeleteCtrlRequestNode(laneHandle);
171         return;
172     }
173     CtrlTriggerLink(laneHandle);
174 }
175 
UpdateCtrlReqInfo(uint32_t laneHandle,uint64_t laneId)176 static void UpdateCtrlReqInfo(uint32_t laneHandle, uint64_t laneId)
177 {
178     if (Lock() != SOFTBUS_OK) {
179         LNN_LOGE(LNN_LANE, "get lock fail");
180         return;
181     }
182     CtrlReqInfo *item = NULL;
183     LIST_FOR_EACH_ENTRY(item, &g_ctrlReqList->list, CtrlReqInfo, node) {
184         if (item->laneHandle == laneHandle) {
185             item->laneId = laneId;
186             Unlock();
187             return;
188         }
189     }
190     Unlock();
191 }
192 
CtrlNotifyLaneAllocSuccess(uint32_t laneHandle,uint64_t laneId,const LaneLinkInfo * info)193 static void CtrlNotifyLaneAllocSuccess(uint32_t laneHandle, uint64_t laneId, const LaneLinkInfo *info)
194 {
195     UpdateCtrlReqInfo(laneHandle, laneId);
196     CtrlReqInfo reqInfo;
197     (void)memset_s(&reqInfo, sizeof(CtrlReqInfo), 0, sizeof(CtrlReqInfo));
198     if (GetCtrlReqInfo(laneHandle, &reqInfo) != SOFTBUS_OK) {
199         LNN_LOGE(LNN_LANE, "get lane reqInfo fail");
200         return;
201     }
202 
203     LaneProfile profile;
204     LaneConnInfo connInfo;
205     (void)memset_s(&profile, sizeof(LaneProfile), 0, sizeof(LaneProfile));
206     if (LaneInfoProcess(info, &connInfo, &profile) != SOFTBUS_OK) {
207         LNN_LOGE(LNN_LANE, "lane alloc success, but laneInfo proc fail");
208         return;
209     }
210     LNN_LOGI(LNN_LANE, "ctrl notify laneAlloc succ, laneHandle=%{public}u, linkType=%{public}d, "
211         "laneId=%{public}" PRIu64 "", laneHandle, info->type, laneId);
212     connInfo.laneId = laneId;
213     reqInfo.listener.onLaneAllocSuccess(laneHandle, &connInfo);
214 }
215 
CtrlLinkSuccess(uint32_t laneHandle,LaneLinkType linkType,const LaneLinkInfo * linkInfo)216 static void CtrlLinkSuccess(uint32_t laneHandle, LaneLinkType linkType, const LaneLinkInfo *linkInfo)
217 {
218     if (linkInfo == NULL) {
219         LNN_LOGE(LNN_LANE, "linkSuccess param invalid");
220         return;
221     }
222     char localUdid[UDID_BUF_LEN] = {0};
223     if (LnnGetLocalStrInfo(STRING_KEY_DEV_UDID, localUdid, UDID_BUF_LEN) != SOFTBUS_OK) {
224         LNN_LOGE(LNN_LANE, "get udid fail, laneHandle=%{public}u", laneHandle);
225         CtrlLinkFail(laneHandle, SOFTBUS_LANE_GET_LEDGER_INFO_ERR, linkType);
226         return;
227     }
228     uint64_t laneId = GenerateLaneId(localUdid, linkInfo->peerUdid, linkInfo->type);
229     if (laneId == INVALID_LANE_ID) {
230         LNN_LOGE(LNN_LANE, "generate laneId fail, laneHandle=%{public}u", laneHandle);
231         CtrlLinkFail(laneHandle, SOFTBUS_LANE_ID_GENERATE_FAIL, linkType);
232         return;
233     }
234     int32_t ret = AddLaneResourceToPool(linkInfo, laneId, false);
235     if (ret != SOFTBUS_OK) {
236         LNN_LOGE(LNN_LANE, "add linkInfo item fail, laneHandle=%{public}u", laneHandle);
237         CtrlLinkFail(laneHandle, ret, linkType);
238         return;
239     }
240     CtrlNotifyLaneAllocSuccess(laneHandle, laneId, linkInfo);
241 }
242 
CreateLinkRequestNode(const LaneAllocInfo * allocInfo,LinkRequest * requestInfo)243 static int32_t CreateLinkRequestNode(const LaneAllocInfo *allocInfo, LinkRequest *requestInfo)
244 {
245     requestInfo->networkDelegate = allocInfo->extendInfo.networkDelegate;
246     requestInfo->pid = allocInfo->pid;
247     requestInfo->acceptableProtocols = allocInfo->acceptableProtocols;
248     requestInfo->transType = allocInfo->transType;
249     if (memcpy_s(requestInfo->peerNetworkId, NETWORK_ID_BUF_LEN,
250         allocInfo->networkId, NETWORK_ID_BUF_LEN) != EOK) {
251         LNN_LOGE(LNN_LANE, "memcpy networkId fail");
252         return SOFTBUS_MEM_ERR;
253     }
254     if (memcpy_s(requestInfo->peerBleMac, MAX_MAC_LEN, allocInfo->extendInfo.peerBleMac, MAX_MAC_LEN) != EOK) {
255         LNN_LOGE(LNN_LANE, "memcpy peerBleMac fail");
256         return SOFTBUS_MEM_ERR;
257     }
258     return SOFTBUS_OK;
259 }
260 
CreateCtrlReqNode(uint32_t laneHandle,const LaneAllocInfo * allocInfo,const LaneAllocListener * listener,LanePreferredLinkList * recommendLinkList)261 static int32_t CreateCtrlReqNode(uint32_t laneHandle, const LaneAllocInfo *allocInfo,
262     const LaneAllocListener *listener, LanePreferredLinkList *recommendLinkList)
263 {
264     CtrlReqInfo *newNode = (CtrlReqInfo *)SoftBusCalloc(sizeof(CtrlReqInfo));
265     if (newNode == NULL) {
266         LNN_LOGE(LNN_LANE, "malloc fail");
267         return SOFTBUS_MALLOC_ERR;
268     }
269     if (memcpy_s(&newNode->allocInfo, sizeof(LaneAllocInfo), allocInfo, sizeof(LaneAllocInfo)) != EOK ||
270         memcpy_s(&newNode->listener, sizeof(LaneAllocListener), listener, sizeof(LaneAllocListener)) != EOK ||
271         memcpy_s(&newNode->linkList, sizeof(LanePreferredLinkList), recommendLinkList,
272             sizeof(LanePreferredLinkList)) != EOK) {
273         LNN_LOGE(LNN_LANE, "memcpy fail for lane alloc listener");
274         SoftBusFree(newNode);
275         return SOFTBUS_MEM_ERR;
276     }
277     newNode->laneHandle = laneHandle;
278     newNode->linkListIdx = 0;
279     ListInit(&newNode->node);
280     if (Lock() != SOFTBUS_OK) {
281         LNN_LOGE(LNN_LANE, "get lock fail");
282         SoftBusFree(newNode);
283         return SOFTBUS_LOCK_ERR;
284     }
285     ListTailInsert(&g_ctrlReqList->list, &newNode->node);
286     g_ctrlReqList->cnt++;
287     Unlock();
288     return SOFTBUS_OK;
289 }
290 
GetCtrlReqInfoWithoutLock(uint32_t laneHandle)291 static CtrlReqInfo *GetCtrlReqInfoWithoutLock(uint32_t laneHandle)
292 {
293     CtrlReqInfo *item = NULL;
294     LIST_FOR_EACH_ENTRY(item, &g_ctrlReqList->list, CtrlReqInfo, node) {
295         if (item->laneHandle == laneHandle) {
296             return item;
297         }
298     }
299     return NULL;
300 }
301 
CtrlTriggerLink(uint32_t laneHandle)302 static int32_t CtrlTriggerLink(uint32_t laneHandle)
303 {
304     if (Lock() != SOFTBUS_OK) {
305         LNN_LOGE(LNN_LANE, "get lock fail");
306         return SOFTBUS_LOCK_ERR;
307     }
308     CtrlReqInfo *reqInfo = GetCtrlReqInfoWithoutLock(laneHandle);
309     if (reqInfo == NULL) {
310         LNN_LOGE(LNN_LANE, "get lane reqInfo fail");
311         Unlock();
312         return SOFTBUS_LANE_NOT_FOUND;
313     }
314     LaneLinkCb linkCb = {
315         .onLaneLinkSuccess = CtrlLinkSuccess,
316         .onLaneLinkFail = CtrlLinkFail,
317     };
318     LinkRequest requestInfo = {0};
319     int32_t ret = SOFTBUS_LANE_TRIGGER_LINK_FAIL;
320     do {
321         ret = CreateLinkRequestNode(&reqInfo->allocInfo, &requestInfo);
322         if (ret != SOFTBUS_OK) {
323             Unlock();
324             LNN_LOGE(LNN_LANE, "Create LinkRequestNode fail.");
325             break;
326         }
327         requestInfo.linkType = reqInfo->linkList.linkType[reqInfo->linkListIdx];
328         reqInfo->linkListIdx++;
329         Unlock();
330         ret = BuildLink(&requestInfo, laneHandle, &linkCb);
331         if (ret == SOFTBUS_OK) {
332             return SOFTBUS_OK;
333         }
334     } while (false);
335     linkCb.onLaneLinkFail(laneHandle, ret, requestInfo.linkType);
336     return ret;
337 }
338 
AllocCtrlLane(uint32_t laneHandle,const LaneAllocInfo * allocInfo,const LaneAllocListener * listener)339 static int32_t AllocCtrlLane(uint32_t laneHandle, const LaneAllocInfo *allocInfo, const LaneAllocListener *listener)
340 {
341     AuthLinkTypeList authList;
342     if (memset_s(&authList, sizeof(AuthLinkTypeList), 0, sizeof(AuthLinkTypeList)) != EOK) {
343         return SOFTBUS_MEM_ERR;
344     }
345     int32_t ret = GetAuthLinkTypeList(allocInfo->networkId, &authList);
346     if (ret != SOFTBUS_OK) {
347         LNN_LOGE(LNN_LANE, "get authList fail");
348         return ret;
349     }
350     LanePreferredLinkList request;
351     if (memset_s(&request, sizeof(LanePreferredLinkList), 0, sizeof(LanePreferredLinkList)) != EOK) {
352         LNN_LOGE(LNN_LANE, "memset_s request fail");
353         return SOFTBUS_MEM_ERR;
354     }
355     ret = ConvertAuthLinkToLaneLink(&authList, &request);
356     if (ret != SOFTBUS_OK) {
357         LNN_LOGE(LNN_LANE, "convert authLink to laneLink fail");
358         return ret;
359     }
360     LanePreferredLinkList *recommendLinkList = (LanePreferredLinkList *)SoftBusCalloc(sizeof(LanePreferredLinkList));
361     if (recommendLinkList == NULL) {
362         LNN_LOGE(LNN_LANE, "calloc recommendLinkList fail");
363         return SOFTBUS_MALLOC_ERR;
364     }
365     recommendLinkList->linkTypeNum = 0;
366     ret = SelectAuthLane(allocInfo->networkId, &request, recommendLinkList);
367     if (ret != SOFTBUS_OK) {
368         SoftBusFree(recommendLinkList);
369         LNN_LOGE(LNN_LANE, "select auth lane fail, laneHandle=%{public}u", laneHandle);
370         return ret;
371     }
372     for (uint32_t i = 0; i < recommendLinkList->linkTypeNum; ++i) {
373         LNN_LOGI(LNN_LANE, "auth expect recommendLinkList nums=%{public}u, priority=%{public}u, link=%{public}u",
374             recommendLinkList->linkTypeNum, i, recommendLinkList->linkType[i]);
375     }
376     if (CreateCtrlReqNode(laneHandle, allocInfo, listener, recommendLinkList) != SOFTBUS_OK) {
377         SoftBusFree(recommendLinkList);
378         LNN_LOGE(LNN_LANE, "create ctrlReqInfo node fail.");
379         return SOFTBUS_LANE_LIST_ERR;
380     }
381     ret = CtrlTriggerLink(laneHandle);
382     if (ret != SOFTBUS_OK) {
383         SoftBusFree(recommendLinkList);
384         DeleteCtrlRequestNode(laneHandle);
385         LNN_LOGE(LNN_LANE, "trigger link fail, laneHandle=%{public}u", laneHandle);
386         return ret;
387     }
388     return SOFTBUS_OK;
389 }
390 
CtrlAlloc(uint32_t laneHandle,const LaneAllocInfo * allocInfo,const LaneAllocListener * listener)391 static int32_t CtrlAlloc(uint32_t laneHandle, const LaneAllocInfo *allocInfo, const LaneAllocListener *listener)
392 {
393     if (laneHandle == INVALID_LANE_REQ_ID || allocInfo == NULL || allocInfo->type != LANE_TYPE_CTRL) {
394         LNN_LOGE(LNN_LANE, "param invalid");
395         return SOFTBUS_INVALID_PARAM;
396     }
397     int32_t ret = AllocCtrlLane(laneHandle, allocInfo, listener);
398     if (ret != SOFTBUS_OK) {
399         LNN_LOGE(LNN_LANE, "alloc valid lane fail, laneHandle=%{public}u", laneHandle);
400         FreeLaneReqId(laneHandle);
401         return ret;
402     }
403     return SOFTBUS_OK;
404 }
405 
CtrlInit(const ILaneIdStateListener * listener)406 static void CtrlInit(const ILaneIdStateListener *listener)
407 {
408     if (g_ctrlReqList != NULL) {
409         LNN_LOGW(LNN_LANE, "already init");
410         return;
411     }
412     if (SoftBusMutexInit(&g_ctrlLaneMutex, NULL) != SOFTBUS_OK) {
413         LNN_LOGE(LNN_LANE, "ctrlLane mutex init fail");
414         return;
415     }
416     g_ctrlReqList = (CtrlLaneList *)SoftBusCalloc(sizeof(CtrlLaneList));
417     if (g_ctrlReqList == NULL) {
418         LNN_LOGE(LNN_LANE, "ctrlLane malloc fail");
419         (void)SoftBusMutexDestroy(&g_ctrlLaneMutex);
420         return;
421     }
422     ListInit(&g_ctrlReqList->list);
423 }
424 
CtrlDeinit(void)425 static void CtrlDeinit(void)
426 {
427     if (g_ctrlReqList == NULL) {
428         return;
429     }
430     if (Lock() != SOFTBUS_OK) {
431         LNN_LOGE(LNN_LANE, "get lock fail");
432         return;
433     }
434     CtrlReqInfo *item = NULL;
435     CtrlReqInfo *nextItem = NULL;
436     LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &g_ctrlReqList->list, CtrlReqInfo, node) {
437         ListDelete(&item->node);
438         SoftBusFree(item);
439         g_ctrlReqList->cnt--;
440     }
441     Unlock();
442     (void)SoftBusMutexDestroy(&g_ctrlLaneMutex);
443     SoftBusFree(g_ctrlReqList);
444     g_ctrlReqList = NULL;
445 }
446 
FreeLaneLink(uint32_t laneHandle,uint64_t laneId)447 static int32_t FreeLaneLink(uint32_t laneHandle, uint64_t laneId)
448 {
449     LaneResource resourceItem;
450     (void)memset_s(&resourceItem, sizeof(LaneResource), 0, sizeof(LaneResource));
451     if (FindLaneResourceByLaneId(laneId, &resourceItem) != SOFTBUS_OK) {
452         return SOFTBUS_LANE_RESOURCE_NOT_FOUND;
453     }
454     char networkId[NETWORK_ID_BUF_LEN] = { 0 };
455     if (LnnGetNetworkIdByUdid(resourceItem.link.peerUdid, networkId, sizeof(networkId)) != SOFTBUS_OK) {
456         return SOFTBUS_LANE_GET_LEDGER_INFO_ERR;
457     }
458     DestroyLink(networkId, laneHandle, resourceItem.link.type);
459     DelLaneResourceByLaneId(laneId, false);
460     return SOFTBUS_OK;
461 }
462 
CtrlFree(uint32_t laneHandle)463 static int32_t CtrlFree(uint32_t laneHandle)
464 {
465     if (Lock() != SOFTBUS_OK) {
466         LNN_LOGE(LNN_LANE, "get lock fail");
467         return SOFTBUS_LOCK_ERR;
468     }
469     CtrlReqInfo *item = NULL;
470     CtrlReqInfo *next = NULL;
471     LIST_FOR_EACH_ENTRY_SAFE(item, next, &g_ctrlReqList->list, CtrlReqInfo, node) {
472         if (item->laneHandle == laneHandle) {
473             ListDelete(&item->node);
474             g_ctrlReqList->cnt--;
475             Unlock();
476             FreeLaneLink(laneHandle, item->laneId);
477             SoftBusFree(item);
478             FreeLaneReqId(laneHandle);
479             return SOFTBUS_OK;
480         }
481     }
482     Unlock();
483     LNN_LOGI(LNN_LANE, "no find lane need free, laneHandle=%{public}u", laneHandle);
484     FreeLaneReqId(laneHandle);
485     return SOFTBUS_OK;
486 }
487 
488 static LaneInterface g_ctrlLaneObject = {
489     .init = CtrlInit,
490     .allocLaneByQos = CtrlAlloc,
491     .freeLane = CtrlFree,
492     .deinit = CtrlDeinit,
493 };
494 
CtrlLaneGetInstance(void)495 LaneInterface *CtrlLaneGetInstance(void)
496 {
497     return &g_ctrlLaneObject;
498 }