目录

前文列表

《OpenFlow/SDN 的缘起与发展》

《OpenFlow Switch 1.3 规范》

《OpenvSwitch/OpenFlow 架构解析与实践案例》

Open vSwitch 基本概念

Bridge:在 Linux 的语义中代表一个虚拟的以太网交换机(vSwitch)。

Port:Bridge 的端口,每个 Port 都隶属于一个 Bridge。

Interface:连接到 Port 的网络接口设备(e.g. Tap、eth0)。通常情况下,Port 和 Interface 是一对一关系,为 Port 配置 bond 模式后,Port:Interface 是 1:N 的关系。

Controller:OpenFlow 控制器,OvS 作为 OpenFlow 交换机可以同时接受一个或多个 OpenFlow Controller 的管理。

Datapath:在 OpenFlow 的语义中,Datapath 就是一个 OpenFlow 交换机。负责执行数据交换,把从接收 Port 收到的数据包在流表中进行匹配,并执行匹配到的动作。

Flow Table:流表,Datapath 与流表关联,流表记录了网络包的匹配域、计数器和动作集。OpenFlow Controller 通过设定 OvS 的流表来对 SDN 网络进行 “编程”。

Open vSwitch 与 OpenFlow 的关系

Open vSwitch(简称 OvS)是遵守 OpenFlow Switch Specification 的 OpenFlow 交换机软件实现。OpenFlow 协议是用于管理 OpenFlow Switch 流表的协议,ovs-ofctl 就是 OvS 提供的 OpenFlow 流表配置命令行工具。在没有配置 OpenFlow Controller 的场景中,用户可以直接使用 ovs-ofctl 命令与 OvS 连接 OpenFlow 通道,并以此创建、修改或删除 OvS 中的流表项,同时对 OvS 的运行状况进行动态监控。



在 OvS 中,流表项作为 ovs-ofctl 指令的参数,采用 字段=值 的格式,如果有多个字段,可以是用逗号或者空格分开。e.g.

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

通过 Open vSwitch 实践 OpenFlow

查看 OvS 服务进程:

[root@ovs ~]# ps -ea | grep ovs
1295 ? 00:00:00 ovsdb-server
1310 ? 00:00:00 ovs-vswitchd

查看 OvS 版本:

[root@ovs ~]# ovs-appctl --version
ovs-appctl (Open vSwitch) 2.0.0
Compiled Apr 19 2018 17:57:34

查看 OvS 支持的 OpenFlow 版本:

[root@ovs ~]# ovs-ofctl --version
ovs-ofctl (Open vSwitch) 2.0.0
Compiled Apr 19 2018 17:57:34
OpenFlow versions 0x1:0x4

新建一个 OvS Switch:

[root@ovs ~]# ovs-vsctl add-br ovs-switch

[root@ovs ~]# ovs-vsctl show
367a97be-5b4f-40e2-8630-e64f67172fd2
Bridge ovs-switch
Port ovs-switch
Interface ovs-switch
type: internal
ovs_version: "2.0.0" [root@ovs ~]# ip a
...
3: ovs-system: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
link/ether 3a:3f:8b:8c:5d:31 brd ff:ff:ff:ff:ff:ff # Port ovs-switch 的 Interface 虚拟网络设备
4: ovs-switch: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN qlen 1000
link/ether 16:50:76:b2:22:46 brd ff:ff:ff:ff:ff:ff
inet6 fe80::f018:ff:fed7:bf2a/64 scope link
valid_lft forever preferred_lft forever

NOTE:OvS Switch 默认会有一个 “internal” 类型的同名 Port,相当于物理交换机的管理端口。

创建 Port p0,并设置 p0 的 OpenFlow 端口编号为 100。OpenFlow 端口编号常被作为流表项的匹配字段,如果没有显式指定 OpenFlow 端口编号,OvS 会随机指定。

[root@ovs ~]# ovs-vsctl add-port ovs-switch p0 -- set Interface p0 ofport_request=100

[root@ovs ~]# ovs-vsctl show
367a97be-5b4f-40e2-8630-e64f67172fd2
Bridge ovs-switch
Port ovs-switch
Interface ovs-switch
type: internal
Port "p0"
Interface "p0"
ovs_version: "2.0.0"

NOTE:除了在创建 Port 的时候指定虚拟接口设备 p0,也可以指定一个物理接口设备(e.g. eth0)。

