Mininet、ODL、OpenFlow实验笔记

SDN在线比赛平台出题记录

Posted by chochi on March 22, 2018

1 基础配置

1.1 协议版本支持问题,修改协议为OpenFlow13

  • Mininet启动1.3版本OF
sudo mn --topo [topo] --mac --controller remote ,protocols=OpenFlow13
  • 从以上可知,启动1.3版本的命令是protocols=OpenFlow13,但是这只是启动了mininet的1.3版本,还需要对交换机进行配置。命令如下:
ovs-vsctl set bridge [bridge-name] protocols=OpenFlow13
  • 查看1.3版本的流表命令为:
sudo ovs-ofctl dump-flows [bridge-name] -O OpenFlow13

1.2 ODL控制器的启动权限

  • ODL、jdk安装的时候不要用sudo权限,不然会出错。
  • ovs 升级到2.8.1,mininet 2.3.0d, ODL 0.4.4 ,jdk 1u181

1.3 ODL控制器的流表与拓扑

  • 控制器会根据openflow协议自动下发ping通的流表。具体下发规则目前不知。
  • 对环形拓扑支持不友好,不能支持奇葩的拓扑显示,比如两台主机mac地址一样这样奇葩的拓扑,强行打开生成树协议down的路,会导致拓扑显示分离。
  • 流表有记忆性,对于同一个名字的交换机,下过的流表要自己删除掉,不然第二次做实验的时候ODL又会默认下发。
  • 在ovs下发的流表,ODL是识别不到的。只能通过终端查看。

2 OpenFlow 1.0&1.3 协议笔记

2.1 控制器与交换机的基本动作

  • openflow交换机与控制器建立“openflow通道”链接。
  • Proactive模式
    • 控制器想交换机预先发送流表项。
  • Reactive模式
    • 交换机接收到未知数据触发,通过Packer-in消息向控制器询问。

3 机制

3.1 流表和流表项

  • 从流表0开始匹配,当数据包与流表内设置的多条流表项匹配时,优先级最高为匹配的流表项结果,优先级相同,按照交换机的具体实现执行。
  • 每个流表至多的匹配结果为一个(即优先级最高的,具体是一个还是多个目前不清楚,1.0版本为一个),但数据包可以在各个流表中与流表项匹配,即可以与多个流表项匹配。 2018022

4 实验操作

4.1 OpenvSwitch flow

OVS 命令行工具

  • 在没有配置 OpenFlow 控制器的模式下,可以使用 ovs-ofctl 命令通过 OpenFlow 协议去连接 OVS,创建、修改或删除 OVS 中的流表项,并对 OVS 的运行状况进行动态监控。

ovs-ofctl流表操作命令

ovs-ofctl add−flow/add−flows/mod−flows “流表匹配条件,actions=[target][,target…]”

流表匹配条件

  • 在 OVS 中,流表项作为 ovs-ofctl 的参数,采用如下的格式:字段=值。如果有多个字段,可以用逗号或者空格分开 20180322-2

流表执行的动作

  • 流表可以有多个执行动作,是从左向右以此执行,常用动作如下:

  • 屏蔽某个IP

ovs-ofctl add-flow xenbr0 idle_timeout=0,dl_type=0x0800,nw_src=119.75.213.50,actions=drop
  • 数据包重定向
ovs-ofctl add-flow xenbr0 idle_timeout=0,dl_type=0x0800,nw_proto=1,actions=output:4
  • 去除VLAN tag
ovs-ofctl add-flow xenbr0 idle_timeout=0,in_port=3,actions=strip_vlan,normal
  • 更改数据包源IP地址后转发
ovs-ofctl add-flow xenbr0 idle_timeout=0,in_port=3,actions=mod_nw_src:211.68.52.32,normal

