Docker与NS3之间实现数据通信

系列文章目录

第一章 Docker和NS3之间实现数据通信


文章目录


前言

  NS3作为一款开源的网络仿真工具,自身拥有大量的协议库、信道模型库和移动模型库等,在网络协议仿真与算法验证这一块具有一定优势。但有时候仅仅通过NS3中构造的模拟网络场景以及模拟的业务流量缺乏一定的说服力,因此需要扩展NS3和外部物理节点或主机网络的连接,实现真实数据或业务流量向NS3的注入。首先需要解决的问题就是外部节点或应用程序和NS3之间的通信问题。

  Docker作为一款优秀开源容器引擎,能够提供操作系统层面资源的虚拟化,支持分布式,大规模的容器构建以及应用程序,因此想构建Docker到NS3之间的数据环路,为后续大规模网络仿真及开发提供基础。


提示:以下是本篇文章正文内容,下面案例可供参考

一、NS3是什么?

        NS3是一个离散事件模拟器,由美国华盛顿大学的Thomas R.Henderson教授及其研究小组在美国自然科学基金(NSF)的支持下,于2006年开始应用现代网络模拟技术和软件开发技术设计并开发的全新网络模拟工具。它是由C++编写的开源项目,主要运行平台是GUL/Linux(如Ubuntu等)。NS3主要用来模拟计算机网络,也可以在一台计算机上模拟现实世界中的各种类型与规模的网络。

1.NS3网络仿真工具

二、Docker是什么?

        Docker是一款开源的容器应用引擎。基于Linux Container(LXC)架构并在LXC上增加了一套完整的管理工具链和镜像仓库的一种虚拟化技术,它通过使用Docker引擎来管理和操作容器。Docker引擎包含了一个Docker守护进程和一组API,可以用来创建、启动、停止、删除和管理Docker容器。Docker容器结构如图2所示。

2.Docker容器结构图

三、Docker容器间通信以及NS3中的TapBridge

1.Docker容器间通信

        Docker间通信主要有三种方式:基于IP栈通信、Docker DNS server以及Joined容器通信。其中主常用的通信方式是基于IP栈的通信,这里主要介绍一下。

        对于Docker,环境在搭建好后会在操作系统中创建名为Docker0的网桥,默认情况下所有创建好的容器都会挂载到该网桥上,同时会自动获取一个IP地址,因此容器间的应用程序可以通过得知对方的IP地址来实现通信。当然用户也可以自定义网络,即创建一个自定义网桥,在创建容器时指定挂载在某个网桥下。两个容器要能通信,必须要有属于同一个网络的网卡。如图3所示:

Docker容器间基于IP栈的通信方式

  2.NS3中的TapBridge

        TapBridge支持将Tun/Tap等操作系统内核中的虚拟网络设备集成到NS3仿真环境中。安装了TapBridge网络设备的节点可以从物理主机中接收分组,然后通过Tun/Tap等虚拟网络设备将分组发送到NS3中,这里的节点可以是一个真实的物理节点,也可以是一个虚拟节点。这方便在NS3模拟网络中测试和验证物理节点协议栈和相关网络性能。

4.TapBridge示意图

        图4展示了一个安装了TapBridge网络设备的节点架构示意图。其中物理节点为主机中的实际节点,NS3节点为NS3中定义的模拟节点。物理节点产生数据分组通过Tap接口转发至NS3节点,NS3节点的作用就是在物理节点的Tap接口和模拟网络的信道间转发分组,从而实现模拟网络与物理节点的连接。

TapBridge的创建模式有三种:ConfigureLocal、UseLocal和UseBridge。它们主要的区别在于由谁来船创建Tap接口。在ConfigureLocal模式中,Tap由TapBridgeHelper:Install()函数自动创建。Tap接口的属性与TapBridge所属节点的NetDevice完全相同。在后两种模式中,TapBridge均使用已经创建好的Tap接口。因此ConfigureLocal模式适合于物理主机的场景,而UseLocal和UseBridge模式适合于虚拟主机的场景。

四、Docker与NS3之间实现数据通信

项目场景:

系统配置:

ubuntu系统:20.04LTS

python版本:3.8.10

NS3.38

Docker 24.0.2

1.整体架构

        我们在同一个主机操作系统中创建了两个Docker容器,即Docker Container1和Docker Container2。在创建Docker容器的同时会创建一对veth pair的互联接口,这对互联接口类似于一根通信管道,当向任意一端发送数据包时,另一端都能自动收到相同的包。互联接口的一端是容器内的网卡eth0,另一端则是veth(Virtual ethernet)接口。每个LXC容器内部可以运行特定的 Linux 应用程序或网络服务,每个Docker容器配备有相应的Internet协议栈,并与容器内网卡eth0相连。

        veth一端连接着容器内网卡eth0,另一端则连接着主机操作系统中的Docker Bridge(网桥),网桥的另一端连接的是用户或者程序创建的Tap设备。Tap设备是链路层的虚拟网络设备,其作用等同于一个以太网设备,它可以收/发链路层的第二层数据报文包,如以太网数据帧。Tap设备的另一端则连接着我们在NS3脚本中创建的TapBridge网络设备,TapBridge网络设备存在于NS3的用户空间。通过以上这些网络设备,从容器内应用产生的数据包最终可以进入NS3的用户空间,这些数据包最终通过TapBridge网络设备被转发到相应的CSMA网络设备,同理NS3中CSMA网络设备产生的数据包也可以通过同样的方式传递到容器内。最终实现容器与NS3之间互联互通。

5. Docker容器与NS3实现数据通信

 

2.实现步骤

1.创建Tap Devices

ip tuntap add tap-left mode tap #创建名为tap-left的Tap device

