一、network namespace的创建

  在对iproute2的源码进行分析后,我们可以知道,当我们调用命令`ip netns add ns1`时,本质上就是调用`unshare(CLONE_NEWNET)`创建了一个新的network namespace。接着,我们进一步对内核中对于unshare系统调用的实现进行分析,从而了解内核是如何创建一个network namespace的。

1、内核对unshare()的实现分为两步,第一步调用unshare_nsproxy_namespaces创建一个新的nsproxy,nsproxy的数据结构如下

struct nsproxy {
atomic_t count;
struct uts_namespace *uts_ns;
struct ipc_namespace *ipc_ns;
struct mnt_namespace *mnt_ns;
struct pid_namespace *pid_ns;
struct net *net_ns;
};

一个nsproxy实例中包含了指向五种namespace结构的指针,一个process包含一个nsproxy,代表了这个process所在的各个namespace。当process调用unshare()函数时,内核就会其分配一个新的nsproxy结构,并且根据参数,新建部分namespace,并复制保留其余的namespace。例如,对于`unshare(CLONE_NEWNET)`语句,内核就会为当前进程新建一个network namespace,其余namespace保持不变。

int unshare_nsproxy_namespaces(unsigned long unshare_flags, struct nsproxy **new_nsp, struct cred *new_cred, struct fs_struct *new_fs)

  1、若unshare_flags参数中没有包含任何CLONE_NEW*参数,说明不用新建任何namespace,直接退出

  2、检验所在的user namespace是否有CAP_SYS_ADMIN权限,没有则报错退出

  3、调用*new_nsp = create_new_namespaces(unshare_flags, current, user_ns, new_fs ? new_fs : current->fs)创建新的namespace

static struct nsproxy *create_new_namespaces(unsigned long flags, struct task_struct *tsk, struct user_namespace *user_ns, struct fs_struct *new_fs)

  1、调用new_nsp = create_nsproxy()创建一个新的nsproxy结构

  2、再调用一系列例如new_nsp->mnt_ns = copy_mnt_ns(...)的命令,初始化新的nsproxy中的各个namespace指针。如果flags指示需要新建某个namespace,则copy_*函数就会新建一个对应的namespace,否则,就沿用之前的namespace。

  3、最后调用new_nsp->net_ns = copy_net_ns(flags, user_ns, tsk->nsproxy->net_ns),同理,根据flags中的对应位,选择新建或者沿用之前的network namespace

struct net *copy_net_ns(unsigned long flags, struct user_namespace *user_ns, struct net *old_net)

  1、如果flags中不包含CLONE_NEWNET,则返回old_net,否则需要新建一个network namespace

  2、调用net = net_alloc()分配一个新的struct net 结构

  3、调用rv = setup_net(net, user_ns)对新分配的net结构进行初始化

  4、调用list_add_tail_rcu(&net->list, &net_namespace_list),将新建的network namespace,添加到全局的network namespace列表net_namespace_list中

  

static __net_init int setup_net(struct net *net, struct user_namespace *user_ns)

  1、对net中的某些字段进行初始化

  2、遍历pernet_list列表,对其中的每个struct pernet_operations结构,调用err = ops_init(ops, net),完成各个模块的初始化工作

我们知道,每当创建一个新的network namespace,里面总会默认存在一个loopback device,但这是怎么完成的呢?其实在DEV模块初始化的时候,会调用函数register_pernet_device(&loopback_net_ops),将loopback_net_ops挂载到pernet_list中,loopback_pernet_device结构如下所示:

struct pernet_operation __net_initdata loopback_net_ops = {

  .init = loop_net_init,

}

而在ops_init(ops, net)就会调用loop_net_init(),创建该network namespace自己的loopback设备,对于路由表等其他网络资源的初始化,同理可得。

2、在创建了nsproxy之后,再调用switch_task_namespace(current, new_nsproxy)更换当前process的nsproxy

二、network devcie在network namespace之间的移动

通过命令`ip link set eth0 netns ns1`就能将eth0移动到network namespace ns1中。需要注意的是,当设备被标记为NETIF_F_NETNS_LOCAL时,该设备不能在namespace间移动,物理设备只能存在于root namespace中。当namespace被删除时,非NETIF_F_NETNS_LOCAL设备会被移回root namespace,而NETIF_F_NETNS_LOCAL设备会被删除

int dev_change_net_namespace(struct net_device *dev, struct net *net, const char *pat)

  1、若dev->features中的NETIF_F_NETNS_LOCAL置位或者设备的状态不是NETREG_REGISTERED则退出

  2、进行一系列的检测,将设备关闭并且从原先的device chain中取下,并进行设备被移除的通知工作

  3、调用dev_net_set(dev, net)将设备放入新的network namespace中,其实就是将struct net_device中的nd_net字段设置为net

  4、调用__dev_get_by_index(net, dev->ifindex),如果在转移过程中,index有冲突,则另外分配一个

  5、最后进行新设备添加的通知工作

三、总结