流表常用字段

  • in_port=port
    • 传递数据包的端口的 OpenFlow 端口编号
  • dl_vlan=vlan
    • 数据包的 VLAN Tag 值,范围是 0-4095,0xffff 代表不包含 VLAN Tag 的数据包
  • dl_src和dl_dst
    • 匹配源或者目标的 MAC 地址 01:00:00:00:00:00/01:00:00:00:00:00 代表广播地址 00:00:00:00:00:00/01:00:00:00:00:00 代表单播地址
  • dl_type=ethertype
    • dl_type=0x0800 IPv4 协议
    • dl_type=0x086dd IPv6 协议
    • dl_type=0x0806 ARP 协议
    • dl_type=0x88cc LLDP 协议
  • nw_src=ip[/netmask]和nw_dst=ip[/netmask]
    • 当 dl_typ=0x0800 时,匹配源或者目标的 IPv4 地址,可以使 IP 地址或者域名
  • nw_proto=proto
    • 和 dl_type 字段协同使用。当 dl_type=0x0800 时,匹配 IP 协议编号;当 dl_type=0x086dd 代表 IPv6 协议编号
  • table=number
    • 指定要使用的流表的编号,范围是0-254。在不指定的情况下,默认值为0。通过使用流表编号,可以创建或者修改多个 Table 中的 Flow
  • reg=value[/mask]
    • 交换机中的寄存器的值。当一个数据包进入交换机时,所有的寄存器都被清零,用户可以通过 Action 的指令修改寄存器中的值

常见的操作

  • output:port
    • 输出数据包到指定的端口。port 是指端口的 OpenFlow 端口编号
  • mod_vlan_vid
    • 修改数据包中的 VLAN tag
  • strip_vlan
    • 移除数据包中的 VLAN tag
  • mod_dl_src/ mod_dl_dest
    • 修改源或者目标的 MAC 地址信息
  • mod_nw_src/mod_nw_dst
    • 修改源或者目标的 IPv4 地址信息
  • resubmit:port
    • 替换流表的 in_port 字段,并重新进行匹配
  • load:value−>dst[start..end]
    • 写数据到指定的字段

5 Mininet 实验1:欺诈游戏

20180322-3

  • 拓扑信息如上图所示。
  • IP: h1:192.168.0.1 h2:192.168.0.2 h3:192.168.0.3
  • 做h1 ping h2操作时,要求重定向数据,实际为h3应答h1的请求。 20180322-4

  • 为了将题目简化,连上控制器pingall之后,控制器显示出完整的拓扑之后,将h3的ip改为:192.168.0.2
//Miniet CLI
py h3.setIP('192.168.0.2')