设定 p0 的 Interface 类型为 “internal”:

[root@ovs ~]# ovs-vsctl set Interface p0 type=internal

[root@ovs ~]# ip a
...
5: p0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN qlen 1000
link/ether 5a:d7:49:85:d9:da brd ff:ff:ff:ff:ff:ff
inet6 fe80::58d7:49ff:fe85:d9da/64 scope link
valid_lft forever preferred_lft forever

NOTE:Internal 类型是 OvS 内部创建的虚拟网卡接口,每创建一个 Port,OvS 会自动在 Linux 上创建一个同名接口设备挂载到新创建的 Port 上。同时可以为这个虚拟网络设备配置 IP 地址,进行数据监听等。

为了避免 OvS Interface 的 IP 地址与 HostOS 本地的 IP 地址冲突,可以创建一个 Network Namespace ns0,把 p0 的 Interface 移入 ns0 中,并配置 IP 地址为 192.168.1.100。

# 新建 ns0,初始 ns0 只有 lo 设备
[root@ovs ~]# ip netns add ns0
[root@ovs ~]# ip netns exec ns0 ip l
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 # 将 p0 移入 ns0 后,p0 被隔离在 ns0,HostOS 看不见 p0 Interface 设备
[root@ovs ~]# ip link set p0 netns ns0
[root@ovs ~]# ip netns exec ns0 ip l
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
5: p0: <BROADCAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 5a:d7:49:85:d9:da brd ff:ff:ff:ff:ff:ff
[root@ovs ~]# ip l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether fa:16:3e:c4:f4:7f brd ff:ff:ff:ff:ff:ff
3: ovs-system: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 3a:3f:8b:8c:5d:31 brd ff:ff:ff:ff:ff:ff
4: ovs-switch: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1000
link/ether 16:50:76:b2:22:46 brd ff:ff:ff:ff:ff:ff # 为 ns0 内的 p0 设定 IP 地址和开启混杂模式,让所有 MAC 地址的二层帧都能通过
[root@ovs ~]# ip netns exec ns0 ip addr add 192.168.1.100/24 dev p0
[root@ovs ~]# ip netns exec ns0 ifconfig p0 promisc up
[root@ovs ~]# ip netns exec ns0 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
5: p0: <BROADCAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN qlen 1000
link/ether 5a:d7:49:85:d9:da brd ff:ff:ff:ff:ff:ff
inet 192.168.1.100/24 scope global p0
valid_lft forever preferred_lft forever
inet6 fe80::58d7:49ff:fe85:d9da/64 scope link
valid_lft forever preferred_lft forever

使用同样的方法创建 p1、p2,p0-2 的 IP/MAC 地址分别为:

  • p0

    • Network Namespace: ns0
    • IP: 192.168.1.100/24
    • MAC: 5a:d7:49:85:d9:da
    • OpenFlow Port Number: 100
  • p1
    • Network Namespace: ns1
    • IP: 192.168.1.101/24
    • MAC: 62:f0:3e:b6:7d:6f
    • OpenFlow Port Number: 101
  • p2
    • Network Namespace: ns2
    • IP: 192.168.1.102/24
    • MAC: 3e:3f:34:6b:0a:3d
    • OpenFlow Port Number: 102
