• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification,
5  * are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this list of
8  *    conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11  *    of conditions and the following disclaimer in the documentation and/or other materials
12  *    provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15  *    to endorse or promote products derived from this software without specific prior written
16  *    permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #ifdef LOSCFG_NET_CONTAINER
32 #include <sched.h>
33 #include "los_net_container_pri.h"
34 #include "los_config.h"
35 #include "los_memory.h"
36 #include "los_process_pri.h"
37 
38 STATIC UINT32 g_currentNetContainerNum = 0;
39 STATIC NetContainer *g_rootNetContainer = NULL;
40 
NetifAlloc(VOID)41 STATIC struct netif *NetifAlloc(VOID)
42 {
43     UINT32 size = sizeof(struct netif);
44     struct netif *netif = LOS_MemAlloc(m_aucSysMem1, size);
45     if (netif == NULL) {
46         return NULL;
47     }
48     (VOID)memset_s(netif, size, 0, size);
49 
50     return netif;
51 }
52 
FreeNetif(struct netif * netif)53 STATIC VOID FreeNetif(struct netif *netif)
54 {
55     if (netif != NULL) {
56         if (netif->peer != NULL) {
57             netif_remove(netif->peer);
58             (VOID)LOS_MemFree(m_aucSysMem1, netif->peer);
59         }
60         netif_remove(netif);
61         (VOID)LOS_MemFree(m_aucSysMem1, netif);
62     }
63 }
64 
CreateVethNetif(NetContainer * netContainer,struct netif ** veth)65 STATIC UINT32 CreateVethNetif(NetContainer *netContainer, struct netif **veth)
66 {
67     struct netif *netif = NetifAlloc();
68     if (netif == NULL) {
69         return ENOMEM;
70     }
71 
72     veth_init(netif, netContainer->group);
73 
74     *veth = netif;
75     return LOS_OK;
76 }
77 
InitVethPair(NetContainer * netContainer)78 STATIC UINT32 InitVethPair(NetContainer *netContainer)
79 {
80     struct netif *vethOfNetContainer = NULL;
81     struct netif *vethOfRootNetContainer = NULL;
82 
83     UINT32 ret = CreateVethNetif(netContainer, &vethOfNetContainer);
84     if (ret != LOS_OK) {
85         return ret;
86     }
87 
88     ret = CreateVethNetif(g_rootNetContainer, &vethOfRootNetContainer);
89     if (ret != LOS_OK) {
90         FreeNetif(vethOfNetContainer);
91         return ret;
92     }
93 
94     vethOfNetContainer->peer = vethOfRootNetContainer;
95     vethOfRootNetContainer->peer = vethOfNetContainer;
96     return LOS_OK;
97 }
98 
InitLoopNetif(NetContainer * netContainer)99 STATIC UINT32 InitLoopNetif(NetContainer *netContainer)
100 {
101     struct netif *loop_netif = NetifAlloc();
102     if (loop_netif == NULL) {
103         return ENOMEM;
104     }
105 
106     netContainer->group->loop_netif = loop_netif;
107     netif_init(netContainer->group);
108     return LOS_OK;
109 }
110 
InitContainerNetifs(NetContainer * netContainer)111 STATIC UINT32 InitContainerNetifs(NetContainer *netContainer)
112 {
113     UINT32 ret = InitLoopNetif(netContainer);
114     if (ret != LOS_OK) {
115         return ret;
116     }
117     return InitVethPair(netContainer);
118 }
119 
InitNetGroup(NetContainer * netContainer)120 STATIC UINT32 InitNetGroup(NetContainer *netContainer)
121 {
122     UINT32 size = sizeof(struct net_group);
123     struct net_group *group = LOS_MemAlloc(m_aucSysMem1, size);
124     if (group == NULL) {
125         return ENOMEM;
126     }
127     (VOID)memset_s(group, size, 0, size);
128 
129     netContainer->group = group;
130     return LOS_OK;
131 }
132 
FreeNetContainerGroup(struct net_group * group)133 STATIC VOID FreeNetContainerGroup(struct net_group *group)
134 {
135     if (group == NULL) {
136         return;
137     }
138 
139     struct netif *freeNetif = group->netif_list;
140     struct netif *nextNetif = NULL;
141 
142     while (freeNetif != NULL) {
143         nextNetif = freeNetif->next;
144         FreeNetif(freeNetif);
145         freeNetif = nextNetif;
146     }
147 }
148 
OsNetContainerDestroy(Container * container)149 VOID OsNetContainerDestroy(Container *container)
150 {
151     UINT32 intSave;
152     if (container == NULL) {
153         return;
154     }
155 
156     SCHEDULER_LOCK(intSave);
157     NetContainer *netContainer = container->netContainer;
158     if (netContainer == NULL) {
159         SCHEDULER_UNLOCK(intSave);
160         return;
161     }
162 
163     LOS_AtomicDec(&netContainer->rc);
164     if (LOS_AtomicRead(&netContainer->rc) > 0) {
165         SCHEDULER_UNLOCK(intSave);
166         return;
167     }
168 
169     g_currentNetContainerNum--;
170     SCHEDULER_UNLOCK(intSave);
171     FreeNetContainerGroup(netContainer->group);
172     container->netContainer = NULL;
173     (VOID)LOS_MemFree(m_aucSysMem1, netContainer->group);
174     (VOID)LOS_MemFree(m_aucSysMem1, netContainer);
175     return;
176 }
177 
CreateNewNetContainer(NetContainer * parent)178 STATIC NetContainer *CreateNewNetContainer(NetContainer *parent)
179 {
180     NetContainer *netContainer = LOS_MemAlloc(m_aucSysMem1, sizeof(NetContainer));
181     if (netContainer == NULL) {
182         return NULL;
183     }
184     (VOID)memset_s(netContainer, sizeof(NetContainer), 0, sizeof(NetContainer));
185 
186     netContainer->containerID = OsAllocContainerID();
187 
188     if (parent != NULL) {
189         LOS_AtomicSet(&netContainer->rc, 1);
190     } else {
191         LOS_AtomicSet(&netContainer->rc, 3); /* 3: Three system processes */
192     }
193     return netContainer;
194 }
195 
CreateNetContainer(Container * container,NetContainer * parentContainer)196 STATIC UINT32 CreateNetContainer(Container *container, NetContainer *parentContainer)
197 {
198     UINT32 intSave, ret;
199     NetContainer *newNetContainer = CreateNewNetContainer(parentContainer);
200     if (newNetContainer == NULL) {
201         return ENOMEM;
202     }
203 
204     ret = InitNetGroup(newNetContainer);
205     if (ret != LOS_OK) {
206         (VOID)LOS_MemFree(m_aucSysMem1, newNetContainer);
207         return ret;
208     }
209 
210     ret = InitContainerNetifs(newNetContainer);
211     if (ret != LOS_OK) {
212         (VOID)LOS_MemFree(m_aucSysMem1, newNetContainer->group);
213         (VOID)LOS_MemFree(m_aucSysMem1, newNetContainer);
214         return ret;
215     }
216 
217     SCHEDULER_LOCK(intSave);
218     g_currentNetContainerNum++;
219     container->netContainer = newNetContainer;
220     SCHEDULER_UNLOCK(intSave);
221     return LOS_OK;
222 }
223 
OsCopyNetContainer(UINTPTR flags,LosProcessCB * child,LosProcessCB * parent)224 UINT32 OsCopyNetContainer(UINTPTR flags, LosProcessCB *child, LosProcessCB *parent)
225 {
226     UINT32 intSave;
227     NetContainer *currNetContainer = parent->container->netContainer;
228 
229     if (!(flags & CLONE_NEWNET)) {
230         SCHEDULER_LOCK(intSave);
231         LOS_AtomicInc(&currNetContainer->rc);
232         child->container->netContainer = currNetContainer;
233         SCHEDULER_UNLOCK(intSave);
234         return LOS_OK;
235     }
236 
237     if (OsContainerLimitCheck(NET_CONTAINER, &g_currentNetContainerNum) != LOS_OK) {
238         return EPERM;
239     }
240 
241     return CreateNetContainer(child->container, currNetContainer);
242 }
243 
OsUnshareNetContainer(UINTPTR flags,LosProcessCB * curr,Container * newContainer)244 UINT32 OsUnshareNetContainer(UINTPTR flags, LosProcessCB *curr, Container *newContainer)
245 {
246     UINT32 intSave;
247     NetContainer *parentContainer = curr->container->netContainer;
248 
249     if (!(flags & CLONE_NEWNET)) {
250         SCHEDULER_LOCK(intSave);
251         newContainer->netContainer = parentContainer;
252         LOS_AtomicInc(&parentContainer->rc);
253         SCHEDULER_UNLOCK(intSave);
254         return LOS_OK;
255     }
256 
257     if (OsContainerLimitCheck(NET_CONTAINER, &g_currentNetContainerNum) != LOS_OK) {
258         return EPERM;
259     }
260 
261     return CreateNetContainer(newContainer, parentContainer);
262 }
263 
OsSetNsNetContainer(UINT32 flags,Container * container,Container * newContainer)264 UINT32 OsSetNsNetContainer(UINT32 flags, Container *container, Container *newContainer)
265 {
266     if (flags & CLONE_NEWNET) {
267         newContainer->netContainer = container->netContainer;
268         LOS_AtomicInc(&container->netContainer->rc);
269         return LOS_OK;
270     }
271 
272     newContainer->netContainer = OsCurrProcessGet()->container->netContainer;
273     LOS_AtomicInc(&newContainer->netContainer->rc);
274     return LOS_OK;
275 }
276 
OsGetNetContainerID(NetContainer * netContainer)277 UINT32 OsGetNetContainerID(NetContainer *netContainer)
278 {
279     if (netContainer == NULL) {
280         return OS_INVALID_VALUE;
281     }
282 
283     return netContainer->containerID;
284 }
285 
DoGetNetGroupFromCurrProcess(VOID)286 STATIC struct net_group *DoGetNetGroupFromCurrProcess(VOID)
287 {
288     LosProcessCB *processCB = OsCurrProcessGet();
289     NetContainer *netContainer = processCB->container->netContainer;
290     return netContainer->group;
291 }
292 
DoSetNetifNetGroup(struct netif * netif,struct net_group * group)293 STATIC VOID DoSetNetifNetGroup(struct netif *netif, struct net_group *group)
294 {
295     netif->group = group;
296 }
297 
DoGetNetGroupFromNetif(struct netif * netif)298 STATIC struct net_group *DoGetNetGroupFromNetif(struct netif *netif)
299 {
300     return netif != NULL ? netif->group : NULL;
301 }
302 
DoSetIppcbNetGroup(struct ip_pcb * pcb,struct net_group * group)303 STATIC VOID DoSetIppcbNetGroup(struct ip_pcb *pcb, struct net_group *group)
304 {
305     pcb->group = group;
306 }
307 
DoGetNetGroupFromIppcb(struct ip_pcb * pcb)308 STATIC struct net_group *DoGetNetGroupFromIppcb(struct ip_pcb *pcb)
309 {
310     return pcb != NULL ? pcb->group : NULL;
311 }
312 
313 struct net_group_ops netGroupOps = {
314     .get_curr_process_net_group = DoGetNetGroupFromCurrProcess,
315     .set_netif_net_group = DoSetNetifNetGroup,
316     .get_net_group_from_netif = DoGetNetGroupFromNetif,
317     .set_ippcb_net_group = DoSetIppcbNetGroup,
318     .get_net_group_from_ippcb = DoGetNetGroupFromIppcb,
319 };
320 
OsInitRootNetContainer(NetContainer ** netContainer)321 UINT32 OsInitRootNetContainer(NetContainer **netContainer)
322 {
323     UINT32 intSave;
324     NetContainer *newNetContainer = CreateNewNetContainer(NULL);
325     if (newNetContainer == NULL) {
326         return ENOMEM;
327     }
328 
329     newNetContainer->group = get_root_net_group();
330     set_default_net_group_ops(&netGroupOps);
331 
332     SCHEDULER_LOCK(intSave);
333     g_currentNetContainerNum++;
334     *netContainer = newNetContainer;
335     g_rootNetContainer = newNetContainer;
336     SCHEDULER_UNLOCK(intSave);
337     return LOS_OK;
338 }
339 
OsGetNetContainerCount(VOID)340 UINT32 OsGetNetContainerCount(VOID)
341 {
342     return g_currentNetContainerNum;
343 }
344 #endif
345