​ QoS差异化服务是这次实训的最后一个项目,也是难度较大的一个项目。7.10创建的博客一直被搁置,今天最后答辩结束了,简单记录一下学习过程(๑•̀ㅂ•́)و✧

0x01 基础知识

​ 实际生活中,数据包的价值是不同的,分分钟上千万项目的数据包和在线观看娱乐视频的数据包的价值孰轻孰重,不言而喻,所以会优先传输价值大的数据包(价值这一定义,由用户决定)。基于SDN的QoS差异化服务,说直白点就是对用户发来的数据包做传输速度的限制。是有限的带宽价值创造更多的财富。

​ 在SDN的环境中,利用Meter表可以实现这一功能。Meter表是OpenFlow 1.3中使用的。因此这次实验需要支持的OpenFlow 1.3的交换机,然而自己之前安装的OVS版本不支持,所以这次需要安装Openvswitch 2.8.1及其以上。

0x02 实验环境

​ 由于某些众所周知的原因,导致升级Openvswitch很容易失败。这里是Openvswitch 2.8.1的下载链接:https://github.com/lowbee2019/Files/blob/master/openvswitch-2.8.1.tar.gz,其实安装命令很简单,切换到mininet/util 下执行 ./install.sh -V 2.8.1,但是你可能会遇到下面的情况:

最终显示Failed to find OVS at http://openvswitch.org/releases/openvswitch-2.8.1.tar.gz

这时候就需要人为助力:首先要明白install.sh文件本质是一系列的shell命令构成的,因此打开install.sh找到相关的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# Install Open vSwitch specific version Ubuntu package
function ubuntuOvs {
echo "Creating and Installing Open vSwitch packages..."

OVS_SRC=$BUILD_DIR/openvswitch
OVS_TARBALL_LOC=http://openvswitch.org/releases

if ! echo "$DIST" | egrep "Ubuntu|Debian" > /dev/null; then
echo "OS must be Ubuntu or Debian"
$cd BUILD_DIR
return
fi
if [ "$DIST" = "Ubuntu" ] && ! version_ge $RELEASE 12.04; then
echo "Ubuntu version must be >= 12.04"
cd $BUILD_DIR
return
fi
if [ "$DIST" = "Debian" ] && ! version_ge $RELEASE 7.0; then
echo "Debian version must be >= 7.0"
cd $BUILD_DIR
return
fi

rm -rf $OVS_SRC
mkdir -p $OVS_SRC
cd $OVS_SRC

if wget $OVS_TARBALL_LOC/openvswitch-$OVS_RELEASE.tar.gz 2> /dev/null; then
tar xzf openvswitch-$OVS_RELEASE.tar.gz
else
echo "Failed to find OVS at $OVS_TARBALL_LOC/openvswitch-$OVS_RELEASE.tar.gz"
cd $BUILD_DIR
return
fi

# Remove any old packages

$remove openvswitch-common openvswitch-datapath-dkms openvswitch-pki openvswitch-switch \
openvswitch-controller || true

# Get build deps
$install build-essential fakeroot debhelper autoconf automake libssl-dev \
pkg-config bzip2 openssl python-all procps python-qt4 \
python-zopeinterface python-twisted-conch dkms dh-python dh-autoreconf \
uuid-runtime

# Build OVS
parallel=`grep processor /proc/cpuinfo | wc -l`
cd $BUILD_DIR/openvswitch/openvswitch-$OVS_RELEASE
DEB_BUILD_OPTIONS='parallel=$parallel nocheck' fakeroot debian/rules binary
cd ..
for pkg in common datapath-dkms pki switch; do
pkg=openvswitch-${pkg}_$OVS_RELEASE*.deb
echo "Installing $pkg"
$pkginst $pkg
done
if $pkginst openvswitch-controller_$OVS_RELEASE*.deb 2>/dev/null; then
echo "Ignoring error installing openvswitch-controller"
fi

/sbin/modinfo openvswitch
sudo ovs-vsctl show
# Switch can run on its own, but
# Mininet should control the controller
# This appears to only be an issue on Ubuntu/Debian
if sudo service openvswitch-controller stop 2>/dev/null; then
echo "Stopped running controller"
fi
if [ -e /etc/init.d/openvswitch-controller ]; then
sudo update-rc.d openvswitch-controller disable
fi
}

知道是下载失败后,所以我们可以通过别的路径进行下载,为它准备好材料后,再让它工作:

  • 下载好需要的版本
  • 将下载后的文件解压到与mininet同级目录的openvswitch文件夹下
  • 注释install.sh中不必要指令
  • 再次执行./install.sh -V 2.8.1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# Install Open vSwitch specific version Ubuntu package
function ubuntuOvs {
echo "Creating and Installing Open vSwitch packages..."

OVS_SRC=$BUILD_DIR/openvswitch
cd $OVS_SRC
# Remove any old packages

$remove openvswitch-common openvswitch-datapath-dkms openvswitch-pki openvswitch-switch \
openvswitch-controller || true

# Get build deps
$install build-essential fakeroot debhelper autoconf automake libssl-dev \
pkg-config bzip2 openssl python-all procps python-qt4 \
python-zopeinterface python-twisted-conch dkms dh-python dh-autoreconf \
uuid-runtime

# Build OVS
parallel=`grep processor /proc/cpuinfo | wc -l`
cd $BUILD_DIR/openvswitch/openvswitch-$OVS_RELEASE
DEB_BUILD_OPTIONS='parallel=$parallel nocheck' fakeroot debian/rules binary
cd ..
for pkg in common datapath-dkms pki switch; do
pkg=openvswitch-${pkg}_$OVS_RELEASE*.deb
echo "Installing $pkg"
$pkginst $pkg
done
if $pkginst openvswitch-controller_$OVS_RELEASE*.deb 2>/dev/null; then
echo "Ignoring error installing openvswitch-controller"
fi

/sbin/modinfo openvswitch
sudo ovs-vsctl show
# Switch can run on its own, but
# Mininet should control the controller
# This appears to only be an issue on Ubuntu/Debian
if sudo service openvswitch-controller stop 2>/dev/null; then
echo "Stopped running controller"
fi
if [ -e /etc/init.d/openvswitch-controller ]; then
sudo update-rc.d openvswitch-controller disable
fi
}

