【案例共创】基于华为云主机的软件定义网络SDN实践

本案例由开发者:华为2024年第三批次协同育人项目-南航金城学院-孙福清教师提供

一、概述

1. 案例介绍

本案例是在华为云主机中,进行软件定义网络SDN的二层交换机交换原理实践:使用 python 开源模块 mininet,编写 python 代码建立2个SDN交换机4个主机的简单网络拓扑,按照二层交换机mac地址学习和转发表原理,构建转发流表,下发到两个SDN交换机,使得4个主机之间网络互通。

通过本实践,使得学生学习理解软件定义网络SDN概念,学习和理解二层交换机mac地址学习和转发表。

华为开发者空间,是为全球开发者打造的专属开发者空间,致力于为每位开发者提供一台云主机、一套开发工具和云上存储空间,汇聚昇腾、鸿蒙、鲲鹏、GaussDB、欧拉等华为各项根技术的开发工具资源,并提供配套案例指导开发者 从开发编码到应用调测,基于华为根技术生态高效便捷的知识学习、技术体验、应用创新。

2. 适用对象

  • 个人开发者
  • 高校学生

3. 案例时间

本案例总时长预计90分钟。

4. 案例流程

说明:

  1. 配置python开发环境;
  2. 安装python模块mininet;
  3. 验证python模块mininet;
  4. SDN仿真(MAC地址学习和转发)。

5. 资源总览

本案例预计花费0元。

资源名称规格单价(元)时长(分钟)
华为开发者空间 - 云主机鲲鹏通用计算增强型 kc2 | 4vCPUs | 8G | Ubuntu免费90

二、环境配置

1. 开发者空间配置

面向广大开发者群体,华为开发者空间提供一个随时访问的“开发桌面云主机”、丰富的“预配置工具集合”和灵活使用的“场景化资源池”,开发者开箱即用,快速体验华为根技术和资源。

进入华为开发者空间工作台界面,点击打开云主机 > 进入桌面连接云主机。 如果还没有领取云主机进入工作台界面后点击配置云主机,选择Ubuntu操作系统。

2. 安装文本编辑器gedit

本案例中,参考案例《【案例共创】华为云主机Linux Python开发环境配置》“三、文本编辑工具gedit”完成文本编辑工具gedit的安装和测试功能。

3. 配置ubuntu apt镜像软件源

本案例中,参考案例《【案例共创】华为云主机Linux Python开发环境配置》“四、配置ubuntu的apt软件源”完成软件源的安装和更新。

:华为镜像源地址:

http://repo.huaweicloud.com/ubuntu-ports/

三、安装验证 python 模块 mininet

1. python 模块 mininet

SDN 是一种网络架构,它将控制平面(Control Plane)与数据平面(Data Plane)分离,使得网络控制逻辑集中在一个控制器中(如 OpenDaylight、ONOS、Ryu 等),而数据转发由交换机完成。 核心理念:通过软件编程控制网络行为,而不是手动配置每个设备。 协议:OpenFlow 是最常用的南向协议,用于控制器与交换机通信。

Mininet 是一个轻量级的软件定义网络SDN的网络仿真器,用于在linux系统(如笔记本电脑或虚拟机)上快速创建包含主机、交换机、控制器和链路的完整SDN网络拓扑。 特点: - 支持 OpenFlow 协议; - 可以运行真实的 Linux 网络栈; - 支持自定义拓扑、带宽、延迟、丢包率等参数; - 与真实网络行为高度一致。 官网地址:https://mininet.org/

2. 安装mininet

  1. 多种方式安装mininet 本案例采用Ubuntu包安装方式安装mininet,非常简单方便。在root用户下,先创建一个独立的文件夹SDN,在这个文件夹下安装mininet。

依次执行如下命令:

#创建文件夹
mkdir sdn

#进入文件夹
cd sdn

#安装mininet
apt install mininet

安装的位置:/usr/lib/python3/dist-packages/mininet

