CentOS on Mac#5.OpenVSwitch+mininet

OpenVSwitch

任务:
1.源码安装ovs
2.写基本的openflow条目控制网络包转发方向
3.minine环境下设计应用ovs

OpenVSwitch安装

Linux内核支持到4.1.25。
之前安装的是4.6.4
所以用系统原本的3.10.0

天才第一步:先好好看源码包里的README

下载源码

1
wget http://openvswitch.org/releases/openvswitch-2.0.1.tar.gz

这里写图片描述
!!注意!!下载前一定要了解自己内核支持的版本,这个在readme里都有写,切勿一味追求latest version

比如

ovs版本|系统内核
2.0.x | 2.6.32 to 3.10

解压

tar zxvf openvswitch-2.0.1.tar.gz

这里写图片描述

前期准备
1.确保OVS正确运行的环境依赖,切换至root用户

1
2
3
yum update
yum install -y build-essential (有则忽略)
yum -y install openssl-devel wget kernel-devel

这里写图片描述

这里写图片描述
要求如下(可以通过xxx –version)查询

gcc版本4.1或更高
pkg-config版本0.22或更高
autoconf版本2.64或更高
automake版本1.10或更高
m4版本1.42或更高
python2.X ,X>4(不建议用python3.0以上的版本)

这里写图片描述

这里写图片描述

构建基于Linux内核的交换机

cd openvswitch-2.0.1

./boot.sh

这里写图片描述
开始用了不匹配的2.5.0,不过这里结果基本一致,是在make时候出错的

make clean

./configure --with-linux=/lib/modules/uname -r/build
这里写图片描述
内核版本

编译并安装OVS 2.3.0

1
make

//make没有这么快的

这里写图片描述

1
make install

install要用root权限 su
这里写图片描述

这里写图片描述

install 不通过 安装autoconf 和autonmake libtool rpm-build m4

安装并加载构建的内核模块

1
2
make modules_install
/sbin/modprobe openvswitch

使用ovsdb工具初始化配置数据库

1
2
mkdir -p /usr/local/etc/openvswitch
ovsdb-tool create /usr/local/etc/openvswitch/conf.db vswitchd/vswitch.ovsschema

这里写图片描述

启动配置数据库

1
2
3
4
5
6
ovsdb-server --remote=punix:/usr/local/var/run/openvswitch/db.sock \
--remote=db:Open_vSwitch,Open_vSwitch,manager_options \
--private-key=db:Open_vSwitch,SSL,private_key \
--certificate=db:Open_vSwitch,SSL,certificate \
--bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \
--pidfile —detach

这里写图片描述

初始化数据库

1
ovs-vsctl --no-wait init

启动主进程

1
ovs-vswitchd --pidfile —detach

查看OVS进程是否启动

1
ps aux|grep ovs

这里写图片描述

ovs应用

例子:新建网桥br0并加入端口

1
2
3
ovs-vsctl add-br br0
ovs-vsctl add-port br0 eth0
ovs-vsctl add-port br0 vif1.0

这里写图片描述

应用场景:
1.常用:如删除网桥br0上挂接的eth0网络接口

1
ovs-vsctl del-port br0 eth0

这里写图片描述

2.新建网桥加入端口

1
2
3
ovs-vsctl add-br ovs-switch
ovs-vsctl add-port ovs-switch eth0 //port4

自定义

1
2
3
ovs-vsctl add-port ovs-switch p1 -- set Interface p1 ofport_request=101
ovs-vsctl add-port ovs-switch p2 -- set Interface p2 ofport_request=102
ovs-vsctl add-port ovs-switch p3 -- set Interface p3 ofport_request=103

对于 internal 类型的的网络接口,OVS 会在 Linux 系统中创建一个可以用来收发数据的模拟网络设备。我们可以为这个网络设备配置 IP 地址、进行数据监听。

