• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

SDN 控制器初探

开发技术 开发技术 5小时前 1次浏览

预备知识

流表查看与匹配示例

使用 ryu-manager 执行 GitHub 上的 ryu 官方的控制器例程,来创建 SDN 控制器:

sdn@debian:~$ sudo ryu-manager ryu/ryu/app/simple_switch_13.py 
loading app ryu/ryu/app/simple_switch_13.py
loading app ryu.controller.ofp_handler
instantiating app ryu/ryu/app/simple_switch_13.py of SimpleSwitch13
instantiating app ryu.controller.ofp_handler of OFPHandler

使用 mininet 连接 RYU 控制器,并创建只有一个交换机和两个主机的简单的网络拓扑:

sdn@debian:~$ sudo mn --controller=remote
*** Creating network
*** Adding controller
Connecting to remote controller at 127.0.0.1:6653
*** Adding hosts:
h1 h2 
*** Adding switches:
s1 
*** Adding links:
(h1, s1) (h2, s1) 
*** Configuring hosts
h1 h2 
*** Starting controller
c0 
*** Starting 1 switches
s1 ...
*** Starting CLI:
mininet> net
h1 h1-eth0:s1-eth1
h2 h2-eth0:s1-eth2
s1 lo:  s1-eth1:h1-eth0 s1-eth2:h2-eth0
c0

此时的网络拓扑结构如下图:

SDN 控制器初探

查看交换机 s1 的流表信息,此时 s1 中只有一条流表项:

mininet> dpctl dump-flows
*** s1 ------------------------------------------------------------------------
 cookie=0x0, duration=40.319s, table=0, n_packets=16, n_bytes=1272, priority=0 actions=CONTROLLER:65535

actions=CONTROLLER:65535 是交换机的 Table-miss 流表项,该流表项的匹配域为通配,即匹配任何报文,优先级为 0(优先级最低)。也就是说,当收到的数据包没有匹配到任意一条流表项时,则将该数据包发送给 controller,且限制数据包最大长度为 65535 字节。

在 mininet 中执行 pingall,来测试 h1、h2 的联通性:

mininet> pingall
*** Ping: testing ping reachability
h1 -> h2 
h2 -> h1 
*** Results: 0% dropped (2/2 received)

再查看 s1 的流表信息:

mininet> dpctl dump-flows
*** s1 ------------------------------------------------------------------------
 cookie=0x0, duration=39.658s, table=0, n_packets=3, n_bytes=238, priority=1,in_port="s1-eth2",dl_src=62:cc:b8:e8:2f:6b,dl_dst=d2:12:9f:77:82:71 actions=output:"s1-eth1"
 cookie=0x0, duration=39.655s, table=0, n_packets=2, n_bytes=140, priority=1,in_port="s1-eth1",dl_src=d2:12:9f:77:82:71,dl_dst=62:cc:b8:e8:2f:6b actions=output:"s1-eth2"
 cookie=0x0, duration=198.655s, table=0, n_packets=23, n_bytes=1734, priority=0 actions=CONTROLLER:65535

此时 s1 中新增了两条流表项:

cookie=0x0, duration=39.658s, table=0, n_packets=3, n_bytes=238, priority=1,in_port="s1-eth2",dl_src=62:cc:b8:e8:2f:6b,dl_dst=d2:12:9f:77:82:71 actions=output:"s1-eth1"
cookie=0x0, duration=39.655s, table=0, n_packets=2, n_bytes=140, priority=1,in_port="s1-eth1",dl_src=d2:12:9f:77:82:71,dl_dst=62:cc:b8:e8:2f:6b actions=output:"s1-eth2"

in_port="s1-eth2",dl_src=62:cc:b8:e8:2f:6b,dl_dst=d2:12:9f:77:82:71 actions=output:"s1-eth1" 指示 s1,当端口 s1-eth2 接收到源 MAC 为 62:cc:b8:e8:2f:6b,目标 MAC 为 d2:12:9f:77:82:71 的数据包时,则将该数据包发送到与端口 s1-eth1 连接的主机。而 h1 和 h2 的 MAC 地址,正好分别是 d2:12:9f:77:82:7162:cc:b8:e8:2f:6b