由于采用了包安装方式,python包mininet位于ubuntu的python全局环境,因此直接引用mininet模块,无需创建Python的虚拟环境。

#python命令
python3

#导入mininet
import mininet

#导入之后退出
exit()

3. 验证mininet

在终端命令行下运行mininet命令mn创建一个最小的网络拓扑,并测试节点之间的可达。 创建一个最小的仿真网络:1个交换机带2个主机:

mn

测试两个主机之间是否可达:

#测试是否可达
pingall
#退出
exit

清理仿真资源

mn -c

四、网络仿真(无控制器的二层交换机)

1. 定义仿真网络

  1. Mininet有两种方式定义仿真网络
  2. 命令行方式:创建仿真网络拓扑,非常不方便,记忆众多命令,容易出错, 本案例不使用。
  3. python代码:创建仿真网络拓扑,可以定义更为复杂的仿真网络,本案例采用。

仿真网络思想: 没有SDN控制器ryu、pox等,只有交换机switch和主机host。 根据二层交换机的基于MAC地址学习和转发的原理,人工构造和添加流表,使得主机之间互通。

仿真网络拓扑

  1. 示例python代码
#!/usr/bin/env python

from mininet.net import Mininet
from mininet.node import RemoteController
from mininet.node import Host
from mininet.node import OVSKernelSwitch
from mininet.cli import CLI
from mininet.log import setLogLevel, info

def myNetwork():
    net = Mininet( topo=None,
                   build=False)

    info( '*** Adding controller\n' )
    c0=net.addController(name='c0',
                      controller=RemoteController,
                      ip='127.0.0.1',
                      protocol='tcp',
                      port=6633)

    info( '*** Add switches\n')
    s1 = net.addSwitch('s1', cls=OVSKernelSwitch)
    s2 = net.addSwitch('s2', cls=OVSKernelSwitch)

    info( '*** Add hosts\n')
    h1 = net.addHost('h1', cls=Host, defaultRoute=None,mac='24:69:A5:A2:CA:01')
    h2 = net.addHost('h2', cls=Host, defaultRoute=None,mac='24:69:A5:A2:CA:02')
    h3 = net.addHost('h3', cls=Host, defaultRoute=None,mac='24:69:A5:A2:CA:03')
    h4 = net.addHost('h4', cls=Host, defaultRoute=None,mac='24:69:A5:A2:CA:04')

    info( '*** Add links\n')
    net.addLink(h1, s1)
    net.addLink(h2, s1)
    net.addLink(h3, s2)
    net.addLink(h4, s2)
    net.addLink(s1, s2)

    info( '*** Starting network\n')
    net.build()
    info( '*** Starting controllers\n')
    for controller in net.controllers:
        controller.start()

    info( '*** Starting switches\n')
    net.get('s1').start([c0])
    net.get('s2').start([c0])

    CLI(net)
    net.stop()

if __name__ == '__main__':
    setLogLevel( 'info' )
    myNetwork()

  1. 代码释义 (1)引入 Mininet 的核心类 代码
from mininet.net import Mininet
from mininet.node import RemoteController, Host, OVSKernelSwitch
from mininet.cli import CLI
from mininet.log import setLogLevel, info

释义Mininet:整个仿真网络的“总管”。 RemoteController:让 Mininet 去连外部控制器(本例是 POX)。 Host / OVSKernelSwitch:主机与 Open vSwitch 内核交换机。 CLI:交互式命令行。 setLogLevel, info:打印彩色日志。

(2)创建一个“空壳”网络实例,稍后再往里塞节点 代码

def myNetwork():
    net = Mininet(
        topo=None,   # 不依赖外部 Topo 对象,后面手动加节点
        build=False )  # 先不立刻 build,方便后面再改

释义: 创建空壳网络对象,后面逐步向内增加节点:控制器、交换机,主机等。

(3)添加控制器 代码

info('*** Adding controller\n')
c0 = net.addController(
    name='c0',
    controller=RemoteController,
    ip='127.0.0.1',
    protocol='tcp',
    port=6633
)