实验步骤

  • 使用脚本创建拓扑 (拓扑脚本命名 trip.py )
    #!/usr/bin/python
    # -*- coding: UTF-8 -*-
    from mininet.topo import Topo
    class MyTopo( Topo ):
      def __init__( self ):
          Topo.__init__( self )
          h1 = self.addHost('h1',ip='192.168.0.1')
          h2 = self.addHost('h2',ip='192.168.0.2')
          h3 = self.addHost('h3',ip='192.168.0.3')
          s1 = self.addSwitch('s1')
          s2 = self.addSwitch('s2')
          # Creating links between nodes in network
          self.addLink(h1, s1,0,1)
          self.addLink(h2, s2,0,1)
          self.addLink(h3, s2,0,3)
          self.addLink(s1, s2,2,2)
    topos = { 'mytopo': ( lambda: MyTopo() ) }
    

  • Ubuntu 终端执行自定义脚本并连接控制器
    sudo mn --custom trip.py --topo mytopo --mac --controller=remote,ip=[remote]:[port]
    

  • 新建一个终端修改交换机支持的协议版本
    #!/bin/bash
    sudo ovs-vsctl set bridge s1 protocols=OpenFlow13
    sudo ovs-vsctl set bridge s2 protocols=OpenFlow13
    

  • pingall之后查看h1的arp缓存
    mininet> h1 arp -a
    ? (192.168.0.2) 位于 00:00:00:00:00:02 [ether] 在 h1-eth0
    ? (192.168.0.3) 位于 00:00:00:00:00:03 [ether] 在 h1-eth0
    

  • 修改h3的ip
     py h3.setIP('192.168.0.2')
    

  • 查看s2的3口数据包,即s2和h3相连的端口
    • 虽然将h3的ip地址改为了192.168.0.2,但是开始pingal的时候h1已经有h2的mac地址,所以目标mac不匹配,h3不会回应。 20180323-1.png

  • 查看控制器的预发流表项。
    ➜  ~ sudo ovs-ofctl dump-flows -O OpenFlow13 s2
     cookie=0x2b00000000000006, duration=2237.164s, table=0, n_packets=448, n_bytes=38080, priority=100,dl_type=0x88cc actions=CONTROLLER:65535
     cookie=0x2b00000000000000, duration=2232.916s, table=0, n_packets=20, n_bytes=1512, priority=2,in_port="s2-eth3" actions=output:"s2-eth2",output:"s2-eth1",CONTROLLER:65535
     cookie=0x2b00000000000001, duration=2232.916s, table=0, n_packets=823, n_bytes=137858, priority=2,in_port="s2-eth2" actions=output:"s2-eth3",output:"s2-eth1"
     cookie=0x2b00000000000002, duration=2232.916s, table=0, n_packets=137, n_bytes=12642, priority=2,in_port="s2-eth1" actions=output:"s2-eth3",output:"s2-eth2",CONTROLLER:65535
     cookie=0x2b00000000000004, duration=2237.164s, table=0, n_packets=2, n_bytes=449, priority=0 actions=drop
    ➜  ~ 
    

  • 在s2交换机内,将所有符合我们匹配条件流的目的mac修改为h3的mac地址,并转发给3口
  • 同理添加一条处理回应 icmp_reply 的流表项
    sudo ovs-ofctl add-flow -O OpenFlow13 s2 priority=200,icmp,in_port=2,actions=mod_dl_dst=00:00:00:00:00:03,output=3
    sudo ovs-ofctl add-flow -O OpenFlow13 s2 priority=200,icmp,in_port=3,actions=mod_dl_src=00:00:00:00:00:02,output=2
    

  • 查看流表项是否下发成功
    ➜  ~ sudo ovs-ofctl dump-flows -O OpenFlow13 s2                                                                        
     cookie=0x0, duration=149.952s, table=0, n_packets=0, n_bytes=0, priority=200,icmp,in_port="s2-eth2" actions=set_field:00:00:00:00:00:03->eth_dst,output:"s2-eth3"
     cookie=0x0, duration=21.839s, table=0, n_packets=0, n_bytes=0, priority=200,icmp,in_port="s2-eth3" actions=set_field:00:00:00:00:00:02->eth_src,output:"s2-eth2"
     cookie=0x2b00000000000006, duration=2602.827s, table=0, n_packets=522, n_bytes=44370, priority=100,dl_type=0x88cc actions=CONTROLLER:65535
     cookie=0x2b00000000000000, duration=2598.579s, table=0, n_packets=20, n_bytes=1512, priority=2,in_port="s2-eth3" actions=output:"s2-eth2",output:"s2-eth1",CONTROLLER:65535
     cookie=0x2b00000000000001, duration=2598.579s, table=0, n_packets=946, n_bytes=161057, priority=2,in_port="s2-eth2" actions=output:"s2-eth3",output:"s2-eth1"
     cookie=0x2b00000000000002, duration=2598.579s, table=0, n_packets=137, n_bytes=12642, priority=2,in_port="s2-eth1" actions=output:"s2-eth3",output:"s2-eth2",CONTROLLER:65535
     cookie=0x2b00000000000004, duration=2602.827s, table=0, n_packets=2, n_bytes=449, priority=0 actions=drop
    ➜  ~ 
    

  • 使用wireshark抓包后,h1 ping h2 已经成功的转变为h1 ping h3了
  • 检查各个端口的数据包正确性 20180323-2.png 20180323-2.png

  • 检查h1的arp缓存没有被改变
    mininet> h1 arp -a
    ? (192.168.0.2) 位于 00:00:00:00:00:02 [ether] PERM 在 h1-eth0
    ? (192.168.0.3) 位于 00:00:00:00:00:03 [ether] 在 h1-eth0
    
  • 完成欺诈!

实验总结

  • 自己想的一个小实验,主要对MININET的练手,和匹配操作的一些概念。