LXC之namespace模块学习-小结

目录:

  Networking Namespaces

(1)有那些namespeace

(2命名空间设备指的是那些?

(3)namespacesocket 与网络设备的关系:

  代码分析

2.1 数据结构  struct net {

2.2 网络命名空间”与“ 网络设备”的组织关系图:

2.3 网络命名空间的操作

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

  Networking Namespaces

1有那些namespeace

(2命名空间设备指的是那些?

(3)namespacesocket 与网络设备的关系:

 

1.0  整体框架:namespacesocket,协议栈,网络设备的关系:

LXC之namespace模块学习-小结_第1张图片

图片引用自:http://www.cnblogs.com/zmkeil/archive/2013/05/01/3053545.html

1有那些namespeacelinux系统包括默认的命名空间:“init_net和用户自定义的net

这里namespace 一般是默认的命名空间:“init_net,也就是所有的"网络通信协议"+"网络设备"都是属于默认的命名空间.

网络命名空间定义了2个链表,pernet_list和net_namespace_list

如下

static LIST_HEAD(pernet_list);

static struct list_head *first_device = &pernet_list;

LIST_HEAD(net_namespace_list);

init_net会被链接到net_namespace_list这个双向链表上。

pernet_operations结构将被链接到pernet_list这个双向链表上。

以后,如果没自定义网络命名空间的话,所有想用网络命名空间时都将利用默认的“init_net”

 

引用自:源文档

 

(2命名空间设备指的是那些?就是网络设备。通过register_pernet_device注册:就是“注册一个网络设备”到“所有的网络命名空间net网络设备包括两类:虚拟的网络设备和物理网络设备:

 

a)虚拟的网络设备:参考"核心层:命名空间:register_pernet_device作用“

虚拟网络设备的协议根据自身设计特点对skb数据进行处理,并通过全局变量xx_net_id和各个协议私有的特殊数据结构xx_net,寻找到该数据包对应的应用层socket插口,并将其放在该socket插口的接收队列中;最后应用层在某个时刻会通过read系统调用读取该数据

ipv6隧道设备

static struct pernet_operations ip6_tnl_net_ops = {用于ipv6iPv4之间互通

pppoe设备

pppoe是一个完整的协议,是从应用层到设备之间的协议模块,从这个意义上来讲,它和INET域中的协议是等价的,定义协议族:PF_PPPOX

ipv4gre设备(GRE路由协议)

 

vti协议设备

 

---各个设备私有的特殊数据结构xx_net全局变量xx_net_id有那些?例如:

1)static int pppoe_net_id__read_mostly;

2

staticint ip6_tnl_net_id __read_mostly;

struct ip6_tnl_net {

/*the IPv6 tunnel fallback device */

structnet_device *fb_tnl_dev;

/*lists for storing tunnels in use */

structip6_tnl __rcu *tnls_r_l[HASH_SIZE];

structip6_tnl __rcu *tnls_wc[1];

structip6_tnl __rcu **tnls[2];

};

3)ipv4的:static int ipgre_net_id__read_mostly;

4)static int vti_net_id__read_mostly;

struct vti_net {

structip_tunnel __rcu *tunnels_r_l[HASH_SIZE];

structip_tunnel __rcu *tunnels_r[HASH_SIZE];

structip_tunnel __rcu *tunnels_l[HASH_SIZE];

structip_tunnel __rcu *tunnels_wc[1];

structip_tunnel __rcu **tunnels[4];

 

structnet_device *fb_tunnel_dev;

};

b 物理网络设备,

比如网卡驱动、无线网卡驱动。

 

======================================================================================

 

(3)namespacesocket 与网络设备的关系:

上述的socket索引方法有个绕弯的地方:就是每个协议私有的xx_net结构可以直接由协议模块本身分配,索引起来也方便,不要用到全局的net_generic。而目前内核所用的方法,其实是为了另外的目的,那就是命名空间namespace。也就是虚拟多用户的一套机制,具体的也没细看,好像目前内核整个namespace还没有全部完成。


network的命名空间问题主要在于,每个协议模块的xx_net私有结构不仅是一个,而是由内核全局决定的,即每注册一个新的用户(有点像虚拟机机制),就分配一个新的xx_net结构,这样多用户间可以用参数相同的socket连接,但却指向不同的socket。

 

LXC之namespace模块学习-小结_第2张图片

         图片引用自 

http://www.cnblogs.com/zmkeil/archive/2013/05/01/3053545.html> 


     可以看到 socket 的操作 都会有个 net 参数 ,就是为了这个作用,主要实现函数在 namespace.c 中。

代码如下:

intsock_create(int family, int type, int protocol, struct socket **res)

{

return__sock_create(current->nsproxy->net_ns,family, type, protocol, res, 0);

}

int__sock_create(struct net *net, int family, int type, int protocol,

 struct socket **res, int kern)

参数:

Net

current->nsproxy->net_ns获取当前线程的网络命名空间,“当前线程”被“创建”的时候,就是同时“copy了一个网络命名空间”,参考:

”核心层:命名空间-创建命名空间-内核层代码分析“

作用就是表明该线程所在的命名空间,进而找到该空间内的网络设备,路由表,ARP表,ip地址表,iptables,ebtables,等等。总之,与网络有关的组件,

比如:ipv4操作路由表,通过socket参数成员的:命名空间net

int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){

struct net *net = sock_net(sk);

…..

case SIOCADDRT:

case SIOCDELRT:

case SIOCRTMSG:

err = ip_rt_ioctl(net, cmd, (void __user *)arg);

 

int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)