1
2
3
4
5
6
ovs-vsctl set Interface p1 type=internal
ovs-vsctl set Interface p1 type=internal
ovs-vsctl set Interface p3 type=internal
ethtool -i p2
ethtool -i p2
ethtool -i p3

这里写图片描述

3.创建虚拟网络空间
为了避免网络接口上的地址和本机已有网络地址冲突,创建一个虚拟网络空间 ns1,把 p1 接口移入网络空间 ns1,并配置 IP 地址为 192.168.1.101,另外两个同理

1
2
3
4
ip netns add ns1
ip link set p1 netns ns1
ip netns exec ns1 ip addr add 192.168.1.101/24 dev p1
ip netns exec ns1 ifconfig p1 promisc up

这里写图片描述

4.查看 OVS 交换机的信息

1
ovs-vsctl show

查看 Open vSwitch 中的端口信息,获得交换机对应的 datapath ID (dpid),以及每个端口的 OpenFlow 端口编号,端口名称,当前状态。
这里写图片描述

1
ovs-ofctl show ovs-switch

这里写图片描述
5.运行查看

1
ovs-appctl fdb/show ovs-switch

这里写图片描述

查看交换机所有table

1
ovs-ofctl dump-tables ovs-switch

这里写图片描述
查看交换机中的所有流表项

1
2
ovs−ofctl dump−flows ovs-switch

这里写图片描述
6.屏蔽数据包
(1)屏蔽 STP 协议的广播数据包

1
ovs-ofctl add-flow ovs-switch "table=0, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"

(2)屏蔽所有进入 OVS 的以太网广播数据包

1
$ ovs-ofctl add-flow ovs-switch "table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop"

7.修改数据包
(1)添加新的 OpenFlow 条目,修改从端口 p1 收到的数据包的源地址为 9.181.137.1

1
2
ovs-ofctl add-flow ovs-switch "priority=1 idle_timeout=0,\
in_port=101,actions=mod_nw_src:9.181.137.1,normal"

(2)从端口 p1(192.168.1.101)发送测试数据到端口 p3(192.168.1.103)

1
ip netns exec ns1 ping 192.168.1.103

这里写图片描述

(3)再打开一个ssh终端运行tcpdump
在接收端口 p3 监控数据

1
ip netns exec ns3 tcpdump -i p3 icmp

这里写图片描述

8.重定向数据包
添加新的 OpenFlow 条目,重定向所有的 ICMP 数据包到端口 p2

1
ovs-ofctl add-flow ovs-switch idle_timeout=0,dl_type=0x0800,nw_proto=1,actions=output:102

这里写图片描述

从端口 p1 (192.168.1.101)发送数据到端口 p3(192.168.1.103)

1
ip netns exec ns1 ping 192.168.1.103

这里写图片描述
在端口 p2 上监控数据,发现数据包已被转发到端口 p2

1
2
ip netns exec ns3 tcpdump -i p2 icmp

这里写图片描述
取代make的rpm-build

因为前面的make经常出错,我在网上找到了rpm-build的方法。最终没有按照这个方法,但也顺带了解了rpm-build

1
//创建编译目录:mkdir -p ~/rpmbuild/SOURCES

这里写图片描述

1
2
3
4
5
# cp ../openvswitch-2.5.0.tar.gz ~/rpmbuild/SOURCES/ //复制文件目录
# cp rhel/openvswitch-kmod.files ~/rpmbuild/SOURCES/
# cp rhel/openvswitch.spec ~/rpmbuild/SPECS/
# rpmbuild -ba ~/rpmbuild/SPECS/openvswitch.spec rpmbuild则是用来将源代码打包成.rpm格式的工具。-ba 编译后做成*.rpm和src.rpm
#cp rhel/openvswitch-kmod-rhel6.spec ~/rpmbuild/SPECS/

这里写图片描述

#mininet
安装mininet模拟环境
www.mininet.org
源码安装

