这是基于RYU+Mininet的SDN架构设计仿真校园网络的第一部分

总体详见:【基本中型网络的仿真(RYU+Mininet的SDN架构)-以校园为例】​​​​​​

章节:

【RYU+Mininet的SDN架构-设计校园网络(一)】【RYU+Mininet的SDN架构-设计校园网络(二)】https://blog.csdn.net/weixin_53284122/article/details/129393371

【RYU+Mininet的SDN架构-设计校园网络(二)】

【RYU+Mininet的SDN架构-设计校园网络(三)】

【RYU+Mininet的SDN架构-设计校园网络(四)】

【RYU+Mininet的SDN架构-设计校园网络(五)】

 四、设计配置与实现

4.1 SDN设计配置与实现

SDN采用RYU控制器和mininet的方式,交换机采用的是openflow13协议。

  1. 配置

主要是涉及Mininet和RYU控制器的安装,一起路由定义软件Quagga的安装和配置。

详细的配置步骤在网络上都可以找到,在此不在叙述。

  1. 实现

第一步:打开RYU控制器,运行相应的程序(比如simple_switch_13.py默认路由,rest_firewall.py防火墙程序)

第二步:运行拓扑代码,连接到控制器

4.2 OSPF设计配置与实现

ospf采用quagga实现,需要对每个路由器配置相应的守护进程,在通过命令行开启ospf算法,最终实现路由的收敛。

(1)配置

1.在quagga安装目录里写配置文件

r1ospfd.conf(设置r1的直连网络)

hostname r1_ospfd

password 123

enable password 123

router ospf

  ospf router-id 192.168.3.2

  network 192.168.3.0/30 area 0

  network 192.168.3.4/30 area 0

  network 192.168.10.0/30 area 0

debug ospf event

log stdout

hostname r1_ospfd

password 123

enable password 123



router ospf

  ospf router-id 192.168.3.2

  network 192.168.3.0/30 area 0

  network 192.168.3.4/30 area 0

  network 192.168.10.0/30 area 0

debug ospf event

log stdout

r2ospfd.conf(设置r2的直连网络)

hostname r2_ospfd

password 123

enable password 123

router ospf

  ospf router-id 192.168.3.1

  network 192.168.1.0/24 area 0

  network 192.168.3.0/30 area 0

debug ospf event

log stdout

hostname r2_ospfd

password 123

enable password 123



router ospf

  ospf router-id 192.168.3.1

  network 192.168.1.0/24 area 0

  network 192.168.3.0/30 area 0

debug ospf event

log stdout

r3ospfd.conf(设置r3的直连网络)

hostname r3_ospfd

password 123

enable password 123

router ospf

  ospf router-id 192.168.3.6

  network 192.168.2.0/24 area 0

  network 192.168.3.4/30 area 0

debug ospf event

log stdout

hostname r3_ospfd

password 123

enable password 123



router ospf

  ospf router-id 192.168.3.6

  network 192.168.2.0/24 area 0

  network 192.168.3.4/30 area 0

debug ospf event

log stdout

r1zebra.conf、r2zebra.conf、r3zebra.conf 3个文件无需额外配置,直接复制示例模板即可。

2.命令行启动quagga及运行

命令行打开quagga软件,命令如下:

sudo zebra -d

软件打开后,在拓扑代码final.py中嵌入以下命令,运行ospf: 

r1.cmd('zebra -f /etc/quagga/r1zebra.conf -d -z /tmp/r1zebra.api -i /tmp/r1zebra.interface')

    r2.cmd('zebra -f /etc/quagga/r2zebra.conf -d -z /tmp/r2zebra.api -i /tmp/r2zebra.interface')

    r3.cmd('zebra -f /etc/quagga/r3zebra.conf -d -z /tmp/r3zebra.api -i /tmp/r3zebra.interface')

    time.sleep(1)  # time for zebra to create api socket

    r1.cmd('ospfd -f /etc/quagga/r1ospfd.conf -d -z /tmp/r1zebra.api -i /tmp/r1ospfd.interface')

    r2.cmd('ospfd -f /etc/quagga/r2ospfd.conf -d -z /tmp/r2zebra.api -i /tmp/r2ospfd.interface')

r3.cmd('ospfd -f /etc/quagga/r3ospfd.conf -d -z /tmp/r3zebra.api -i /tmp/r3ospfd.interface')

r1.cmd('zebra -f /etc/quagga/r1zebra.conf -d -z /tmp/r1zebra.api -i /tmp/r1zebra.interface')

r2.cmd('zebra -f /etc/quagga/r2zebra.conf -d -z /tmp/r2zebra.api -i /tmp/r2zebra.interface')