[root@ovs ~]# ovs-vsctl show
367a97be-5b4f-40e2-8630-e64f67172fd2
Bridge ovs-switch
Port "p2"
Interface "p2"
type: internal
Port ovs-switch
Interface ovs-switch
type: internal
Port "p0"
Interface "p0"
type: internal
Port "p1"
Interface "p1"
type: internal
ovs_version: "2.0.0" # 查看 OvS Switch 的详细端口信息
[root@ovs ~]# ovs-ofctl show ovs-switch
# OpenFlow Features 响应消息,包含:
# Datapath 的唯一标示 ID
# Datapath 支持的流表数量
# Datapath 可以缓存数据包的最大数量
OFPT_FEATURES_REPLY (xid=0x2): dpid:0000165076b22246
n_tables:254, n_buffers:256
# Datapath 支持的容量,即功能
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
# Datapath 支持的动作
actions: OUTPUT SET_VLAN_VID SET_VLAN_PCP STRIP_VLAN SET_DL_SRC SET_DL_DST SET_NW_SRC SET_NW_DST SET_NW_TOS SET_TP_SRC SET_TP_DST ENQUEUE
# Datapath 包含的 Ports 及其编号,是一个可变的 ofp_phy_port 结构体数组类型
100(p0): addr:00:00:00:00:00:00
# 配置为 Down,即没有手动配置为 UP
config: PORT_DOWN
# 状态为 Down
state: LINK_DOWN
# 数据传输速率
speed: 0 Mbps now, 0 Mbps max
101(p1): addr:00:00:00:00:00:00
config: PORT_DOWN
state: LINK_DOWN
speed: 0 Mbps now, 0 Mbps max
102(p2): addr:00:00:00:00:00:00
config: PORT_DOWN
state: LINK_DOWN
speed: 0 Mbps now, 0 Mbps max
LOCAL(ovs-switch): addr:f2:18:00:d7:bf:2a
config: PORT_DOWN
state: LINK_DOWN
speed: 0 Mbps now, 0 Mbps max
# GET_CONFIG 答复消息,包含 flags 和 miss_send_len 配置信息
# flags 指定了 OpenFlow 交换机的 IP 碎片处理方法
# miss_send_len 表示在 Table-miss 时和 Packet-In 消息中发送的数据包字节数
OFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0

NOTE:执行指令 ovs-ofctl show ovs-switch 就相当于 OpenFlow 控制器向 OpenFlow 交换机发送了询问功能的 Features 请求消息,OpenFlow 交换机响应了 Features 应答消息给 OpenFlow,消息体记录了 OpenFlow 交换机的功能参数。这个过程就是 OpenFlow 的 “握手”。

也可以获取指定 Port 的 OpenFlow 端口编号:

[root@ovs ~]# ovs-vsctl get Interface p0 ofport
100

查看 Datapath 信息:

# Get all
[root@ovs ~]# ovs-dpctl show
system@ovs-system:
lookups: hit:35 missed:21 lost:0
flows: 0
port 0: ovs-system (internal)
port 1: ovs-switch (internal)
port 2: p0 (internal)
port 3: p1 (internal)
port 4: p2 (internal) # Get one
[root@ovs ~]# ovs-dpctl show system@ovs-system
system@ovs-system:
lookups: hit:35 missed:21 lost:0
flows: 0
port 0: ovs-system (internal)
port 1: ovs-switch (internal)
port 2: p0 (internal)
port 3: p1 (internal)
port 4: p2 (internal)

检查 p0、p1、p2 的互通性:

ip netns exec ns0 ping 192.168.1.101
ip netns exec ns0 ping 192.168.1.102

NOTE:如果想在 ns0 ping 通 p0 Interface 的 IP 地址,那么首先需要把 lo Up 起来,否则执行 ip netns exec ns0 ping 192.168.1.100 ping 不通。这是因为所有只在本机内部流转的数据包都需要经过 lo 设备的处理,而 ping 外部 IP 地址时内核协议栈直接将数据包从 NIC 送出。所以如果 lo DOWN,则无法 ping 通过本地。

[root@ovs ~]# ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
5: p0: <BROADCAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN qlen 1000
link/ether 5a:d7:49:85:d9:da brd ff:ff:ff:ff:ff:ff
inet 192.168.1.100/24 scope global p0
valid_lft forever preferred_lft forever
inet6 fe80::58d7:49ff:fe85:d9da/64 scope link
valid_lft forever preferred_lft forever [root@ovs ~]# ip netns exec ns0 ifconfig lo up [root@ovs ~]# ip netns exec ns0 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
5: p0: <BROADCAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN qlen 1000
link/ether 5a:d7:49:85:d9:da brd ff:ff:ff:ff:ff:ff
inet 192.168.1.100/24 scope global p0
valid_lft forever preferred_lft forever
inet6 fe80::58d7:49ff:fe85:d9da/64 scope link
valid_lft forever preferred_lft forever

屏蔽数据包

查看当前 OvS Switch 的所有流表,数量应该就是 OpenFlow 控制器和 OpenFlow 交换机握手时反馈的 254 张:

root@ovs ~]# ovs-ofctl dump-tables ovs-switch
OFPST_TABLE reply (xid=0x2): 254 tables
0: classifier: wild=0x3fffff, max=1000000, active=2
lookup=489, matched=489
1: table1 : wild=0x3fffff, max=1000000, active=0
lookup=0, matched=0
...

查看当前 OvS Switch 的所有流表项:

[root@ovs ~]# ovs-ofctl dump-flows ovs-switch
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=6469.422s, table=0, n_packets=82, n_bytes=6300, idle_age=2533, priority=0 actions=NORMAL
  • cookie:一个 64bit 的整数,OpenFlow 控制器用于标识流表项,相同的 cookie 值可以用来标记是同一批或同一类规则。只对 OpenFlow 控制器有效,OpenFlow 交换机不关心该字段。
  • duration:规则创建的时长
  • table:流表编号,用来建立流表的层次关系
  • n_packets、n_bytes:匹配到这条规则的网络包数、字节数。
  • idle_age:该流表项多久没有被匹配过,单位秒。
  • hard_age:这条流表项创建、修改了多次时间,单位秒。
  • priority:优先级,当 Flow 被同一个流表中的多条流表项匹配时,选择优先级高的。
  • actions=NORMAL:正常的 L2/L3 交换机行为。

NOTE:默认情况下 OvS Switch 执行传统 L2/L3 交换机的行为

添加流表项,屏蔽所有进入 OvS 的以太网广播包:

[root@ovs ~]# ovs-ofctl add-flow ovs-switch "table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop"

[root@ovs ~]# ovs-ofctl dump-flows ovs-switch
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=6603.552s, table=0, n_packets=82, n_bytes=6300, idle_age=2667, priority=0 actions=NORMAL
cookie=0x0, duration=1.952s, table=0, n_packets=0, n_bytes=0, idle_age=1, dl_src=01:00:00:00:00:00/01:00:00:00:00:00 actions=drop
  • dl_src:以太网数据帧源 MAC 地址
  • actions=drop:流表项匹配域匹配之后对 Flow( e.g. 数据包,TCP 连接)执行的动作集,这里表示丢弃数据包

NOTEdl_src=01:00:00:00:00:00/01:00:00:00:00:00 matches all multicast (including broadcast) Ethernet packets.

添加流表项,屏蔽所有进入 OvS 的 IEEE 802.1D STP 协议广播包:

[root@ovs ~]# ovs-ofctl add-flow ovs-switch "table=0, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"

[root@ovs ~]# ovs-ofctl dump-flows ovs-switch
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=15.302s, table=0, n_packets=0, n_bytes=0, idle_age=15, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0 actions=drop
cookie=0x0, duration=7051.931s, table=0, n_packets=82, n_bytes=6300, idle_age=3116, priority=0 actions=NORMAL
cookie=0x0, duration=450.331s, table=0, n_packets=0, n_bytes=0, idle_age=450, dl_src=01:00:00:00:00:00/01:00:00:00:00:00 actions=drop
  • dl_dst:以太网数据帧目的 MAC 地址

删除流表项:

[root@ovs ~]# ovs-ofctl del-flows ovs-switch "dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0"
[root@ovs ~]# ovs-ofctl del-flows ovs-switch "dl_src=01:00:00:00:00:00/01:00:00:00:00:00"

重定向数据包

添加流表项,重定向所有 ICMP 数据包到 p2:

[root@ovs ~]# ovs-ofctl add-flow ovs-switch "idle_timeout=0, dl_type=0x0800, nw_proto=1, actions=output:102"

[root@ovs ~]# ovs-ofctl dump-flows ovs-switch
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=14.749s, table=0, n_packets=0, n_bytes=0, idle_age=14, icmp actions=output:102
cookie=0x0, duration=7605.774s, table=0, n_packets=82, n_bytes=6300, idle_age=3670, priority=0 actions=NORMAL
  • idle_timeout:流表项空闲超时时间,从上次匹配该流表项开始计时
  • dl_type=0x0800, nw_proto=1:ICMP Packet
  • actions=output:102:匹配该流表项的 Flow 被转发至 OpenFlow 端口编号为 102 的 Port

验证结果,通过 p0 ping p1,但实际是 ICMP echo request 包被转发了到 p2:

# ns0
[root@ovs ~]# ip netns exec ns0 ping 192.168.1.101
PING 192.168.1.101 (192.168.1.101) 56(84) bytes of data. # ns1
[root@ovs ~]# ip netns exec ns1 tcpdump -i p1 -nntve -p icmp
tcpdump: listening on p1, link-type EN10MB (Ethernet), capture size 262144 bytes # ns2
[root@ovs ~]# ip netns exec ns2 tcpdump -i p2 -nntve -p icmp
tcpdump: listening on p2, link-type EN10MB (Ethernet), capture size 262144 bytes
5a:d7:49:85:d9:da > 62:f0:3e:b6:7d:6f, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 12532, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.1.100 > 192.168.1.101: ICMP echo request, id 11772, seq 5, length 64