释义: 控制器名字叫 c0。 类型是 RemoteController,即外部控制器(POX、Ryu、ODL…)。 地址端口指向本地6633,正好与 POX 默认一致。

(4)添加交换机 代码

info('*** Add switches\n')
s1 = net.addSwitch('s1', cls=OVSKernelSwitch)
s2 = net.addSwitch('s2', cls=OVSKernelSwitch)

释义: 两台 Open vSwitch 内核交换机 s1、s2。 cls=OVSKernelSwitch 表示使用内核态 datapath(性能高,需 root)。

(5)添加主机 代码

info('*** Add hosts\n')
h1 = net.addHost('h1', cls=Host, defaultRoute=None,
                 mac='24:69:A5:A2:CA:01')

释义: 四个主机,手动指定 MAC 方便抓包或做流表下发实验。 defaultRoute=None 表示暂时不自动配置默认网关。

(6)添加链路 代码

info('*** Add links\n')
net.addLink(h1, s1)   # h1 连 s1
net.addLink(h2, s1)   # h2 连 s1
net.addLink(h3, s2)   # h3 连 s2
net.addLink(h4, s2)   # h4 连 s2
net.addLink(s1, s2)   # 两台交换机互连

释义: 默认链路带宽无限、延迟 0ms、无丢包;如需限制可加 bw=10,delay='5ms' 等参数。

(7)启动网络 代码

info('*** Starting network\n')
net.build()      # 真正创建 namespace、veth、OVS 等
info('*** Starting controllers\n')
for controller in net.controllers:
    controller.start()

info('*** Starting switches\n')
net.get('s1').start([c0])
net.get('s2').start([c0])

释义: net.build():生成所有虚拟设备。 把 s1、s2 的控制器指向c0,这样交换机才会发 Packet-In 给 POX 等控制器。 注意顺序:先起控制器 → 再起交换机,否则交换机会报错 “no controller”。

(8)进入交互 CLI & 清理 代码和释义

CLI(net)   # 阻塞在这里,用户可敲 pingall、iperf、dpctl...
net.stop() # 用户键入 exit 后自动清理 veth、namespace、OVS

(9)代码主入口 代码

if __name__ == '__main__':
    setLogLevel('info')  # 打印 INFO 级别以上日志,好看
    myNetwork()

释义: 脚本直接运行时执行myNetwork(),开始仿真。

2. 启动仿真网络

  1. 新建空白py代码文件准备编写py代码。
gedit 2switch4hosts.py

如果gedit未授权,还需要对gedit进行root账号的X图形服务器权限授权,允许 root 用户从本地连接到 X 服务器,另开一个终端,输入如下代码:

xhost +local:root

:执行代码报授权协议,只需按照上述步骤执行即可。

再次新建空白py代码文件,将第一步中示例代码复制到文件中,点击保存。

gedit 2switch4hosts.py

  1. 执行代码 通过如下命令执行代码,定义、创建仿真网络,启动仿真:
python3 2switch4hosts.py

  1. 测试连通性 执行如下代码测试仿真网络主机之间的网络连通性。
pingall

此时仿真网络既没有配置SDN控制器,也没有下发流表,因此主机之间是不通的。

3. 构造下发流表

  1. 查看仿真网络端口连接关系 使用linke查看连接关系。
links

4个主机的mac地址,通过代码或者仿真命令: ('h1', cls=Host, defaultRoute=None,mac='24:69:A5:A2:CA:01') ('h2', cls=Host, defaultRoute=None,mac='24:69:A5:A2:CA:02') ('h3', cls=Host, defaultRoute=None,mac='24:69:A5:A2:CA:03') ('h4', cls=Host, defaultRoute=None,mac='24:69:A5:A2:CA:04')

根据二层交换机的MAC地址学习原理,构造MAC地址学习表:

主机MAC地址表交换机端口
h124:69:A5:A2:CA:01s11
h224:69:A5:A2:CA:02s12
h324:69:A5:A2:CA:03s13
h424:69:A5:A2:CA:04s13
主机MAC地址表交换机端口
h124:69:A5:A2:CA:01s23
h224:69:A5:A2:CA:02s23
h324:69:A5:A2:CA:03s21
h424:69:A5:A2:CA:04s22

根据二层交换机的MAC地址转发原理,从哪来到哪去,依据上面的MAC地址学习表,构造SDN的转发流表:

交换机S1:到主机h1的报文的转发规则:

sh ovs-ofctl add-flow s1 dl_dst=24:69:A5:A2:CA:01,action=output:1

交换机S1:到主机h2的报文的转发规则:

sh ovs-ofctl add-flow s1 dl_dst=24:69:A5:A2:CA:02,action=output:2

交换机S1:到主机h3的报文的转发规则:

sh ovs-ofctl add-flow s1 dl_dst=24:69:A5:A2:CA:03,action=output:3

交换机S1:到主机h4的报文的转发规则:

sh ovs-ofctl add-flow s1 dl_dst=24:69:A5:A2:CA:03,action=output:3

交换机S2:到主机h1的报文的转发规则:

sh ovs-ofctl add-flow s2 dl_dst=24:69:A5:A2:CA:01,action=output:3

交换机S2:到主机h2的报文的转发规则:

sh ovs-ofctl add-flow s2 dl_dst=24:69:A5:A2:CA:02,action=output:3

交换机S2:到主机h3的报文的转发规则:

sh ovs-ofctl add-flow s2 dl_dst=24:69:A5:A2:CA:03,action=output:1

交换机S2:到主机h4的报文的转发规则:

sh ovs-ofctl add-flow s2 dl_dst=24:69:A5:A2:CA:04,action=output:2

目的地址为广播地址(ff:ff:ff:ff:ff:ff)的转发规则,例如ipv4的ARP报文: 交换机S1和S2:广播的以太网目的地址,泛洪FLOOD。

sh ovs-ofctl add-flow s1  dl_dst=ff:ff:ff:ff:ff:ff,actions=FLOOD
sh ovs-ofctl add-flow s2  dl_dst=ff:ff:ff:ff:ff:ff,actions=FLOOD

构造的流表如下:

sh ovs-ofctl add-flow s1  dl_dst=ff:ff:ff:ff:ff:ff,actions=FLOOD
sh ovs-ofctl add-flow s2  dl_dst=ff:ff:ff:ff:ff:ff,actions=FLOOD

sh ovs-ofctl add-flow s1 dl_dst=24:69:a5:a2:ca:01,action=output:1
sh ovs-ofctl add-flow s1 dl_dst=24:69:a5:a2:ca:02,action=output:2
sh ovs-ofctl add-flow s1 dl_dst=24:69:a5:a2:ca:03,action=output:3
sh ovs-ofctl add-flow s1 dl_dst=24:69:a5:a2:ca:04,action=output:3

sh ovs-ofctl add-flow s2 dl_dst=24:69:a5:a2:ca:01,action=output:3
sh ovs-ofctl add-flow s2 dl_dst=24:69:a5:a2:ca:02,action=output:3
sh ovs-ofctl add-flow s2 dl_dst=24:69:a5:a2:ca:03,action=output:1
sh ovs-ofctl add-flow s2 dl_dst=24:69:a5:a2:ca:04,action=output:2

下发流表,将上述代码依次执行: 再次测试仿真网络的主机之间的连通性:

五、安装验证python控制器pox

1. 开源SDN控制器pox

POX是一个基于python的开源 OpenFlow/SDN 控制器,其底层模块由C++实现,上层应用可以用python编写,提供快速开发网络控制软件原型的平台。 基于python3开源控制器POX,因其简单易用而广泛应用,适合初学者和小规模SDN网络实验,是SDN入门、学习SDN控制器的很好选择。 在SDN架构中,POX作为控制器负责集中管理网络的行为,可进行路径选择、流量管理、安全策略应用等操作。