ip tuntap add tap-right mode tap #创建名为tap-right的Tap device

2. 设置Tap设备为混杂模式并启动

ip link set tap-left promisc on
ip link set tap-right promisc on
sudo ifconfig tap-left up
sudo ifconfig tap-right up

设置Tap为混杂模式是使Tap能够监听系统中所有正在发送的数据包。

3.创建Docker网桥(Bridge)并将对应的Tap绑定到相应的网桥上

docker network create net-left #创建名为net-left的Docker网桥
docker network create net-right #创建名为net-right的Docker网桥
brctl addif br-left tap-left #将tap-left绑定在net-left网桥
brctl addif br-right tap-right #将tap-right绑定在net-right网桥
ip link set dev net-left up #启动net-left网桥
ip link set dev net-right up #启动net-right网桥

4.创建两个Docker容器并指定容器分别挂载在不同的Docker网桥上

docker run -it --name left --network net-left ubuntu:18.04 /bin/bash #创建名为left的docker容器并挂载到net-left网桥上
docker run -it --name right --network net-right ubuntu:18.04 /bin/bash #创建名为right的docker容器并挂载到net- right网桥上

5.在Linux中分别创建自定义网桥并允许操作系统将以太网帧转发到新创建的网桥

sudo iptables -I FORWARD -m physdev --physdev-is-bridged -i net-left -p tcp -j ACCEPT
sudo iptables -I FORWARD -m physdev --physdev-is-bridged -i net-left -p arp -j ACCEPT
sudo iptables -I FORWARD -m physdev --physdev-is-bridged -i net-right -p tcp -j ACCEPT
sudo iptables -I FORWARD -m physdev --physdev-is-bridged -i net-right -p arp -j ACCEPT

PS:

* 这里的net-left和net-right都是Docker network中的网桥,在你的操作系统中显示的名字会不一样,会以br-****这样的名字出现。所以第5步代码中的net-left和net-right是需要改成br-****的。后面代码中所有的net-****都需要改成对应的br-****

* 设置arp转发时可能会报错,但不影响后续结果。 报错截图如下:

6.分别获取Docker容器进程 ID (PID)

pid_left=$(docker inspect --format '{{ .State.Pid }}' left)

pid_right=$(docker inspect --format '{{ .State.Pid }}' right)

7.创建一个新的网络命名空间,该命名空间将以符号方式链接到第一个Docker容器left

mkdir -p /var/run/netns
sudo ln -s /proc/$pid_left/ns/net /var/run/netns/$pid_left

8.创建 veth pair将容器连接到自定义网桥

sudo ip link add internal-left type veth peer name external-left

sudo ip link set internal-left master net-left

sudo ip link set internal-left up

 9.为容器分配 IP 地址和 MAC 地址

sudo ip link set external-left netns $pid_left
sudo ip netns exec $pid_left ip link set dev external-left name eth0
sudo ip netns exec $pid_left ip link set eth0 address 12:34:88:5D:61:BD
sudo ip netns exec $pid_left ip link set eth0 up
sudo ip netns exec $pid_left ip addr add 10.0.0.1/16 dev eth0

10.对Docker容器right重复步骤7-9

11.切换到NS3所在文件夹下并编译整个NS3工程,并启动root权限

./ns3 configure --enable-examples --enable-tests --enable-sudo

./ns3 build

12.配置tap-csma-virtual-machine.cc文件并运行该NS3脚本

// tap-csma-virtual-machine.cc文件内配置
TapBridgeHelper tapBridge; #创建tapBridge
// 将tapBr-idge设置为UseBridge模式
tapBridge.SetAttribute("Mode", StringValue(“UseBridge"));
// 将tap-left绑定tapBridge并安装入节点0
tapBridge.SetAttribute("DeviceName", StringValue("tap-left"));
tapBridge.Install(nodes.Get(0), devices.Get(0));
// 将tap-right绑定tapBridge并安装入节点1
tapBridge.SetAttribute("DeviceName", StringValue("tap-righ"));
tapBridge.Install(nodes.Get(1), devices.Get(1));

切换到NS3执行目录下并执行该脚本:

#在NS3目录下运行脚本
./ns3 run ns-3/src/tap-bridge/examples/tap-csma-virtual-machine.cc 

13.分别在两个Docker容器内ping对方

#left >ping 10.0.0.2 -i 1 -c 20

#right >ping 10.0.0.1 -i 1 -c 20

3.结果验证

6.未运行tap-csma-virtual-machine.cc脚本容器间不可达情形
7.运行tap-csma-virtual-machine.cc脚本后容器间可达情形

4.一个令人自闭的bug:

        由于tap设备这些都是虚拟的网络设备,在关机后再重启电脑就会突然消失。当我重新按照这些步骤在执行后,发现tap-left即使被挂载在网桥上但是怎么也启动不了,他的状态一直都是DOWN的。截图如下:

这里的tap-up是我新建的一个tap设备,和tap-left只有名字不同。

问题好像出在这个tap-up没有inet6的地址。

转机:

后面我发现还是NS3的问题,不得不说NS3在各种疑难杂症上真的算是一流软件(qAq).

只有当NS3识别并调用到tap-left或者tap-right设备时,才会分给它一个inet6的地址,这样tap设备的状态才会打开,如果没有识别调用到的话就一直时down的状态。但是最后到底这个问题该怎么解决目前我还是没有好的办法,希望如果有能看到最后并且有碰到过这样的问题的小伙伴不吝赐教一下。万分感谢~


总结

提供了一种Docker和NS3间相互通信的方法。

参考文献:

[1]:HOWTO Use Linux Containers to set up virtual networks - Nsnam

[2]How to Use Docker and NS-3 to Create Realistic Network Simulations

  • 12
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值