1
2
3
4
git clone git://github.com/mininet/mininet
cd mininet/util/
./install.sh -a
ls

这里写图片描述

这里写图片描述

应用场景设置

Stochastic Switching using Open vSwitch in Mininet
随机交换模型(参考github)

1.修改select group type,修改程序
/home/parallels/openvswitch-2.0.1/ofproto/ofproto-dpif-xlate.c中
加入头文件

1
2
#include <stdlib.h>
#include <time.h>

添加全局变量

1
static bool is_srand_initialized = false;

修改函数(注意要在程序前面加上函数调用

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
static void
xlate_select_group(struct xlate_ctx *ctx, struct group_dpif *group)
{
struct flow_wildcards *wc = &ctx->xout->wc;
const struct ofputil_bucket *bucket;
uint32_t basis;
// The following tells the caching code that every packet in
// the flow in question must go to the userspace "slow path".
ctx->xout->slow |= SLOW_CONTROLLER;
basis = hash_bytes(ctx->xin->flow.dl_dst, sizeof ctx->xin->flow.dl_dst, 0);
bucket = group_best_live_bucket(ctx, group, basis);
if (bucket) {
memset(&wc->masks.dl_dst, 0xff, sizeof wc->masks.dl_dst);
xlate_group_bucket(ctx, bucket);
}
}
static const struct ofputil_bucket *
group_best_live_bucket(const struct xlate_ctx *ctx,
const struct group_dpif *group,
uint32_t basis) // basis in not being used
{
uint32_t rand_num = 0, sum = 0;
const struct ofputil_bucket *bucket = NULL;
const struct list *buckets;
// initialize random seed once
if (!is_srand_initialized) {
srand(time(NULL));
is_srand_initialized = true;
}
// generate a random number in [1, 10]
rand_num = (rand() % 10) + 1;
group_dpif_get_buckets(group, &buckets);
LIST_FOR_EACH (bucket, list_node, buckets) {
if (bucket_is_alive(ctx, bucket, 0)) {
sum += bucket->weight;
if (rand_num <= sum) {
return bucket; // return this bucket
}
}
}
return bucket; // return NULL
}

2.重置更新后的ovs(步骤基本同上

1
2
3
4
5
6
7
8
9
cd openvswitch-2.0.1/
./configure --prefix=/usr --with-linux=/lib/modules/`uname -r`/build
make
make install
make modules_install
//此处不同
rmmod openvswitch
depmod -a

3.运行ovs

1
/etc/init.d/openvswitch-switch start

4.mininet测试拓扑(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
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/usr/bin/python
"""Topology with 10 switches and 10 hosts
"""
from mininet.cli import CLI
from mininet.topo import Topo
from mininet.net import Mininet
from mininet.link import TCLink
from mininet.log import setLogLevel
class CSLRTopo( Topo ):
def __init__( self ):
"Create Topology"
# Initialize topology
Topo.__init__( self )
# Add hosts
h0 = self.addHost( 'h0' )
h1 = self.addHost( 'h1' )
h2 = self.addHost( 'h2' )
h3 = self.addHost( 'h3' )
h4 = self.addHost( 'h4' )
h5 = self.addHost( 'h5' )
h6 = self.addHost( 'h6' )
h7 = self.addHost( 'h7' )
h8 = self.addHost( 'h8' )
h9 = self.addHost( 'h9' )
# Add switches
s0 = self.addSwitch( 's0', listenPort=6634 )
s1 = self.addSwitch( 's1', listenPort=6635 )
s2 = self.addSwitch( 's2', listenPort=6636 )
s3 = self.addSwitch( 's3', listenPort=6637 )
s4 = self.addSwitch( 's4', listenPort=6638 )
s5 = self.addSwitch( 's5', listenPort=6639 )
s6 = self.addSwitch( 's6', listenPort=6640 )
s7 = self.addSwitch( 's7', listenPort=6641 )
s8 = self.addSwitch( 's8', listenPort=6642 )
s9 = self.addSwitch( 's9', listenPort=6643 )
# Add links between hosts and switches
self.addLink( h0, s0 ) # h0-eth0 <-> s0-eth1
self.addLink( h1, s1 ) # h1-eth0 <-> s1-eth1
self.addLink( h2, s2 ) # h2-eth0 <-> s2-eth1
self.addLink( h3, s3 ) # h3-eth0 <-> s3-eth1
self.addLink( h4, s4 ) # h4-eth0 <-> s4-eth1
self.addLink( h5, s5 ) # h5-eth0 <-> s5-eth1
self.addLink( h6, s6 ) # h6-eth0 <-> s6-eth1
self.addLink( h7, s7 ) # h7-eth0 <-> s7-eth1
self.addLink( h8, s8 ) # h8-eth0 <-> s8-eth1
self.addLink( h9, s9 ) # h9-eth0 <-> s9-eth1
# Add links between switches, with bandwidth 100Mbps
self.addLink( s0, s1, bw=100 ) # s0-eth2 <-> s1-eth2, Bandwidth = 100Mbps
self.addLink( s0, s2, bw=100 ) # s0-eth3 <-> s2-eth2, Bandwidth = 100Mbps
self.addLink( s1, s2, bw=100 ) # s1-eth3 <-> s2-eth3, Bandwidth = 100Mbps
self.addLink( s2, s3, bw=100 ) # s2-eth4 <-> s3-eth2, Bandwidth = 100Mbps
self.addLink( s3, s4, bw=100 ) # s3-eth3 <-> s4-eth2, Bandwidth = 100Mbps
self.addLink( s3, s6, bw=100 ) # s3-eth4 <-> s6-eth2, Bandwidth = 100Mbps
self.addLink( s4, s5, bw=100 ) # s4-eth3 <-> s5-eth2, Bandwidth = 100Mbps
self.addLink( s5, s7, bw=100 ) # s5-eth3 <-> s7-eth2, Bandwidth = 100Mbps
self.addLink( s6, s7, bw=100 ) # s6-eth3 <-> s7-eth3, Bandwidth = 100Mbps
self.addLink( s7, s8, bw=100 ) # s7-eth4 <-> s8-eth2, Bandwidth = 100Mbps
self.addLink( s7, s9, bw=100 ) # s7-eth5 <-> s9-eth2, Bandwidth = 100Mbps
self.addLink( s8, s9, bw=100 ) # s8-eth3 <-> s9-eth3, Bandwidth = 100Mbps
def run():
"Create and configure network"
topo = CSLRTopo()
net = Mininet( topo=topo, link=TCLink, controller=None )
# Set interface IP and MAC addresses for hosts
h0 = net.get( 'h0' )
h0.intf( 'h0-eth0' ).setIP( '10.0.0.2', 24 )
h0.intf( 'h0-eth0' ).setMAC( '0A:00:00:02:00:00' )
h1 = net.get( 'h1' )
h1.intf( 'h1-eth0' ).setIP( '10.0.1.2', 24 )
h1.intf( 'h1-eth0' ).setMAC( '0A:00:01:02:00:00' )
h2 = net.get( 'h2' )
h2.intf( 'h2-eth0' ).setIP( '10.0.2.2', 24 )
h2.intf( 'h2-eth0' ).setMAC( '0A:00:02:02:00:00' )
h3 = net.get( 'h3' )
h3.intf( 'h3-eth0' ).setIP( '10.0.3.2', 24 )
h3.intf( 'h3-eth0' ).setMAC( '0A:00:03:02:00:00' )
h4 = net.get( 'h4' )
h4.intf( 'h4-eth0' ).setIP( '10.0.4.2', 24 )
h4.intf( 'h4-eth0' ).setMAC( '0A:00:04:02:00:00' )
h5 = net.get( 'h5' )
h5.intf( 'h5-eth0' ).setIP( '10.0.5.2', 24 )
h5.intf( 'h5-eth0' ).setMAC( '0A:00:05:02:00:00' )
h6 = net.get( 'h6' )
h6.intf( 'h6-eth0' ).setIP( '10.0.6.2', 24 )
h6.intf( 'h6-eth0' ).setMAC( '0A:00:06:02:00:00' )
h7 = net.get( 'h7' )
h7.intf( 'h7-eth0' ).setIP( '10.0.7.2', 24 )
h7.intf( 'h7-eth0' ).setMAC( '0A:00:07:02:00:00' )
h8 = net.get( 'h8' )
h8.intf( 'h8-eth0' ).setIP( '10.0.8.2', 24 )
h8.intf( 'h8-eth0' ).setMAC( '0A:00:08:02:00:00' )
h9 = net.get( 'h9' )
h9.intf( 'h9-eth0' ).setIP( '10.0.9.2', 24 )
h9.intf( 'h9-eth0' ).setMAC( '0A:00:09:02:00:00' )
# Set interface MAC address for switches (NOTE: IP
# addresses are not assigned to switch interfaces)
s0 = net.get( 's0' )
s0.intf( 's0-eth1' ).setMAC( '0A:00:00:01:00:01' )
s0.intf( 's0-eth2' ).setMAC( '0A:00:0A:01:00:02' )
s0.intf( 's0-eth3' ).setMAC( '0A:00:0B:01:00:03' )
s1 = net.get( 's1' )
s1.intf( 's1-eth1' ).setMAC( '0A:00:01:01:00:01' )
s1.intf( 's1-eth2' ).setMAC( '0A:00:0A:FE:00:02' )
s1.intf( 's1-eth3' ).setMAC( '0A:00:0C:01:00:03' )
s2 = net.get( 's2' )
s2.intf( 's2-eth1' ).setMAC( '0A:00:02:01:00:01' )
s2.intf( 's2-eth2' ).setMAC( '0A:00:0B:FE:00:02' )
s2.intf( 's2-eth3' ).setMAC( '0A:00:0D:01:00:03' )
s2.intf( 's2-eth4' ).setMAC( '0A:00:0C:FE:00:04' )
s3 = net.get( 's3' )
s3.intf( 's3-eth1' ).setMAC( '0A:00:03:01:00:01' )
s3.intf( 's3-eth2' ).setMAC( '0A:00:0D:FE:00:02' )
s3.intf( 's3-eth3' ).setMAC( '0A:00:0E:01:00:03' )
s3.intf( 's3-eth4' ).setMAC( '0A:00:0F:01:00:04' )
s4 = net.get( 's4' )
s4.intf( 's4-eth1' ).setMAC( '0A:00:04:01:00:01' )
s4.intf( 's4-eth2' ).setMAC( '0A:00:0E:FE:00:02' )
s4.intf( 's4-eth3' ).setMAC( '0A:00:10:01:00:03' )
s5 = net.get( 's5' )
s5.intf( 's5-eth1' ).setMAC( '0A:00:05:01:00:01' )
s5.intf( 's5-eth2' ).setMAC( '0A:00:10:FE:00:02' )
s5.intf( 's5-eth3' ).setMAC( '0A:00:11:01:00:03' )
s6 = net.get( 's6' )
s6.intf( 's6-eth1' ).setMAC( '0A:00:06:01:00:01' )
s6.intf( 's6-eth2' ).setMAC( '0A:00:0F:FE:00:02' )
s6.intf( 's6-eth3' ).setMAC( '0A:00:12:01:00:03' )
s7 = net.get( 's7' )
s7.intf( 's7-eth1' ).setMAC( '0A:00:07:01:00:01' )
s7.intf( 's7-eth2' ).setMAC( '0A:00:11:FE:00:02' )
s7.intf( 's7-eth3' ).setMAC( '0A:00:12:FE:00:03' )
s7.intf( 's7-eth4' ).setMAC( '0A:00:13:01:00:04' )
s7.intf( 's7-eth5' ).setMAC( '0A:00:14:01:00:05' )
s8 = net.get( 's8' )
s8.intf( 's8-eth1' ).setMAC( '0A:00:08:01:00:01' )
s8.intf( 's8-eth2' ).setMAC( '0A:00:13:FE:00:02' )
s8.intf( 's8-eth3' ).setMAC( '0A:00:15:01:00:03' )
s9 = net.get( 's9' )
s9.intf( 's9-eth1' ).setMAC( '0A:00:09:01:00:01' )
s9.intf( 's9-eth2' ).setMAC( '0A:00:14:FE:00:02' )
s9.intf( 's9-eth3' ).setMAC( '0A:00:15:FE:00:03' )
net.start()
# Add routing table entries for hosts (NOTE: The gateway
# IPs 10.0.X.1 are not assigned to switch interfaces)
h0.cmd( 'route add default gw 10.0.0.1 dev h0-eth0' )
h1.cmd( 'route add default gw 10.0.1.1 dev h1-eth0' )
h2.cmd( 'route add default gw 10.0.2.1 dev h2-eth0' )
h3.cmd( 'route add default gw 10.0.3.1 dev h3-eth0' )
h4.cmd( 'route add default gw 10.0.4.1 dev h4-eth0' )
h5.cmd( 'route add default gw 10.0.5.1 dev h5-eth0' )
h6.cmd( 'route add default gw 10.0.6.1 dev h6-eth0' )
h7.cmd( 'route add default gw 10.0.7.1 dev h7-eth0' )
h8.cmd( 'route add default gw 10.0.8.1 dev h8-eth0' )
h9.cmd( 'route add default gw 10.0.9.1 dev h9-eth0' )
# Add arp cache entries for hosts
h0.cmd( 'arp -s 10.0.0.1 0A:00:00:01:00:01 -i h0-eth0' )
h1.cmd( 'arp -s 10.0.1.1 0A:00:01:01:00:01 -i h1-eth0' )
h2.cmd( 'arp -s 10.0.2.1 0A:00:02:01:00:01 -i h2-eth0' )
h3.cmd( 'arp -s 10.0.3.1 0A:00:03:01:00:01 -i h3-eth0' )
h4.cmd( 'arp -s 10.0.4.1 0A:00:04:01:00:01 -i h4-eth0' )
h5.cmd( 'arp -s 10.0.5.1 0A:00:05:01:00:01 -i h5-eth0' )
h6.cmd( 'arp -s 10.0.6.1 0A:00:06:01:00:01 -i h6-eth0' )
h7.cmd( 'arp -s 10.0.7.1 0A:00:07:01:00:01 -i h7-eth0' )
h8.cmd( 'arp -s 10.0.8.1 0A:00:08:01:00:01 -i h8-eth0' )
h9.cmd( 'arp -s 10.0.9.1 0A:00:09:01:00:01 -i h9-eth0' )
# Open Mininet Command Line Interface
CLI(net)
# Teardown and cleanup
net.stop()
if __name__ == '__main__':
setLogLevel('info')
run()

在Mininet中测试拓扑脚本,生成10主机和10个交换拓扑结构。详细 IP/MAC 地址的拓扑如下

这里写图片描述

5.设计openflow条目
打开终端

1
2
3
4
5
6
7
8
9
10
ovs-vsctl set bridge s0 protocols=OpenFlow13
ovs-vsctl set bridge s1 protocols=OpenFlow13
ovs-vsctl set bridge s2 protocols=OpenFlow13
ovs-vsctl set bridge s3 protocols=OpenFlow13
ovs-vsctl set bridge s4 protocols=OpenFlow13
ovs-vsctl set bridge s5 protocols=OpenFlow13
ovs-vsctl set bridge s6 protocols=OpenFlow13
ovs-vsctl set bridge s7 protocols=OpenFlow13
ovs-vsctl set bridge s8 protocols=OpenFlow13
ovs-vsctl set bridge s9 protocols=OpenFlow13

多路径随机交换思路

测试 multipath stochastic switching
从h0向h9发送数据包
(1)[s0, s2, s3, s6, s7, s9]
(2) [s0, s2, s3, s6, s7, s8, s9]

这里写图片描述

6.运行 xterm s0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# ADD-GROUP at s7 for [0, 9]
ovs-ofctl -O OpenFlow13 add-group tcp:127.0.0.1:6641 group_id=0,type=select,bucket=weight:7,mod_dl_src:0A:00:14:01:00:05,mod_dl_dst:0A:00:14:FE:00:02,output=5,bucket=weight:3,mod_dl_src:0A:00:13:01:00:04,mod_dl_dst:0A:00:13:FE:00:02,output=4
# ADD-FLOW(s) for [0, 9] at [0, 2, 3, 6, 7, 8, 9]
ovs-ofctl -O OpenFlow13 add-flow tcp:127.0.0.1:6634 in_port=1,ip,nw_src=10.0.0.2,nw_dst=10.0.9.2,actions=mod_dl_src:0A:00:0B:01:00:03,mod_dl_dst:0A:00:0B:FE:00:02,output=3
ovs-ofctl -O OpenFlow13 add-flow tcp:127.0.0.1:6636 in_port=2,ip,nw_src=10.0.0.2,nw_dst=10.0.9.2,actions=mod_dl_src:0A:00:0D:01:00:04,mod_dl_dst:0A:00:0D:FE:00:02,output=4
ovs-ofctl -O OpenFlow13 add-flow tcp:127.0.0.1:6637 in_port=2,ip,nw_src=10.0.0.2,nw_dst=10.0.9.2,actions=mod_dl_src:0A:00:0F:01:00:04,mod_dl_dst:0A:00:0F:FE:00:02,output=4
ovs-ofctl -O OpenFlow13 add-flow tcp:127.0.0.1:6640 in_port=2,ip,nw_src=10.0.0.2,nw_dst=10.0.9.2,actions=mod_dl_src:0A:00:12:01:00:03,mod_dl_dst:0A:00:12:FE:00:03,output=3
ovs-ofctl -O OpenFlow13 add-flow tcp:127.0.0.1:6641 in_port=3,ip,nw_src=10.0.0.2,nw_dst=10.0.9.2,actions=group=0
ovs-ofctl -O OpenFlow13 add-flow tcp:127.0.0.1:6643 in_port=2,ip,nw_src=10.0.0.2,nw_dst=10.0.9.2,actions=mod_dl_src:0A:00:09:01:00:01,mod_dl_dst:0A:00:09:02:00:00,output=1
ovs-ofctl -O OpenFlow13 add-flow tcp:127.0.0.1:6642 in_port=2,ip,nw_src=10.0.0.2,nw_dst=10.0.9.2,actions=mod_dl_src:0A:00:15:01:00:03,mod_dl_dst:0A:00:15:FE:00:03,output=3
ovs-ofctl -O OpenFlow13 add-flow tcp:127.0.0.1:6643 in_port=3,ip,nw_src=10.0.0.2,nw_dst=10.0.9.2,actions=mod_dl_src:0A:00:09:01:00:01,mod_dl_dst:0A:00:09:02:00:00,output=1

这里写图片描述

参考https://github.com/saeenali/openvswitch

总结:
这几个实验当中,个人最喜欢的是第四个tinyhttp和webbench,感觉最实用,第五个ovs感觉很综合有许多概念还是比较模糊,也花了很多时间研究。
在这半个月的学习中,一步一步总结步骤、截图,最重要是学会了资料搜索,获益匪浅!