r3.cmd('zebra -f /etc/quagga/r3zebra.conf -d -z /tmp/r3zebra.api -i /tmp/r3zebra.interface')

time.sleep(1)  # time for zebra to create api socket

r1.cmd('ospfd -f /etc/quagga/r1ospfd.conf -d -z /tmp/r1zebra.api -i /tmp/r1ospfd.interface')

r2.cmd('ospfd -f /etc/quagga/r2ospfd.conf -d -z /tmp/r2zebra.api -i /tmp/r2ospfd.interface')

r3.cmd('ospfd -f /etc/quagga/r3ospfd.conf -d -z /tmp/r3zebra.api -i /tmp/r3ospfd.interface')

(2)实现

通过直接运行final.py文件

图4-1启动ospf操作示意图

4.3 STP设计配置与实现

Stp采用ryu控制器实现,通过设置可以处理的流表类型来允许处理BDPU包,从而开启stp,实现防止环路形成/链路恢复。

(1)配置

在ryu的模块simple_switch_13.py中配置

simple_switch_13.py

……

……

from ryu.lib import stplib #改变1:引入stplib,以支持STP协议

class SimpleSwitch13(app_manager.RyuApp):

    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

    _CONTEXTS = {'stplib': stplib.Stp} #改变2:指定STP协议参考类

……

……

    #@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)

    @set_ev_cls(stplib.EventPacketIn, MAIN_DISPATCHER)#改变3:将EventOFPPacketIn 换成EventPacketIn,后者封装了前者,且可以处理BDPU包

……

……

……

……

from ryu.lib import stplib #改变1:引入stplib,以支持STP协议



class SimpleSwitch13(app_manager.RyuApp):

    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

    _CONTEXTS = {'stplib': stplib.Stp} #改变2:指定STP协议参考类

……

……

    #@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)

    @set_ev_cls(stplib.EventPacketIn, MAIN_DISPATCHER)#改变3:将EventOFPPacketIn 换成EventPacketIn,后者封装了前者,且可以处理BDPU包

(2)实现

由于是直接在ryu控制器中进行设置,那么无需在拓扑代码中再进行设置,直接运行拓扑文件final.py文件即可。

图4-2启动stp操作示意图

4.4 DHCP设计配置与实现

DHCP采用的是下载额外的DHCP服务器,然后通过mininet自带的host.defaultIntf.updateIP()函数进行IP地址的更新。

  1. 配置

checkRequired()函数检查各项配置

def checkRequired():

    "Check for required executables"

    required = [ 'udhcpd', 'udhcpc', 'dnsmasq', 'curl', 'firefox' ]

    for r in required:

        if not quietRun( 'which ' + r ):

            print '* Installing', r

            print quietRun( 'apt-get install -y ' + r )

            if r == 'dnsmasq':

                print quietRun( 'update-rc.d dnsmasq disable' )

def checkRequired():

    "Check for required executables"

    required = [ 'udhcpd', 'udhcpc', 'dnsmasq', 'curl', 'firefox' ]

    for r in required:

        if not quietRun( 'which ' + r ):

            print '* Installing', r

            print quietRun( 'apt-get install -y ' + r )

            if r == 'dnsmasq':

                print quietRun( 'update-rc.d dnsmasq disable' )

(1)实现

主要流程如下图:

图4-3 DHCP运行流程图

下面介绍各个流程核心代码

地址池的设置(例子)

DNSTemplate = """

start #开始IP

end #结束IP

option subnet #子网掩码

option domain local

option lease 7  # seconds

"""

DNSTemplate = """

start #开始IP

end #结束IP

option subnet #子网掩码

option domain local

option lease 7  # seconds

"""

创建DHCP服务器.conf文件

def makeDHCPconfig( filename, intf, gw, dns ):

    "Create a DHCP configuration file"

    config = (

        'interface %s' % intf,

        DNSTemplate,

        'option router %s' % gw,

        'option dns %s' % dns,

        '' )

     with open( filename, 'w' ) as f:

        f.write( '\n'.join( config ) )

def makeDHCPconfig( filename, intf, gw, dns ):

    "Create a DHCP configuration file"

    config = (

        'interface %s' % intf,

        DNSTemplate,

        'option router %s' % gw,

        'option dns %s' % dns,

        '' )

     with open( filename, 'w' ) as f:

        f.write( '\n'.join( config ) )

启动DHCP服务器

def startDHCPserver( host, gw, dns ):

    "Start DHCP server on host with specified DNS server"

    info( '* Starting DHCP server on', host, 'at', host.IP(), '\n' )

    dhcpConfig = '/tmp/%s-udhcpd.conf' % host

    makeDHCPconfig( dhcpConfig, host.defaultIntf(), gw, dns )

    host.cmd( 'udhcpd -f', dhcpConfig,

              '1>/tmp/%s-dhcp.log 2>&1  &' % host )