到最后可能会遇到这样的错误:

解决办法如下:

1
2
3
4
5
6
7
8
root@SDN:/home/low/mininet-wifi/mininet/util# cd ../../openvswitch/
root@SDN:/home/low/mininet-wifi/mininet/util# dpkg -i *.deb
...
root@SDN:/home/low/mininet-wifi/mininet/util# service openvswitch-switch start
root@SDN:/home/low/mininet-wifi/mininet/util# ovs-vsctl --version
ovs-vsctl (Open vSwitch) 2.8.1
DB Schema 7.15.0

此时ovs-vsctl版本已经升级成功!

0x03 拓扑创建

​ 在使用Openflow 1.3 时,需要将OVS交换机切换到用户态并指定协议版本:

1
2
ovs-vsctl set bridge s1 datapath_type=netdev
ovs-vsctl set bridge s1 protocols=OpenFlow13

当然也可以在Python脚本中指定协议版本和切换用户态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from mininet.net import Mininet
from mininet.cli import CLI
from mininet.node import RemoteController,Controller
from mininet.log import info
import sys
import os
import time


if len(sys.argv) == 1:
controller_ip = '127.0.0.1'
else:
controller_ip = sys.argv[1]
net = Mininet(controller=RemoteController)
odl_controller=net.addController('ODL_controller',ip=controller_ip,port=6653)
print(controller_ip)
print("*** Add Switch")
print("s1")
s1=net.addSwitch('s1')
print("*** Add Hosts")
h1=net.addHost('h1')
h2=net.addHost('h2')
print("h1 h2")
net.addLink(s1,h1)
net.addLink(s1,h2)


h1.setIP('10.0.0.2',24)
h2.setIP('10.0.0.3',24)

net.start()
# time.sleep(2)
print("*** set bridge s1 work moudle")
os.system("ovs-vsctl set bridge s1 datapath_type=netdev")
os.system("ovs-vsctl set bridge s1 protocols=OpenFlow13")
CLI(net)

0x04 项目展示

​ 此项目和上一个项目所用的环境大致相同,且前端应用的功能也包含上一个项目的大致内容,这两个项目的相似度大约80%,所以这是是在上个项目的基础上进行扩展的。下面只简述添加内容:

  • 添加Meter表的下发、管理、删除等功能
  • 为流表下发提供功能选择:
    • Drop:直接丢弃数据包
    • Meter:设置网速限制,选定指定的Meter表

Meter表下发:

流表下发:通过action选项的选择实现与上一个项目的合并(๑•̀ㅂ•́)و✧

演示

  • 没有限速前:

  • 下发流表:

  • 重新测试:

  • 下放优先级更高的Drop流表,禁止iperf的TCP打流:禁用目的端口为5001

  • 重新进行打流测试:测试不同

0x05 踩坑记录

​ 最后我们实现的是将上一个项目和这个项目集成到一个WebApp中,简述一下自己的踩坑记录,这天debug心态都要崩溃了,还是自己太菜了:-)

  • OVS版本要升级至2.8.1及其以上

  • 创建Mininet拓扑时,要切换用户态,指定OpenFlow 1.3 协议

  • Meter表不能直接覆盖,同一meter_id的Meter表需要先删除,后下发才能成功

  • 由于Meter表不能被覆盖、不能一次性查询、且meter_id是用户自定义,所以需要下发时记录Meter表的信息,以供前端显示和流表下发使用

  • 可以用Django的Sqlite3数据库存储Meter表信息

  • 对于meter表:本文采取的meter-band-typeofpmbt-drop方式,因此,真正的限流字段是 drop-burst-sizedrop-rate

  • 通过命令行手动下发的流表,ODL只能获取流表存在,但不知流表的详细信息

  • 对于转发端口 Output字段还没找到ALL,FLOOD等值的正确用法;只能换思路:在获取拓扑结构时,就记录IP地址与物理接口的对应关系(由于本文采取的是四层流表的匹配,因此记录IP-Port的关系,也可以根据需求记录MAC-Port的关系)

  • 在使用iperf打流时,需要注意关闭网卡的tx校验,且connection的源端口会自动变化

    关闭方式:ethtool -K enp0s5 tx off其中enp0s5是ifconfig显示的网卡名,虚拟机和Mininet主机都要关闭

每个坑都是亲身经历的…希望以后对自己有点帮助。

0x06 心得

​ 通过这十五天的实训,让SDN的身影逐渐清晰起来,算是对SDN简单的入门了。感谢指导老师这15天的教导,感谢大佬Steve·Curcy的合作,实训就算告一段落了,收获不少较为满意(๑•̀ㅂ•́)و✧
​ 马上就是新的开始了,学无止境(๑•̀ㅂ•́)و✧