基于Linux Network Namespace的Mininet架构分析
Mininet作为一个轻量级的SDN仿真工具,在其系统实现架构中充分利用了Linux命名空间内核技术,其中Linux Network Namespace机制更是Mininet软件架构的基石,对网络资源的模拟发挥着重要作用。其实Linux Network Namespace在OpenStack和Docker等开源项目中也广泛应用。
什么是Linux Network Namespace? 从Linux 2.6.24版的内核开始,Linux 逐渐支持6种不同类型的命名空间。这其中包括进程间通信(IPC)的命名空间、进程命名空间、网络命名空间、挂载命名空间、UTS 命名空间、 用户命名空间。通过命名空间技术使得用户创建的进程能够与系统分离得更加彻底,从而不需要使用更多的底层虚拟化技术。Linux Namespaces机制提供一种资源隔离方案,使得PID、Network、IPC等系统资源不再具有全局性,而是属于某个特定的Namespace。每个Namespace下的资源对于其他Namespace下的资源都是透明,不可见的。因此在操作系统层面上看,就会出现多个相同pid的进程。而在用户层面上只能看到属于用户自己Namespace下的资源,例如使用ps命令只能列出自己Namespace下的进程。这样每个Namespace看上去就像一个单独的Linux系统。Linux的命名空间技术架构如下图所示:
Network namespace主要提供了网络资源的隔离能力,包括网络设备、IPv4和IPv6协议栈、IP路由表、防火墙、/proc/net目录、/sys/class/net目录、端口(socket)等等。从网络命名空间的角度看,它代表着分配给一个或多个进程的私有网络资源集合。其主要特性集中在虚拟化和隔离。每个Linux container拥有其自己的网络设备(虚拟的)和用于绑定自己网络端口号的应用程序。主机上合适的路由规则可以将网络数据包和特定container相关的网络设备关联。网络命名空间的主要应用场景包括:1、多个网络命名空间可以拥有eth0和lo等网络设备;2、多个Apache服务器进程可以在不同网络命名空间的80端口上进行监听;3、一个进程不能嗅探其他网络命名空间的流量;4、一个进程不能关闭其他网络命名空间的接口。
后台进程可以运行在不同网络命名空间内的相同端口上,用户还可以自己虚拟出网卡。一个物理的网络设备最多存在于一个Network namespace中,你可以通过创建veth pair(虚拟网络设备对)在不同的Network namespace间创建通道进行通信。veth pair是用于不同Network namespace间进行通信的方式,veth pair将一个Network namespace数据发往另一个Network namespace的veth。
简单veth pair通信机制
多Network namespace借助bridge进行通信
Mininet如何使用网络命名空间技术? Mininet使用Linux Network Namespaces来创建虚拟节点,默认情况下,在仿真网络中Mininet会为每一个host创建一个新的网络命名空间,同时在root Namespace(根进程命名空间)运行交换机和控制器的进程,因此这两个进程就共享同一个网络命名空间。由于每个主机都有各自独立的网络命名空间,我们就可以进行个性化的网络配置和网络程序部署。由于命名空间的虚拟技术没有提供类似于虚拟机的持久化能力,所以在Mininet关闭时不能保存所有的配置。
Mininet使用网络命名空间来让不同的Host进程拥有独立的网络上下文。在如下的示例中,两个虚拟主机H1和H2连接到交换机S1,通过Bash来模拟H1和H2,交换机S1运行在Linux内核运行的root namespace。H1和H2就拥有自己的网络命名空间以及私有网络接口h1-eth0和h2-eth0。交换机S1有两个端口s1-eth0和s1-eth1,通过veth pair与对应的主机接口相连,这样H1和H2就可以通过S1进行通信。s1-eth0和s1-eth1间的数据包转发通过软件交换机完成,它运行在root namespace并使用物理接口eth0,等待控制器的指令。
其实基于Linux Network Namespace就可以原生支持操作系统层级的虚拟化,就可以被用来进行网络仿真。而Mininet工具使用Python语言对网络仿真过程所涉及的节点、拓扑、链路等进行了封装抽象,便于科研人员迅速开展仿真工作。Mininet创建的Network namespace是nameless的,所以通过ip netns list命令是查看不到的,而通过ip netns add命令创建的namespace是带name的,这是两者最明显的区别之处。这其中ip命令是iproute2软件包里面的一个强大的网络配置工具,它能够替代一些传统的网络管理工具,例如ifconfig、route等,使用权限为超级用户。几乎所有的Linux发行版本都支持该命令。
下面就看看两个具体的示例,一个是通过ip命令创建网络命名空间进行实验,另一个是通过Mininet的命令进行实验。两者相比,Mininet就凸显出优势,实验用户可以不再关心底层系统实现,而聚焦在上层实验逻辑上。
示例一:
# Create host namespaces
ip netns add h1
ip netns add h2
# Create switch
ovs-vsctl add-br s1
# Create links
ip link add h1-eth0 type veth peer name s1-eth1
ip link add h2-eth0 type veth peer name s1-eth2
ip link show
# Move host ports into namespaces
ip link set h1-eth0 netns h1
ip link set h2-eth0 netns h2
ip netns exec h1 ip link show
ip netns exec h2 ip link show
# Connect switch ports to OVS
ovs-vsctl add-port s1 s1-eth1
ovs-vsctl add-port s1 s1-eth2
ovs-vsctl show
# Set up OpenFlow controller
ovs-vsctl set-controller s1 tcp:127.0.0.1
ovs-controller ptcp: &
ovs-vsctl show
# Configure network
ip netns exec h1 ifconfig h1-eth0 10.1
ip netns exec h1 ifconfig lo up
ip netns exec h2 ifconfig h2-eth0 10.2
ip netns exec h1 ifconfig lo up
ifconfig s1-eth1 up
ifconfig s1-eth2 up
# Test network
ip netns exec h1 ping -c1 10.2
示例二:
sudo mn --topo=single,2
然后使用pingall命令进行类似的实验
其实从Mininet的util.py中makeIntfPair、moveIntfNoRetry、moveIntf等函数实现,以及link.py文件中对makeIntfPair函数的调用可以看出一些端倪。在makeIntfPair函数中实现了接口管理,包括创建一对veth接口、关联node接口、建立连接映射等。Mininet通过对IP命令的封装实现了基于Linux Network namespace的网络构建。
参考资料: 1、介绍 Linux 的命名空间。https://linux.cn/article-5019-1.html 2、Docker背后的内核知识:命名空间资源隔离。http://linux.cn/article-5057-6.html 3、 Linux内核的namespace机制分析。http://blog.chinaunix.net/uid-20788636-id-4479145.html 4、Docker实践(4)—network namespace与veth pair。http://www.cnblogs.com/hustcat/p/3928261.html 5、mininet与namespace。http://vinllen.com/mininetyu-namespace/ 6、Mininet Walkthrough。http://mininet.org/walkthrough 7、Mininet运作原理。http://hwchiu.logdown.com/posts/221370-mininet-parsing 8、Testing SDN behavior with Mininet。http://www.linux-magazine.com/Issues/2014/162/Mininet 9、Mininet network simulator review。
http://www.brianlinkletter.com/mininet-test-drive/
10、Mininet中虚拟机构成的分析。http://richardzhao.me/?p=369 11、linux IP 命令使用举例。http://blog.csdn.net/radkitty/article/details/3022181
- Asp.net 后台添加CSS、JS、Meta标签(帮助类)
- 分享一下cookies操作(增、删、改、查)小经验
- [Silverlight 4 RC]WebBrowserBrush概览
- 一个例子理解C#位移
- WCF后续之旅(3): WCF Service Mode Layer 的中枢—Dispatcher
- silverlight 2 Random 随机数解决方案
- 开发中巧用Enum枚举类型
- Jquery 事件冒泡
- Vue2的单元测试与调试技术
- silverlight beta 2 将在本周末发布.
- [Silverlight 4 RC]WebBrowser概览
- 英文域名chosen.com超22万元易主
- 简单介绍Docker的架构特性与局限
- .NET4.0下网站应用程序用UrlRewriter.dll重写无后缀路径 (在IIS7.5中的配置方法)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- SpringCloud2020 学习笔记(三) cloud-api-commons通用模块搭建
- SpringCloud2020 学习笔记(四) cloud-provider-payment8001支付模块
- SpringCloud2020 学习笔记(五)cloud-consumer-order80 消费者订单模块
- SpringCloud2020 学习笔记(六)如何开启idea中的Run DashBoard or Services
- SpringCloud2020 学习笔记(七)cloud-eureka-server7001 EurekaServer服务端安装
- SpringCloud2020 学习笔记(八)cloud-provider-payment8001支付模块入驻eurekaServer注册中心
- SpringCloud2020 学习笔记(九)cloud-consumer-order80 消费者订单模块入驻eurekaServer注册中心
- SpringCloud2020 学习笔记(十)cloud-eureka-server7001 cloud-eureka-server7002 Eureka集群安装
- Python爬虫之抓取某东苹果手机评价
- python学习笔记
- 必看!!!python列表( 增 删 改 查),超详细讲解!!
- Python识别验证码
- 多线程爪巴虫下载进击的巨人
- 利用selenium实现自动翻页爬取某鱼数据
- 20行Python代码爬取下载应用宝所有APP软件