mininet> h1 ifconfig h1-eth0
h1-eth0: flags=4163<up,broadcast,running,multicast>  mtu 1500
        inet 10.0.0.1  netmask 255.0.0.0  broadcast 10.255.255.255
        inet6 fe80::d012:9fff:fe77:8271  prefixlen 64  scopeid 0x20<link>
        ether d2:12:9f:77:82:71  txqueuelen 1000  (Ethernet)
        RX packets 35  bytes 3498 (3.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 16  bytes 1216 (1.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

mininet> h2 ifconfig h2-eth0
h2-eth0: flags=4163<up,broadcast,running,multicast>  mtu 1500
        inet 10.0.0.2  netmask 255.0.0.0  broadcast 10.255.255.255
        inet6 fe80::60cc:b8ff:fee8:2f6b  prefixlen 64  scopeid 0x20<link>
        ether 62:cc:b8:e8:2f:6b  txqueuelen 1000  (Ethernet)
        RX packets 35  bytes 3498 (3.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 16  bytes 1216 (1.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

换而言之,in_port="s1-eth2",dl_src=62:cc:b8:e8:2f:6b,dl_dst=d2:12:9f:77:82:71 actions=output:"s1-eth1" 指示 s1,当端口 s1-eth2 接收到 h2 发送给 h1 的数据包时,则将该数据包发送到与端口 s1-eth1 连接的主机,也就是 h1:

mininet> net
h1 h1-eth0:s1-eth1
h2 h2-eth0:s1-eth2
s1 lo:  s1-eth1:h1-eth0 s1-eth2:h2-eth0
c0

in_port="s1-eth1",dl_src=d2:12:9f:77:82:71,dl_dst=62:cc:b8:e8:2f:6b actions=output:"s1-eth2" 同理,不再赘述。

上述例子仅简单演示了 OpenFlow 流表的查看与匹配,细节请参考官方文档 https://opennetworking.org/software-defined-standards/specifications/

流表项如何下发

流表项由 SDN 控制器生成并发送给 SDN 交换机。SDN 交换机维护了流表项,用于决定数据包的流向。由于本文的 SDN 控制器 RYU 与交换机之间使用的南向接口是 OpenFlow,所以接下来的内容依旧是基于 OpenFlow 进行分析。

TCP 握手

在 OpenFlow 中,控制平面与数据平面的传输协议是 TCP。

在上节中,使用 ryu-manager 执行官方例程来启动 RYU 控制器后,控制器监听在本地的 6653 端口:

tcp        0      0 0.0.0.0:6653            0.0.0.0:*               LISTEN      6264/python         

在 mininet 中连接 RYU 控制器时,控制器与交换机的 TCP 握手如下:

16:42:18.461536 IP localhost.51678 > localhost.6653: Flags [S], seq 1969037218, win 43690, options [mss 65495,sackOK,TS val 2494429579 ecr 0,nop,wscale 9], length 0
16:42:18.461556 IP localhost.6653 > localhost.51678: Flags [S.], seq 1946739924, ack 1969037219, win 43690, options [mss 65495,sackOK,TS val 2494429579 ecr 2494429579,nop,wscale 9], length 0
16:42:18.461574 IP localhost.51678 > localhost.6653: Flags [.], ack 1946739925, win 86, options [nop,nop,TS val 2494429579 ecr 2494429579], length 0

OpenFlow 版本协商

TCP 三次握手完成后,RYU 控制器与交换机相互发送 OFPT_HELLO 报文(省略其他无关的报文,如 TCP ACK 报文段和重传报文段)。HELLO 报文用于协商 OpenFLow 版本。通过协商后,通信双方决定使用的 OpenFlow 版本号为 1.3.0:

Frame 4: 74 bytes on wire (592 bits), 74 bytes captured (592 bits) on interface 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 6653, Dst Port: 51676, Seq: 1, Ack: 1, Len: 8
OpenFlow 1.3
    Version: 1.3 (0x04)
    Type: OFPT_HELLO (0)
    Length: 8
    Transaction ID: 3155619061
Frame 12: 74 bytes on wire (592 bits), 74 bytes captured (592 bits) on interface 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 6653, Dst Port: 51678, Seq: 1, Ack: 1, Len: 8
OpenFlow 1.3
    Version: 1.3 (0x04)
    Type: OFPT_HELLO (0)
    Length: 8
    Transaction ID: 1369246796

获取交换机的功能特性

在完成 OpenFlow 版本协商后,控制器需要根据交换机的功能特性,来完成相关配置。因此,RYU 控制器往交换机发送一个 OFPT_FEATURES_REQUEST 报文,以获取交换机的相关特性。作为响应,交换机回以一个 OFPT_FEATURES_REPLY 报文,其中包含了 datapath_id(在 OpenFlow 中,datapath 用于描述一个与控制器相连后的交换机)、n_buffers(单次数据包的接收最大缓冲)、n_tables(该交换机所能支持的流表数目)等信息:

Frame 22: 74 bytes on wire (592 bits), 74 bytes captured (592 bits) on interface 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 6653, Dst Port: 51678, Seq: 9, Ack: 249, Len: 8
OpenFlow 1.3
    Version: 1.3 (0x04)
    Type: OFPT_FEATURES_REQUEST (5)
    Length: 8
    Transaction ID: 1369246797

Frame 23: 98 bytes on wire (784 bits), 98 bytes captured (784 bits) on interface 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 51678, Dst Port: 6653, Seq: 249, Ack: 17, Len: 32
OpenFlow 1.3
    Version: 1.3 (0x04)
    Type: OFPT_FEATURES_REPLY (6)
    Length: 32
    Transaction ID: 1369246797
    datapath_id: 0x0000000000000001
    n_buffers: 0
    n_tables: 254
    auxiliary_id: 0
    Pad: 0
    capabilities: 0x0000004f
        .... .... .... .... .... .... .... ...1 = OFPC_FLOW_STATS: True
        .... .... .... .... .... .... .... ..1. = OFPC_TABLE_STATS: True
        .... .... .... .... .... .... .... .1.. = OFPC_PORT_STATS: True
        .... .... .... .... .... .... .... 1... = OFPC_GROUP_STATS: True
        .... .... .... .... .... .... ..0. .... = OFPC_IP_REASM: False
        .... .... .... .... .... .... .1.. .... = OFPC_QUEUE_STATS: True
        .... .... .... .... .... ...0 .... .... = OFPC_PORT_BLOCKED: False
    Reserved: 0x00000000

交换机发送端口状态信息

当交换机增删改端口时,需要发送 OFPT_PORT_STATUS 报文,以此通知控制器:

Frame 16: 146 bytes on wire (1168 bits), 146 bytes captured (1168 bits) on interface 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 51678, Dst Port: 6653, Seq: 9, Ack: 9, Len: 80
OpenFlow 1.3
    Version: 1.3 (0x04)
    Type: OFPT_PORT_STATUS (12)
    Length: 80
    Transaction ID: 0
    Reason: OFPPR_MODIFY (2)
    Pad: 00000000000000
    Port
        Port no: 2
        Pad: 00000000
        Hw addr: 1e:09:45:71:69:a6 (1e:09:45:71:69:a6)
        Pad: 0000
        Name: s1-eth2
    (略)

修改交换机的流表项信息

控制器通过往交换机发送 OFPT_FLOW_MOD 报文,来调整交换机的流表。同时,在初始化阶段,控制器往交换机发送了一条 Match 字段为空、数据最大长度为 65535 的 OFPT_FLOW_MOD 报文,可见这条报文就是用于设置交换机的 Table-miss 流表项:

Frame 26: 146 bytes on wire (1168 bits), 146 bytes captured (1168 bits) on interface 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 6653, Dst Port: 51678, Seq: 33, Ack: 489, Len: 80
OpenFlow 1.3
    Version: 1.3 (0x04)
    Type: OFPT_FLOW_MOD (14)
    Length: 80
    Transaction ID: 1369246799
    Cookie: 0x0000000000000000
    Cookie mask: 0x0000000000000000
    Table ID: 0
    Command: OFPFC_ADD (0)
    Idle timeout: 0
    Hard timeout: 0
    Priority: 0
    Buffer ID: OFP_NO_BUFFER (4294967295)
    Out port: 0
    Out group: 0
    Flags: 0x0000
        .... .... .... ...0 = Send flow removed: False
        .... .... .... ..0. = Check overlap: False
        .... .... .... .0.. = Reset counts: False
        .... .... .... 0... = Don't count packets: False
        .... .... ...0 .... = Don't count bytes: False
    Pad: 0000
    Match
        Type: OFPMT_OXM (1)
        Length: 4
        Pad: 00000000
    Instruction
        Type: OFPIT_APPLY_ACTIONS (4)
        Length: 24
        Pad: 00000000
        Action
            Type: OFPAT_OUTPUT (0)
            Length: 16
            Port: OFPP_CONTROLLER (4294967293)
            Max length: OFPCML_NO_BUFFER (65535)
            Pad: 000000000000

PACKET_IN 和 PACKET_OUT 报文

上文提到,交换机在初始阶段只有一条默认流表项:

mininet> dpctl dump-flows
*** s1 ------------------------------------------------------------------------
 cookie=0x0, duration=161.361s, table=0, n_packets=19, n_bytes=1466, priority=0 actions=CONTROLLER:65535

因此, 当交换机收到主机发的第一个数据包时(如,在 mininet 执行 h1 ping h2),会通过 PACKET_IN 报文, 将该数据包转发到控制器,

Frame 4: 150 bytes on wire (1200 bits), 150 bytes captured (1200 bits) on interface 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 51750, Dst Port: 6653, Seq: 9, Ack: 9, Len: 84
OpenFlow 1.3
    Version: 1.3 (0x04)
    Type: OFPT_PACKET_IN (10)
    Length: 84
    Transaction ID: 0
    Buffer ID: OFP_NO_BUFFER (4294967295)
    Total length: 42
    Reason: OFPR_NO_MATCH (0)
    Table ID: 0
    Cookie: 0x0000000000000000
    Match
        (略)

控制器收到 PACKET_IN 报文,会根据程序逻辑(本文中就是 ryu/ryu/app/simple_switch_13.py 中的处理逻辑),生成相应的流表项,然后以 PACKET_OUT 报文,将流表项返回给交换机:

Frame 5: 148 bytes on wire (1184 bits), 148 bytes captured (1184 bits) on interface 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 6653, Dst Port: 51750, Seq: 9, Ack: 93, Len: 82
OpenFlow 1.3
    Version: 1.3 (0x04)
    Type: OFPT_PACKET_OUT (13)
    Length: 82
    Transaction ID: 3977916314
    Buffer ID: OFP_NO_BUFFER (4294967295)
    In port: 1
    Actions length: 16
    Pad: 000000000000
    Action
        (略)

交换机收到 PACKET_OUT 报文后,将流表项应用于数据包的转发。

ECHO 报文

控制器与交换机之间,通过 ECHO 报文来保持连接的活性:

Frame 1: 74 bytes on wire (592 bits), 74 bytes captured (592 bits) on interface 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 51750, Dst Port: 6653, Seq: 1, Ack: 1, Len: 8
OpenFlow 1.3
    Version: 1.3 (0x04)
    Type: OFPT_ECHO_REQUEST (2)
    Length: 8
    Transaction ID: 0

Frame 2: 74 bytes on wire (592 bits), 74 bytes captured (592 bits) on interface 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 6653, Dst Port: 51750, Seq: 1, Ack: 9, Len: 8
OpenFlow 1.3
    Version: 1.3 (0x04)
    Type: OFPT_ECHO_REPLY (3)
    Length: 8
    Transaction ID: 0

总结

RYU 控制器是 SDN 软件定义网络中的重要一环,使用 OpenFlow 协议作为南向接口来与交换机进行通信。RYU 对开发者而言是非常友好和容易理解的。至于交换机接收到 RYU 的流表信息,如何作用到数据包的转发,则需要在后续的学习中找到答案。

参考资料


程序员灯塔
转载请注明原文链接:SDN 控制器初探
喜欢 (0)