345 lines
9.5 KiB
C
345 lines
9.5 KiB
C
/*
|
|
* Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
* conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
|
* provided with the distribution.
|
|
*
|
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
|
* to endorse or promote products derived from this software without specific prior written
|
|
* permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifdef LOSCFG_NET_CONTAINER
|
|
#include <sched.h>
|
|
#include "los_net_container_pri.h"
|
|
#include "los_config.h"
|
|
#include "los_memory.h"
|
|
#include "los_process_pri.h"
|
|
|
|
STATIC UINT32 g_currentNetContainerNum = 0;
|
|
STATIC NetContainer *g_rootNetContainer = NULL;
|
|
|
|
STATIC struct netif *NetifAlloc(VOID)
|
|
{
|
|
UINT32 size = sizeof(struct netif);
|
|
struct netif *netif = LOS_MemAlloc(m_aucSysMem1, size);
|
|
if (netif == NULL) {
|
|
return NULL;
|
|
}
|
|
(VOID)memset_s(netif, size, 0, size);
|
|
|
|
return netif;
|
|
}
|
|
|
|
STATIC VOID FreeNetif(struct netif *netif)
|
|
{
|
|
if (netif != NULL) {
|
|
if (netif->peer != NULL) {
|
|
netif_remove(netif->peer);
|
|
(VOID)LOS_MemFree(m_aucSysMem1, netif->peer);
|
|
}
|
|
netif_remove(netif);
|
|
(VOID)LOS_MemFree(m_aucSysMem1, netif);
|
|
}
|
|
}
|
|
|
|
STATIC UINT32 CreateVethNetif(NetContainer *netContainer, struct netif **veth)
|
|
{
|
|
struct netif *netif = NetifAlloc();
|
|
if (netif == NULL) {
|
|
return ENOMEM;
|
|
}
|
|
|
|
veth_init(netif, netContainer->group);
|
|
|
|
*veth = netif;
|
|
return LOS_OK;
|
|
}
|
|
|
|
STATIC UINT32 InitVethPair(NetContainer *netContainer)
|
|
{
|
|
struct netif *vethOfNetContainer = NULL;
|
|
struct netif *vethOfRootNetContainer = NULL;
|
|
|
|
UINT32 ret = CreateVethNetif(netContainer, &vethOfNetContainer);
|
|
if (ret != LOS_OK) {
|
|
return ret;
|
|
}
|
|
|
|
ret = CreateVethNetif(g_rootNetContainer, &vethOfRootNetContainer);
|
|
if (ret != LOS_OK) {
|
|
FreeNetif(vethOfNetContainer);
|
|
return ret;
|
|
}
|
|
|
|
vethOfNetContainer->peer = vethOfRootNetContainer;
|
|
vethOfRootNetContainer->peer = vethOfNetContainer;
|
|
return LOS_OK;
|
|
}
|
|
|
|
STATIC UINT32 InitLoopNetif(NetContainer *netContainer)
|
|
{
|
|
struct netif *loop_netif = NetifAlloc();
|
|
if (loop_netif == NULL) {
|
|
return ENOMEM;
|
|
}
|
|
|
|
netContainer->group->loop_netif = loop_netif;
|
|
netif_init(netContainer->group);
|
|
return LOS_OK;
|
|
}
|
|
|
|
STATIC UINT32 InitContainerNetifs(NetContainer *netContainer)
|
|
{
|
|
UINT32 ret = InitLoopNetif(netContainer);
|
|
if (ret != LOS_OK) {
|
|
return ret;
|
|
}
|
|
return InitVethPair(netContainer);
|
|
}
|
|
|
|
STATIC UINT32 InitNetGroup(NetContainer *netContainer)
|
|
{
|
|
UINT32 size = sizeof(struct net_group);
|
|
struct net_group *group = LOS_MemAlloc(m_aucSysMem1, size);
|
|
if (group == NULL) {
|
|
return ENOMEM;
|
|
}
|
|
(VOID)memset_s(group, size, 0, size);
|
|
|
|
netContainer->group = group;
|
|
return LOS_OK;
|
|
}
|
|
|
|
STATIC VOID FreeNetContainerGroup(struct net_group *group)
|
|
{
|
|
if (group == NULL) {
|
|
return;
|
|
}
|
|
|
|
struct netif *freeNetif = group->netif_list;
|
|
struct netif *nextNetif = NULL;
|
|
|
|
while (freeNetif != NULL) {
|
|
nextNetif = freeNetif->next;
|
|
FreeNetif(freeNetif);
|
|
freeNetif = nextNetif;
|
|
}
|
|
}
|
|
|
|
VOID OsNetContainerDestroy(Container *container)
|
|
{
|
|
UINT32 intSave;
|
|
if (container == NULL) {
|
|
return;
|
|
}
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
NetContainer *netContainer = container->netContainer;
|
|
if (netContainer == NULL) {
|
|
SCHEDULER_UNLOCK(intSave);
|
|
return;
|
|
}
|
|
|
|
LOS_AtomicDec(&netContainer->rc);
|
|
if (LOS_AtomicRead(&netContainer->rc) > 0) {
|
|
SCHEDULER_UNLOCK(intSave);
|
|
return;
|
|
}
|
|
|
|
g_currentNetContainerNum--;
|
|
SCHEDULER_UNLOCK(intSave);
|
|
FreeNetContainerGroup(netContainer->group);
|
|
container->netContainer = NULL;
|
|
(VOID)LOS_MemFree(m_aucSysMem1, netContainer->group);
|
|
(VOID)LOS_MemFree(m_aucSysMem1, netContainer);
|
|
return;
|
|
}
|
|
|
|
STATIC NetContainer *CreateNewNetContainer(NetContainer *parent)
|
|
{
|
|
NetContainer *netContainer = LOS_MemAlloc(m_aucSysMem1, sizeof(NetContainer));
|
|
if (netContainer == NULL) {
|
|
return NULL;
|
|
}
|
|
(VOID)memset_s(netContainer, sizeof(NetContainer), 0, sizeof(NetContainer));
|
|
|
|
netContainer->containerID = OsAllocContainerID();
|
|
|
|
if (parent != NULL) {
|
|
LOS_AtomicSet(&netContainer->rc, 1);
|
|
} else {
|
|
LOS_AtomicSet(&netContainer->rc, 3); /* 3: Three system processes */
|
|
}
|
|
return netContainer;
|
|
}
|
|
|
|
STATIC UINT32 CreateNetContainer(Container *container, NetContainer *parentContainer)
|
|
{
|
|
UINT32 intSave, ret;
|
|
NetContainer *newNetContainer = CreateNewNetContainer(parentContainer);
|
|
if (newNetContainer == NULL) {
|
|
return ENOMEM;
|
|
}
|
|
|
|
ret = InitNetGroup(newNetContainer);
|
|
if (ret != LOS_OK) {
|
|
(VOID)LOS_MemFree(m_aucSysMem1, newNetContainer);
|
|
return ret;
|
|
}
|
|
|
|
ret = InitContainerNetifs(newNetContainer);
|
|
if (ret != LOS_OK) {
|
|
(VOID)LOS_MemFree(m_aucSysMem1, newNetContainer->group);
|
|
(VOID)LOS_MemFree(m_aucSysMem1, newNetContainer);
|
|
return ret;
|
|
}
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
g_currentNetContainerNum++;
|
|
container->netContainer = newNetContainer;
|
|
SCHEDULER_UNLOCK(intSave);
|
|
return LOS_OK;
|
|
}
|
|
|
|
UINT32 OsCopyNetContainer(UINTPTR flags, LosProcessCB *child, LosProcessCB *parent)
|
|
{
|
|
UINT32 intSave;
|
|
NetContainer *currNetContainer = parent->container->netContainer;
|
|
|
|
if (!(flags & CLONE_NEWNET)) {
|
|
SCHEDULER_LOCK(intSave);
|
|
LOS_AtomicInc(&currNetContainer->rc);
|
|
child->container->netContainer = currNetContainer;
|
|
SCHEDULER_UNLOCK(intSave);
|
|
return LOS_OK;
|
|
}
|
|
|
|
if (OsContainerLimitCheck(NET_CONTAINER, &g_currentNetContainerNum) != LOS_OK) {
|
|
return EPERM;
|
|
}
|
|
|
|
return CreateNetContainer(child->container, currNetContainer);
|
|
}
|
|
|
|
UINT32 OsUnshareNetContainer(UINTPTR flags, LosProcessCB *curr, Container *newContainer)
|
|
{
|
|
UINT32 intSave;
|
|
NetContainer *parentContainer = curr->container->netContainer;
|
|
|
|
if (!(flags & CLONE_NEWNET)) {
|
|
SCHEDULER_LOCK(intSave);
|
|
newContainer->netContainer = parentContainer;
|
|
LOS_AtomicInc(&parentContainer->rc);
|
|
SCHEDULER_UNLOCK(intSave);
|
|
return LOS_OK;
|
|
}
|
|
|
|
if (OsContainerLimitCheck(NET_CONTAINER, &g_currentNetContainerNum) != LOS_OK) {
|
|
return EPERM;
|
|
}
|
|
|
|
return CreateNetContainer(newContainer, parentContainer);
|
|
}
|
|
|
|
UINT32 OsSetNsNetContainer(UINT32 flags, Container *container, Container *newContainer)
|
|
{
|
|
if (flags & CLONE_NEWNET) {
|
|
newContainer->netContainer = container->netContainer;
|
|
LOS_AtomicInc(&container->netContainer->rc);
|
|
return LOS_OK;
|
|
}
|
|
|
|
newContainer->netContainer = OsCurrProcessGet()->container->netContainer;
|
|
LOS_AtomicInc(&newContainer->netContainer->rc);
|
|
return LOS_OK;
|
|
}
|
|
|
|
UINT32 OsGetNetContainerID(NetContainer *netContainer)
|
|
{
|
|
if (netContainer == NULL) {
|
|
return OS_INVALID_VALUE;
|
|
}
|
|
|
|
return netContainer->containerID;
|
|
}
|
|
|
|
STATIC struct net_group *DoGetNetGroupFromCurrProcess(VOID)
|
|
{
|
|
LosProcessCB *processCB = OsCurrProcessGet();
|
|
NetContainer *netContainer = processCB->container->netContainer;
|
|
return netContainer->group;
|
|
}
|
|
|
|
STATIC VOID DoSetNetifNetGroup(struct netif *netif, struct net_group *group)
|
|
{
|
|
netif->group = group;
|
|
}
|
|
|
|
STATIC struct net_group *DoGetNetGroupFromNetif(struct netif *netif)
|
|
{
|
|
return netif != NULL ? netif->group : NULL;
|
|
}
|
|
|
|
STATIC VOID DoSetIppcbNetGroup(struct ip_pcb *pcb, struct net_group *group)
|
|
{
|
|
pcb->group = group;
|
|
}
|
|
|
|
STATIC struct net_group *DoGetNetGroupFromIppcb(struct ip_pcb *pcb)
|
|
{
|
|
return pcb != NULL ? pcb->group : NULL;
|
|
}
|
|
|
|
struct net_group_ops netGroupOps = {
|
|
.get_curr_process_net_group = DoGetNetGroupFromCurrProcess,
|
|
.set_netif_net_group = DoSetNetifNetGroup,
|
|
.get_net_group_from_netif = DoGetNetGroupFromNetif,
|
|
.set_ippcb_net_group = DoSetIppcbNetGroup,
|
|
.get_net_group_from_ippcb = DoGetNetGroupFromIppcb,
|
|
};
|
|
|
|
UINT32 OsInitRootNetContainer(NetContainer **netContainer)
|
|
{
|
|
UINT32 intSave;
|
|
NetContainer *newNetContainer = CreateNewNetContainer(NULL);
|
|
if (newNetContainer == NULL) {
|
|
return ENOMEM;
|
|
}
|
|
|
|
newNetContainer->group = get_root_net_group();
|
|
set_default_net_group_ops(&netGroupOps);
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
g_currentNetContainerNum++;
|
|
*netContainer = newNetContainer;
|
|
g_rootNetContainer = newNetContainer;
|
|
SCHEDULER_UNLOCK(intSave);
|
|
return LOS_OK;
|
|
}
|
|
|
|
UINT32 OsGetNetContainerCount(VOID)
|
|
{
|
|
return g_currentNetContainerNum;
|
|
}
|
|
#endif
|