def startDHCPserver( host, gw, dns ):

    "Start DHCP server on host with specified DNS server"

    info( '* Starting DHCP server on', host, 'at', host.IP(), '\n' )

    dhcpConfig = '/tmp/%s-udhcpd.conf' % host

    makeDHCPconfig( dhcpConfig, host.defaultIntf(), gw, dns )

    host.cmd( 'udhcpd -f', dhcpConfig,

              '1>/tmp/%s-dhcp.log 2>&1  &' % host )

启动请求方,并创建.log文件

def startDHCPclient( host ):

    "Start DHCP client on host"

    intf = host.defaultIntf()

    host.cmd( 'dhclient -v -d -r', intf )

host.cmd( 'dhclient -v -d 1> /tmp/dhclient.log 2>&1', intf, '&' )

def startDHCPclient( host ):

    "Start DHCP client on host"

    intf = host.defaultIntf()

    host.cmd( 'dhclient -v -d -r', intf )

host.cmd( 'dhclient -v -d 1> /tmp/dhclient.log 2>&1', intf, '&' )

请求方等待IP地址,若失败则进行重复请求

def waitForIP( host ):

    "Wait for an IP address"

    info( '*', host, 'waiting for IP address' )

    while True:

        host.defaultIntf().updateIP()

        if host.IP():

            break

        info( '.' )

        sleep( 1 )

    info( '\n' )

至此,DHCP分配结束。

def waitForIP( host ):

    "Wait for an IP address"

    info( '*', host, 'waiting for IP address' )

    while True:

        host.defaultIntf().updateIP()

        if host.IP():

            break

        info( '.' )

        sleep( 1 )

    info( '\n' )

4.5 NAT配置与实现

NAPT的配置在拓扑代码里实现。通过以下代码在拓扑中加入NAT节点。

NAT节点添加代码

nat0 = self.addNode('nat0', cls=NAT, ip='192.168.10.1/30', subnet='192.168.0.0/16', inNamespace=False)

其中subnet属性用于配置nat节点所负责的子网范围,只有处于subnet内的主机通信时,nat节点才会为其提供转换。

之后我们还要为所有节点配置默认路由,并为nat节点配置路由使得外面发送的信息能够成功传入Mininet内。

默认路由配置代码

r1.cmd('route add default gw 192.168.10.1 dev r1-eth3')

r2.cmd('route add default gw 192.168.3.2 dev r2-eth1')

r3.cmd('route add default gw 192.168.3.5 dev r3-eth1')

nat0.cmd('route add -net 192.168.0.0/16 gw 192.168.10.2 dev nat0-eth1')

r1.cmd('route add default gw 192.168.10.1 dev r1-eth3')

r2.cmd('route add default gw 192.168.3.2 dev r2-eth1')

r3.cmd('route add default gw 192.168.3.5 dev r3-eth1')

nat0.cmd('route add -net 192.168.0.0/16 gw 192.168.10.2 dev nat0-eth1')

通过以上配置之后,Mininet内的主机便可以与外界主机通信了。

4.6防火墙配置与实现

防火墙采用的是RYU控制器,通过在RYU控制器中的防火墙程序(rest_firewall.py)文件进行实现。

(1)配置

1.通过编写代码设置防火墙规则

Firewall.py(实现防火墙的过滤规则)

import requests

data1='{"nw_src":"192.168.1.1","nw_dst":"192.168.2.1"}'

data2='{"nw_src":"192.168.2.1","nw_dst":"192.168.1.1"}'

data3='{"nw_src":"192.168.2.2","nw_dst":"192.168.1.1"}'

data4='{"nw_src":"192.168.1.1","nw_dst":"192.168.2.2"}'