在对内核中network namespace相关的源码进行分析之后,我们可以发现,其实network namespace特性的添加,对整体代码的修改并不是很大。事实上,它只是将一些原本全局的唯一的网络资源变量,例如设备列表,路由表等等,包裹到了struct net这样一个结构中。因此我们创建多个net结构,就相当于拥有了多个原本的网络空间。从本质上来说,我们可以把network namespace的出现,看做是一种网络空间模块化的从特殊到一般的推广,原本全局唯一的网络空间仅仅只是当前情况的一种特例。

Linux network namespace源码分析的更多相关文章

  1. linux调度器源码分析 - 运行(四)

    本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 引言 之前的文章已经将调度器的数据结构.初始化.加入进程都进行了分析,这篇文章将主要说明调度器是如何在程序稳定运 ...

  2. linux调度器源码分析 - 初始化(二)

    本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 引言 上期文章linux调度器源码分析 - 概述(一)已经把调度器相关的数据结构介绍了一遍,本篇着重通过代码说明 ...

  3. Linux进程调度与源码分析(二)——进程生命周期与task_struct进程结构体

    1.进程生命周期 Linux操作系统属于多任务操作系统,系统中的每个进程能够分时复用CPU时间片,通过有效的进程调度策略实现多任务并行执行.而进程在被CPU调度运行,等待CPU资源分配以及等待外部事件 ...

  4. Docker 基础技术之 Linux namespace 源码分析

    上篇我们从进程 clone 的角度,结合代码简单分析了 Linux 提供的 6 种 namespace,本篇从源码上进一步分析 Linux namespace,让你对 Docker namespace ...

  5. linux调度器源码分析 - 概述(一)

    本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 引言 调度器作为操作系统的核心部件,具有非常重要的意义,其随着linux内核的更新也不断进行着更新.本系列文章通 ...

  6. Linux进程调度与源码分析(一)——简介

    本系列文章主要是近期针对Linux进程调度源码进行阅读与分析后的经验总结,分析过程中可能结合部分Linux网络编程的相关知识以便于理解,加深对Linux进程调度的理解和知识分享. 本系列文章主要结合L ...

  7. Linux 内核网桥源码分析

    Linux网桥源码的实现 转自: Linux二层网络协议 Linux网桥源码的实现 1.调用 在src/net/core/dev.c的软中断函数static void net_rx_action(st ...

  8. Linux内核 fork 源码分析

    内核版本:linux-4.4.18 源码位置:这里 fork相关的代码最终执行的函数为_do_fork(),下面按照顺序分析下_do_fork(): 首先判断是否需要trace(跟踪)这个进程,这一步 ...

  9. linux启动内核源码分析

    内核的启动时从main.c这个文件里面的start_kernel函数开始的,这个文件在linux源码里面的init文件夹下面 下面我们来看看这个函数 这个函数很长,可以看个大概过去 asmlinkag ...

随机推荐

  1. ListView局部更新(非notifyDataSetChanged)

    package com.example.test; import java.util.ArrayList; import java.util.List; import android.app.Acti ...

  2. Linux网络流量监控与分析工具Ntopng

    Ntopng工具 Ntopng是一个功能强大的流量监控.端口监控.服务监控管理系统 能够实现高效地监控多台服务器网络 Ntopng功能介绍 Ntop提供了命令行界面和web界面两种工作方式,通过web ...

  3. listView里面添加gridview

    package com.example.cc.ecustapp.Adapter; import android.content.Context;import android.util.DisplayM ...

  4. 自定义Django的admin界面

    第6章介绍了Django的admin界面,现在是回过头来仔细看看这个的时候了 我们前面讲的几次admin是Django的"杀手级特性",并且大多数Django开发人员很快爱上了它节 ...

  5. DelphiXE8怎么使用调试模式(小米手机2)

    需求:在开发Android程序时,大家一直是使用ShowMessage.其实XE是支持下断点的. 操作:小米手机2: 1.小米手机2用USB线,连到电脑上. 2.小米手机2-设置-关于手机-" ...

  6. DataBinding 笔记

    DataBinding 笔记 android DataBinding notes 那些年踩过的坑 问题 那些年踩过的坑 非 public 类型的变量,getter 方法必须有,没有就会报错:Could ...

  7. Centos6.X 安装MongoDb

    1.查看linux版本,之所以查看linux版本,是因为centos7和以前版本用的防火墙不一样,安装完mongodb后,需要关闭防火墙(或者其他方法,专业运维人员使用,我们这里为简单,直接关闭即可) ...

  8. sql 联合查询

    SELECT NZD_Products.Prd_typename a FROM  dbo.NZD_Products where dbo.NZD_Products.Prd_barcodenumber = ...

  9. 64位系统下,一个32位的程序究竟可以申请到多少内存,4GB还是更多?(一)

    前言: cpu的位是指一次性可处理的数据量是多少,1字节=8位,32位处理器可以一次性处理4个字节的数据量,依次类推.32位操作系统针对的32位的CPU设计.64位操作系统针对的64位的CPU设计.操 ...

  10. 如何用MathType编辑这三个符号

    MathType是一款专门的公式编辑器,用来编辑数学物理等公式,很多期刊杂志的排版都会用到它.用MathType编辑公式的时候,完全不用考虑学习和上手的过程,打开就可以编辑出你的公式,所以这个工具对于 ...