NOTE:虽然 p2 能够接收到 p0 ping p1 的 ICMP 包,但却不会进行响应,因为 IP 地址对不上。值得注意的是,即便我们从 p0 ping p2,但 p0 依旧无法接收到 ICMP reply。这是因为上述流表包含了所有的 ICMP 类型(e.g. ICMP request、ICMP reply)。e.g.

5a:d7:49:85:d9:da > 3e:3f:34:6b:0a:3d, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 53435, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.1.100 > 192.168.1.102: ICMP echo request, id 11780, seq 13, length 64
3e:3f:34:6b:0a:3d > 5a:d7:49:85:d9:da, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 6503, offset 0, flags [none], proto ICMP (1), length 84)
192.168.1.102 > 192.168.1.100: ICMP echo reply, id 11780, seq 13, length 64

删除流表项:

[root@ovs ~]# ovs-ofctl del-flows ovs-switch "icmp"

修改数据包源 IP 地址

添加流表项,修改从 p0 接收到的数据包的源 IP 地址:

[root@ovs ~]# ovs-ofctl add-flow ovs-switch "priority=1, idle_timeout=0, in_port=100, actions=mod_nw_src:9.181.137.1,normal"

[root@ovs ~]# ovs-ofctl dump-flows ovs-switch
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=3.594s, table=0, n_packets=0, n_bytes=0, idle_age=3, priority=1,in_port=100 actions=mod_nw_src:9.181.137.1,NORMAL
cookie=0x0, duration=8661.508s, table=0, n_packets=98, n_bytes=6972, idle_age=379, priority=0 actions=NORMAL
  • in_port:OvS Switch 的输入端口,表示数据包从哪一个 Switch 端口输入
  • actions=mod_nw_src:9.181.137.1:修改与匹配域匹配的数据包的三层数据包源 IP 地址

验证结果,从 p0 ping p1,数据包进入 p0 之后源 IP 地址就会修改为 9.181.137.1 了:

# ns0
[root@ovs ~]# ip netns exec ns0 ping 192.168.1.101
PING 192.168.1.101 (192.168.1.101) 56(84) bytes of data. # ns1
[root@ovs ~]# ip netns exec ns1 tcpdump -i p1 -nntve
tcpdump: listening on p1, link-type EN10MB (Ethernet), capture size 262144 bytes
5a:d7:49:85:d9:da > 62:f0:3e:b6:7d:6f, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 27038, offset 0, flags [DF], proto ICMP (1), length 84)
9.181.137.1 > 192.168.1.101: ICMP echo request, id 11825, seq 1, length 64

删除流表项:

[root@ovs ~]# ovs-ofctl del-flows ovs-switch "in_port=100"

修改数据包 VLAN tag

在该例子中我们使用 ovs-appctl ofproto/trace 指令来生成测试用的模拟数据包,以此测试 OvS 对数据包的转发。

修改 p1 的 VLAN tag 为 101,是 p1 成为 VLAN tag 101 的 Access 口:

[root@ovs ~]# ovs-vsctl show
367a97be-5b4f-40e2-8630-e64f67172fd2
Bridge ovs-switch
Port "p2"
Interface "p2"
type: internal
Port ovs-switch
Interface ovs-switch
type: internal
Port "p0"
Interface "p0"
type: internal
Port "p1"
Interface "p1"
type: internal
ovs_version: "2.0.0" [root@ovs ~]# ovs-vsctl set Port p1 tag=101 [root@ovs ~]# ovs-vsctl show
367a97be-5b4f-40e2-8630-e64f67172fd2
Bridge ovs-switch
Port "p2"
Interface "p2"
type: internal
Port ovs-switch
Interface ovs-switch
type: internal
Port "p0"
Interface "p0"
type: internal
Port "p1"
tag: 101
Interface "p1"
type: internal
ovs_version: "2.0.0"

现在 p0 和 p1 被 VLAN 隔离了,它们之间无法进行数据交换。在此前提下,我们尝试使用 ovs-appctl ofproto/trace 生成一个从 p0 发送到 p1 的数据包,这个数据包不包含 VLAN tag:

[root@ovs ~]# ovs-appctl ofproto/trace ovs-switch "in_port=100, dl_src=5a:d7:49:85:d9:da, dl_dst=62:f0:3e:b6:7d:6f" -generate
# 描述模拟的 Flow 信息
Flow: metadata=0,in_port=100,vlan_tci=0x0000,dl_src=5a:d7:49:85:d9:da,dl_dst=62:f0:3e:b6:7d:6f,dl_type=0x0000
# 描述匹配成功的流表项
Rule: table=0 cookie=0 priority=0
# 匹配域匹配的流表项动作
OpenFlow actions=NORMAL
# 目的 MAC 地址没被学习到,进行洪泛
no learned MAC for destination, flooding # 总结整个处理过程
Final flow: unchanged
Relevant fields: skb_priority=0,in_port=100,vlan_tci=0x0000/0x1fff,dl_src=5a:d7:49:85:d9:da,dl_dst=62:f0:3e:b6:7d:6f,dl_type=0x0000,nw_frag=no
# 数据包被发送到 Datapath 的 1,4 号端口。注:这里的编号与 OpenFlow 端口编号不等同。
Datapath actions: 1,4

添加流表项,从 p0 输入的数据包,如果它不含任何 VLAN tag,则为数据包添加 VLAN tag 101

[root@ovs ~]# ovs-ofctl add-flow ovs-switch "priority=3, in_port=100, dl_vlan=0xffff, actions=mod_vlan_vid:101,normal"

[root@ovs ~]# ovs-ofctl dump-flows ovs-switch
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=2.448s, table=0, n_packets=0, n_bytes=0, idle_age=2, priority=3,in_port=100,vlan_tci=0x0000 actions=mod_vlan_vid:101,NORMAL
cookie=0x0, duration=11641.822s, table=0, n_packets=101, n_bytes=7098, idle_age=985, priority=0 actions=NORMAL
  • actions=mod_vlan_vid:101,normal:打上 VLAN tag 101

再次从尝试使用 ovs-appctl ofproto/trace 生成一个从 p0 到 p1 发送不包含 VLAN tag的数据包,这个数据包在进入 p0 之后会被打上 VLAN 100 的 tag:

[root@ovs ~]# ovs-appctl ofproto/trace ovs-switch "in_port=100, dl_src=5a:d7:49:85:d9:da, dl_dst=62:f0:3e:b6:7d:6f" -generate
Flow: metadata=0,in_port=100,vlan_tci=0x0000,dl_src=5a:d7:49:85:d9:da,dl_dst=62:f0:3e:b6:7d:6f,dl_type=0x0000
Rule: table=0 cookie=0 priority=3,in_port=100,vlan_tci=0x0000
OpenFlow actions=mod_vlan_vid:101,NORMAL
forwarding to learned port Final flow: metadata=0,in_port=100,dl_vlan=101,dl_vlan_pcp=0,dl_src=5a:d7:49:85:d9:da,dl_dst=62:f0:3e:b6:7d:6f,dl_type=0x0000
Relevant fields: skb_priority=0,in_port=100,vlan_tci=0x0000,dl_src=5a:d7:49:85:d9:da,dl_dst=62:f0:3e:b6:7d:6f,dl_type=0x0000,nw_frag=no
Datapath actions: 3

NOTE:虽然通过流表项令从 p0 进来的数据包都打上 VLAN tag 101,但并非是说 p0 就成为了一个 Access 口,p0 依旧无法和 p1 正常通信,因为 p0 不具有 VLAN access 的完整功能。

