zoukankan      html  css  js  c++  java
  • 基于 Open vSwitch 的 OpenFlow 实践

    目录

    前文列表

    《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 的完整功能。

    相关阅读:

  • 相关阅读:
    nvelocity的Foreach 中使用DataTable数据
    好的博客链接收集
    Uber Shaders
    DOF
    纹理过滤模式中的Bilinear、Trilinear以及Anistropic Filtering
    开通博客了
    代码中的隐式转换问题
    使用C++/CLI封装引用BOOST库的DLL造成的问题
    在Free Radius的PAP认证过程中使用MD5密码
    (转)测试CPU是大端Big endian 还是小端Little Endian的C代码
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13309717.html
Copyright © 2011-2022 走看看