{

…..

tb = fib_new_table(net, cfg.fc_table);

…..

 

static inline struct fib_table *fib_new_table(struct net *net, u32 id)

{

return fib_get_table(net, id);

}

static inline struct fib_table *fib_get_table(struct net *net, u32 id)

{

struct hlist_head *ptr;

 

ptr = id == RT_TABLE_LOCAL ?

&net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX] :

&net->ipv4.fib_table_hash[TABLE_MAIN_INDEX];

return hlist_entry(ptr->first, struct fib_table, tb_hlist);

}

Family

指明协议族(af_inet.c,af_inet6.c,ieee802154

protocol

该协议族下的那一种协议(tcp.udp,icmp,)

 

  代码分析

2.1 数据结构  struct net {

2.2  网络命名空间”与“ 网络设备”的组织关系图:

2.3 网络命名空间的操作

=======================================================================================================

从2.6开始,kernel采用namespaces管理networking subsystem.

namesapce,如下:

// include/net/net_namespace.h

2.1 数据结构  struct net {
    atomic_t count; 
/* Todecided when the network
                   * namespaceshould be freed.
                   */
    ...
    
struct list_head list; /* list ofnetwork namespaces */
    ...
    
struct proc_dir_entry *proc_net;
    
struct proc_dir_entry *proc_net_stat;
    
struct proc_dir_entry *proc_net_root;
    
struct net_device *loopback_dev; /* Theloopback */
    
struct list_head dev_base_head;
    
struct hlist_head *dev_name_head;
    
struct hlist_head *dev_index_head;
  };

  • count: 使用计数.
  • list: 所有namespaces用一个以 net_namespace_list 为头的doubly linked list来维护copy_net_ns 函数把新的namespace加入list中去.
  • proc_net 表示 /proc/net , proc_net_stat 表示 /proct/net/stats , proc_net_root 表示 /proc .
  • Network devices由数据结果 struct net_device 表示.在一个namespace中的所有设备通过以 dev_base_head 为头的doubly linked list来存储.并且存储在另外两个hash表中使用device namekey dev_name_head和使用interface indexkey dev_index_head.
    devices和interfaces的概念有点不同.

Devices

表示提供物理传输能力的硬件设备.

Interfaces

可以是虚拟的点.可能基于实际设备上实现.比如一个网卡可以提供两个interfaces.

 

 

2.2  网络命名空间”与“ 网络设备”的组织关系图:

        在Linux协议栈中引入网络命名空间,是为了支持网络协议栈的多个实例,而这些协议栈的隔离就是由命名空间来实现的(有点像进程的线性地址空间,协议栈不能访问其他协议栈的私有数据)。需要纳入命名空间的元素包括进程,套接字,网络设备。进程创建的套接字必须属于某个命名空间,套接字的操作也必须在命名空间内进行,网络设备也必须属于某个命名空间,但可能会改变,因为网络设备属于公共资源<~/include/net.h>。

       在内核中引入命名空间工作量非常大,现在还没有全部完成。为了保持与向后兼容,网络系统在初始化的时候只初始化了一个命名空间,即init_net命名空间。所有的命名空间通过list项组织起来。每个网络设备都对应有一个命名空间。命名空间下的所有网络设备通过dev_base_head组织在一起。

 

引用 源文档

 

 

 

2.3 网络命名空间的创建

每个networknamespace包换许多元件,所以当一个新的network namespace被创建,这些元件必须被初始化.同样,当它被删除时,需要做必要的清理工作.

 

Kernel 引入了如下结构 pernet_operations:来维护所有需要做的 initialization/cleanup 工作:

// include/net/net_namespace.h
structpernet_operations {
  struct list_headlist;
  int (*init)(struct net *net);
  void (*exit)(struct net *net);
};

当一个新的network namespace被创建,kernel遍历 pernet_operations list,并调用其init函数.

 

   linux内核中默认情况下,会有一个“默认的网络命名空间”,其名为init_net,并也将其导出,作为全局变量。

   struct netinit_net;

    EXPORT_SYMBOL_GPL(init_net);

   

   kernel2.42.6:向内核中添加一个网络命名空间:

   struct net *net_create(void);//这个函数用于向内核中添加一个网络

                                 //命名空间;

   这个函数主要做了三件事:

      1.通过struct net*net_alloc(void)函数分配了一个structnet结构体

       2.通过setup_net(struct net*ns)函数对分配的struct net结构体进行了相应的设置;

      3.最后,将分配的struct net结构体加入到 net_namespace_list的双链表尾部。

 

Kernel 3.10是copy_net_ns()添加一个网络命名空间

   

   释放一个网络命名空间:

   voidnet_free(struct net *ns);


你可能感兴趣的:(虚拟化技术)