基于 Open vSwitch 的 OpenFlow 实践的更多相关文章

  1. 基于Open vSwitch的OpenFlow实践

    Open vSwitch(下面简称为 OVS)是由 Nicira Networks 主导的,运行在虚拟化平台(例如 KVM,Xen)上的虚拟交换机.在虚拟化平台上,OVS 可以为动态变化的端点提供 2 ...

  2. 实验2:Open vSwitch虚拟交换机实践

    作业链接:实验2:Open vSwitch虚拟交换机实践 一.实验目的 能够对Open vSwitch进行基本操作: 能够通过命令行终端使用OVS命令操作Open vSwitch交换机,管理流表: 能 ...

  3. 学习笔记——Maven实战(四)基于Maven的持续集成实践

    Martin的<持续集成> 相信很多读者和我一样,最早接触到持续集成的概念是来自Martin的著名文章<持续集成>,该文最早发布于2000年9月,之后在2006年进行了一次修订 ...

  4. 基于AWS的自动化部署实践

    过年前,我给InfoQ写了篇文章详细介绍我们团队在过去4年基于AWS的自动化部署实践.文章包括了:为什么选择AWS.AWS上自动化部署的优势和挑战.我们的解决方案,以及和AWS DevOps方案(Op ...

  5. OVS-----CentOS7上搭建基于Open vSwitch的VxLAN隧道实验

    一.关于VXLAN VXLAN 是 Virtual eXtensible LANs 的缩写,它是对 VLAN 的一个扩展,是非常新的一个 tunnel 技术,在Open vSwitch中应用也非常多. ...

  6. 基于CMS的组件复用实践

    目前前端项目大多基于Vue.React.Angular等框架来实现,这一类框架都有一个明显的特点:基于模块化以及组件化思维.所以,开发者在使用上述框架时,实际上是在写一个一个的组件,并且组件与组件之间 ...

  7. 新浪微博基于MySQL的分布式数据库实践

    提起微博,相信大家都是很了解的.但是有谁知道微博的数据库架构是怎样的呢?在今天举行的2011数据库技术大会上,新浪首席DBA杨海潮为我们详细解读了新浪微博的数据库架构——基于MySQL的分布式数据库实 ...

  8. Maven实战(四)——基于Maven的持续集成实践

    Martin的<持续集成> 相信非常多读者和我一样.最早接触到持续集成的概念是来自Martin的著名文章<持续集成>.该文最早公布于2000年9月,之后在2006年进行了一次修 ...

  9. 聊聊基于Lucene的搜索引擎核心技术实践

    最近公司用到了ES搜索引擎,由于ES是基于Lucene的企业搜索引擎,无意间在“聊聊架构”微信公众号里发现了这篇文章,分享给大家. 请点击链接:聊聊基于Lucene的搜索引擎核心技术实践

随机推荐

  1. (六)buildroot使用详解

    为什么要使用buildroot? (文件系统搭建,强烈建议直接用buildroot,官网[http://buildroot.uclibc.org/]上有使用教程非常详细)文件系统通常要包含很多第三方软 ...

  2. Redis Sentinel机制与用法说明

    本文来自 https://www.cnblogs.com/zhoujinyi/p/5569462.html 概述 Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Red ...

  3. Java入门 异常处理

    Java入门 异常处理 1.处理异常(try-catch以及try-catch-finally): a)try会抛出很多种类型的异常-多重catch块的处理 eg:try{ //一些会抛出异常的方法 ...

  4. Cubase如何进行音频移调

  5. Ruby 中的闭包-代码块

    看了一片文章https://ruby-china.org/topics/38385讲closure的. 写下一些感想: 闭包就是 一个函数能够记住和存取它的lexical作用域,即使这个函数是在它的l ...

  6. 部署NFS共享

    一:NFS工作原理 什么是NFS服务器 NFS就是Network File System的缩写,它最大的功能就是可以通过网络,让不同的机器.不同的操作系统可以共享彼此的文件. NFS服务器可以让PC将 ...

  7. Java中的equals,==,compareTo和compare的比较

    Java中的equals(),==,compareTo()和compare() 首先只有==可以用作两个基本类型数据之间的比较,当然是值比较.当用作两个对象比较时,比较的是对象引用,而不是值比较. 其 ...

  8. springboot打包后静态资源webapp文件夹无法打包进去

    1.如下图的目录结构 webapp 文件夹和resources 文件夹同级.使用mvn clean install 打包过后项目启动访问,静态资源页面404. 2.原因,springboot 打包时候 ...

  9. Python设置浏览器宽高

    # 发起请求,设置浏览器宽高 # 代码中引入selenium版本为:3.4.3 # 通过Chrom浏览器访问发起请求 # Chrom版本:59 ,chromdriver:2.3 # 需要对应版本的Ch ...

  10. V2018.5 MB SD C4功能和软件详细信息更新

    MB SD C4 现在更新为V2018.5版本.功能和HDD Xentry软件信息如下: V2018.5 MB SD C4 功能: 支持无线诊断: 支持K线诊断,CAN BUS和UDS诊断协议.(旧的 ...