简单案例: - mininet连接POX控制器, - POX运行l2_pairs组件, - mininet使用h1 ping h2时,mininet交换机上报给控制器事件packet_in, - 控制器的pox的l2_pairs组件可以抽取packet_in中的src_mac和in_port,进行mac地址学习, 生成mac地址转发表, - 控制器根据事件packet_in中的dst_mac,查找转发表,得到报文的转发目的端口,构造下发下发的src_mac和dst_mac的2条流表flowentry到mininet交换机, - mininet交换机就工作在传统的二层交换机模式。

代码地址: https://github.com/noxrepo/pox https://noxrepo.github.io/pox-doc/html/

2. 安装下载pox

pox目前都没有apt安装的包以及pyhton pip安装的模块,只有纯python代码,通过git可以下载到本地直接进行python运行,无需安装。 新创建一个独立文件夹:

#创建一个独立文件夹
mkdir 202507

#进入到这个目录下
cd 202507

在此目录下下载源码:

git clone https://github.com/noxrepo/pox
#查看
ls
#进入pox
cd pox
#查看
ls

下载的代码是pox的gar分支,要求python3:POX versions are named. Starting with POX "gar", POX officially requires Python 3。 下载后的快速启动方式:python3 pox.py samples.pretty_log forwarding.l2_learning。

3. 启动控制器pox

  1. 快速启动pox 使用如下命令进行启动:
python3 pox.py  log.level --DEBUG forwarding.l2_learning

说明: - pox.py,是其启动入口。 - log.level --DEBUG,是将调试信息打开,可以更好的观察过程。 - forwarding.l2_learning,是一种控制器实现的模式,二层交换机学习。

从提示信息可以看出,pox最后更新时间比较早,最高只支持python3.9版本。而华为云主机的预装python版本为 python3.12。但实际pox在python 3.12下运行也正常。

  1. 启动mininet 在另一个终端启动mininet。
python3 2switch4hosts.py

从上图可以看到,POX终端的输出提示mininet成功连接上了pox控制器。 “ERROR:packet:(dns) parsing questions: ord() expected string of length 1, but int found"提示dns报文解释错误,不用理会,不影响本案例。 如果要消除,需要在华为云主机上安装python的多版本,使用python3.9来运行pox,则消除错误。

  1. Mininet的SDN交换机连接上pox的SDN控制器,可以开始仿真 依次执行如下命令,查看仿真结果:
dpctl dump-flows

第一次仿真不通,进行pingall操作:

pingall

再次仿真:

dpctl dump-flows

从上可以看出,初始mininet交换机上没有流表,但开始执行主机互通测试后,得到流表,并且主机之间也互通。 POX终端输出调试信息:向交换机下发安装转发规则的流表 “DEBUG:forwarding.l2_learning:installing flow for 24:69:a5:a2:ca:02.2 -> 24:69:a5:a2:ca:01.1 DEBUG:forwarding.l2_learning:installing flow for 24:69:a5:a2:ca:01.1 -> 24:69:a5:a2:ca:02.2……”。

控制器pox自带的forwarding.l2_learning的模式,下发的流表: “cookie=0x0, duration=5.399s, table=0, n_packets=1, n_bytes=42, idle_timeout=10, hard_timeout=30, priority=65535,arp,in_port="s1-eth2",vlan_tci=0x0000,dl_src=24:69:a5:a2:ca:02,dl_dst=24:69:a5:a2:ca:01,arp_spa=10.0.0.2,arp_tpa=10.0.0.1,arp_op=2 actions=output:"s1-eth1"……” 这个流表,不是前面所说的传统L2交换机的只基于MAC地址学习和转发的转发模式,而是使用了:源mac,目的mac,源ip,目的ip等的匹配规则。

六、反馈改进建议

如您在案例实操过程中遇到问题或有改进建议,可以到论坛帖评论区反馈即可,我们会及时响应处理,谢谢!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值