def firewall():

    # set rules for switch by ryu/ryu.app/rest_firewall.py

    # data1-data4 is the rule by myself)

    response = requests.put('http://localhost:8080/firewall/module/enable/0000

000000000004')

    response=

requests.post('http://127.0.0.1:8080/firewall/rules/0000000000000004',

data=data1)

    response = requests.post('http://127.0.0.1:8080/firewall/rules/0000000000000004', data=data2)

    response = requests.post('http://127.0.0.1:8080/firewall/rules/0000000000000004', data=data3)

    response = requests.post('http://127.0.0.1:8080/firewall/rules/0000000000000004', data=data4)

firewall()

import requests

data1='{"nw_src":"192.168.1.1","nw_dst":"192.168.2.1"}'

data2='{"nw_src":"192.168.2.1","nw_dst":"192.168.1.1"}'

data3='{"nw_src":"192.168.2.2","nw_dst":"192.168.1.1"}'

data4='{"nw_src":"192.168.1.1","nw_dst":"192.168.2.2"}'

def firewall():

    # set rules for switch by ryu/ryu.app/rest_firewall.py

    # data1-data4 is the rule by myself)

    response = requests.put('http://localhost:8080/firewall/module/enable/0000

000000000004')

    response=

requests.post('http://127.0.0.1:8080/firewall/rules/0000000000000004',

data=data1)

    response = requests.post('http://127.0.0.1:8080/firewall/rules/0000000000000004', data=data2)

    response = requests.post('http://127.0.0.1:8080/firewall/rules/0000000000000004', data=data3)

    response = requests.post('http://127.0.0.1:8080/firewall/rules/0000000000000004', data=data4)

 

firewall()

2.命令行设置防火墙规则

命令行打开S4,设置为可以enable状态,配置命令如下:

curl -X PUT  http://localhost:8080/firewall/module/enable/0000000000000004

之后在enable状态下,在链接到RYU控制器后台设置防火墙的过滤规则。

curl -X POST -d '{"nw_src":"192.168.2.1/32","nw_dst":"192.168.1.1/32"}' http://127.0.0.1:8080/firewall/rules/0000000000000004

curl -X POST -d '{"nw_src":"192.168.1.1/32","nw_dst":"192.168.2.1/32"}' http://127.0.0.1:8080/firewall/rules/0000000000000004

(2)实现

1)启动控制器C1的终端,启动RYU控制器的防火墙程序

图4-4 启动防火墙操作示意图

  1. 通过直接运行firewall.py文件或者命令行方式设置防火墙过滤的规则

图4-5 启动设置防火墙规则操作示意图

4.7 WIFI配置与实现

WLAN部分的实现以代码为主,以下展示具体的实现思路和核心代码。

(1)设置网络类型为Mininet-WiFi,并配置控制器

设置网络类型为Mininet-WiFi,并配置控制器

net = Mininet_wifi(topo=None,

       build=False,

       link=wmediumd ,

       wmediumd_mode=interference)

info('***Adding controllerln ' )

c1= net.addController( name= 'c1 ',controller=Controller, protocol= 'tcp ' ,port=6653)

net = Mininet_wifi(topo=None,

       build=False,

       link=wmediumd ,

       wmediumd_mode=interference)

info('***Adding controllerln ' )

c1= net.addController( name= 'c1 ',controller=Controller, protocol= 'tcp ' ,port=6653)

(2)配置AP的名称、MAC地址、SSID、信道编号、加密方式、密码和物理位置。

配置AP(以AP1为例)

ap1 = net.addAccessPoint( 'ap1', mac='00:00:00:00:00:01', ssid="handover",mode="g", channel="1", passwd= '123456789a',encrypt='wpa2', position='123.0,323.0,0')

ap1 = net.addAccessPoint( 'ap1', mac='00:00:00:00:00:01', ssid="handover",mode="g", channel="1", passwd= '1234567

(3)配置站点的名称、IP地址、物理位置、扫描信号强度门限、短间隔、长间隔和扫描模式。

配置站点(以sta1为例)

sta1 = net.addStation( 'sta1', ip= '192.168.4.1/24',position= '54.0,434.0,0 ', bgscan_threshold=-60,s_inverval=5, l_interval=10,bgscan_module="simpie")

(4)设置无线信号的指数传播模型

设置无线信号的指数传播模型

net.setPropagationModel( model="logDistance" , exp=3)

4.8虚拟机隧道配置与实现

为了实现两个Mininet网络的互连,我们首先需要在两个Ubuntu虚拟机上各再创建一张新的网卡。创建新网卡后,需要将新添加的网卡与Open vSwitch交换机端口绑定。具体实现过程如下:

①在两个Ubuntu虚拟机上各再创建一张新的网卡。添加新的虚拟机网卡需要在VMware Player中设置,如图。

图4-6 创建一张新的网卡

②进入虚拟机,释放新添加的虚拟机网卡。使用的具体命令如图。

图4-7 释放虚拟机网卡使用的命令

③然后将两台虚拟机中新创建的虚拟网卡绑定到同一VMnet网卡上(即下图的VMnet0),并且需要将对应VMnet设置成桥接模式。

图4-8 虚拟机网卡配置

从上图可以看出,VMnet0网卡桥接到了物理主机的无线网卡(Microsoft-WiFi Direct Virtual Adapter)上,因此,我们可以画出如下的设备连接逻辑图。

图4-9 占用网卡后的无线网网络拓扑

④将OVS交换机端口与刚释放出来的虚拟网卡相绑定。使用的代码如下:

代码-将OVS交换机端口与刚释放出来的虚拟网卡相绑定

import os

……

os. popen( 'ovs-vsctl add-port s1 ens34 ')

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