OpenDayLight 还是根据实验自己操作。

0x01 流表结构

OpenFlow1.3的流表结构:

1、匹配域:

​ 和OpenFlow1.0流表的包头域是相同的,涵盖了ISO网络模型中的第二至第四层的网络配置信息;所以可根据需求分为二三四层进行流表下发:

入端口 目的MAC地址 以太网类型 VLAN ID VLAN 优先级 源IP地址 目的IP地址 IP协议 IP TOS位 TCP/UDP源端口 TCP/UDP目的端口
Ingress Port Ehter Des Ether Type VLAN ID VLAN Priority IP Src IP Dst IP Proto IP TOS bits TCP/UDP Src Port TCP/UDP Dst Port

2、优先级:流表项的匹配次序。

3、计数器:

​ 计数器可以针对交换机中每条流表、每个数据流、每个设备端口、每个转发队列进行维护,用于统计数据流表的相关信息。

4、Instructions指令集:

​ 每个流表项都包含一组指令,当一个数据包匹配表项时指令会被执行。这些指令可以更改数据包,动作集或者流表处理。

5、超时:最大时间计数或流有效时间

6、cookie:

​ 由控制器选择的不透明数据值。控制器用来过滤流统计数据、流改变和流删除。但处理数据包时不能使用。

0x02 匹配域解析流程:

​ 当SDN交换机接收到一个数据包时,将按照优先级从table0依次匹配其本地保存的流表中的表项,并以发生具有最高优先级的匹配表项作为匹配结果,并根据相应的动作对数据包进行操作。同时,一旦匹配成功,对应的计数器将更新;而如果没能找到匹配的表项,则将数据包转发给控制器。

  1. 初始化包头域,按照包头域的组成—设置每个字段,其中入端口是接收数据包的物理端口。
  2. 如果数据包类型是VLAN(0x8100),那么就使用VLAN
    ID和PCP字段进行表查找,解封以太网类型为先的以太网类型解析做准备。
  3. (可选)如果是ARP数据包(0x0806),那么匹配字段就可能包含IP源和目的地址。
  4. 如果是IP数据包(0x0800),那么匹配字段就会包含IP首部。如果IP数据包的分段偏移量不为0或者设置了多个分段bit位,那么将所有传输端口设为0。如果IP数据包在IP协议族中的编号为6或者17(分别是TCP/UDP类型),那么匹配字段包含传输端口。如果编号为1(ICMP数据包)则包含Type和Code字段。

OpenFlow1.3匹配流程如下:

  • 可以通过报文的入端口或者元数据信息来进行报文的匹配,一个流表项中可以同时存在多个匹配项,一个报文需要同时普票流表项中所有匹配项才能匹配该流表项。
  • 报文匹配按照现有的报文字段进行,比如前一个流表通过apply-actions改变了该报文的某个字段,则下一个表现按照修改后的字段进行匹配。如果匹配成功;则按照指令集里的动作更新动作集,活更新报文/匹配集字段,或更新元数据和计数器。
  • 根据指令是否继续前往下一个流表,不继续则终止匹配流程执行动作集,如果指令要去继续前往下一流表则继续匹配,下一个流表的ID需要比当前流表ID大。
  • 当报文匹配失败,如果存在无匹配流表项(table-miss)就按照该表项执行指令,一般是将报文转发给控制器、丢弃或者转发给其他流表。如果没有table-miss表项则默认丢弃该报文。

0x03 实验环境

Postman调用ODL下发流表、可以本地搭建环境,下发时端口8080和8181都可以

  • 启动控制器:netstat -an|grep 6633查看OpenDaylight是否工作正常

  • 登录交换机:ovs-vsctl show查看交换机是否成功连接远端控制器

    如果没有连接:

    ovs-vsctl del-controller br-sw,删除br-sw(网桥名)的控制器

    ovs-vsctl set-contoller br-sw tcp:Controller_ip:6633 连接地址为Controller_ip的控制器

  • 登录两个主机查看IP地址

    以下内容均在本地利用Mininet搭建环境实现的。

    实验拓扑如下:

  • 登录控制器,运行Postman:

    返回交换机id信息,从返回信息也能得到交换机的node-id是:openflow: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
    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
    {
    "network-topology": {
    "topology": [
    {
    "topology-id": "flow:1",
    "node": [
    {
    "node-id": "host:00:00:00:00:00:02",
    "termination-point": [
    {
    "tp-id": "host:00:00:00:00:00:02"
    }
    ],
    "host-tracker-service:addresses": [
    {
    "id": 4,
    "mac": "00:00:00:00:00:02",
    "last-seen": 1594214716094,
    "ip": "10.0.0.2",
    "first-seen": 1594214716094
    }
    ],
    "host-tracker-service:attachment-points": [
    {
    "tp-id": "openflow:1:2",
    "corresponding-tp": "host:00:00:00:00:00:02",
    "active": true
    }
    ],
    "host-tracker-service:id": "00:00:00:00:00:02"
    },
    {
    "node-id": "host:00:00:00:00:00:01",
    "termination-point": [
    {
    "tp-id": "host:00:00:00:00:00:01"
    }
    ],
    "host-tracker-service:addresses": [
    {
    "id": 3,
    "mac": "00:00:00:00:00:01",
    "last-seen": 1594214716093,
    "ip": "10.0.0.1",
    "first-seen": 1594214716093
    }
    ],
    "host-tracker-service:attachment-points": [
    {
    "tp-id": "openflow:1:1",
    "corresponding-tp": "host:00:00:00:00:00:01",
    "active": true
    }
    ],
    "host-tracker-service:id": "00:00:00:00:00:01"
    },
    {
    "node-id": "openflow:1",
    "opendaylight-topology-inventory:inventory-node-ref": "/opendaylight-inventory:nodes/opendaylight-inventory:node[opendaylight-inventory:id='openflow:1']",
    "termination-point": [
    {
    "tp-id": "openflow:1:1",
    "opendaylight-topology-inventory:inventory-node-connector-ref": "/opendaylight-inventory:nodes/opendaylight-inventory:node[opendaylight-inventory:id='openflow:1']/opendaylight-inventory:node-connector[opendaylight-inventory:id='openflow:1:1']"
    },
    {
    "tp-id": "openflow:1:LOCAL",
    "opendaylight-topology-inventory:inventory-node-connector-ref": "/opendaylight-inventory:nodes/opendaylight-inventory:node[opendaylight-inventory:id='openflow:1']/opendaylight-inventory:node-connector[opendaylight-inventory:id='openflow:1:LOCAL']"
    },
    {
    "tp-id": "openflow:1:2",
    "opendaylight-topology-inventory:inventory-node-connector-ref": "/opendaylight-inventory:nodes/opendaylight-inventory:node[opendaylight-inventory:id='openflow:1']/opendaylight-inventory:node-connector[opendaylight-inventory:id='openflow:1:2']"
    }
    ]
    }
    ],
    "link": [
    {
    "link-id": "openflow:1:2/host:00:00:00:00:00:02",
    "source": {
    "source-node": "openflow:1",
    "source-tp": "openflow:1:2"
    },
    "destination": {
    "dest-node": "host:00:00:00:00:00:02",
    "dest-tp": "host:00:00:00:00:00:02"
    }
    },
    {
    "link-id": "openflow:1:1/host:00:00:00:00:00:01",
    "source": {
    "source-node": "openflow:1",
    "source-tp": "openflow:1:1"
    },
    "destination": {
    "dest-node": "host:00:00:00:00:00:01",
    "dest-tp": "host:00:00:00:00:00:01"
    }
    },
    {
    "link-id": "host:00:00:00:00:00:02/openflow:1:2",
    "source": {
    "source-node": "host:00:00:00:00:00:02",
    "source-tp": "host:00:00:00:00:00:02"
    },
    "destination": {
    "dest-node": "openflow:1",
    "dest-tp": "openflow:1:2"
    }
    },
    {
    "link-id": "host:00:00:00:00:00:01/openflow:1:1",
    "source": {
    "source-node": "host:00:00:00:00:00:01",
    "source-tp": "host:00:00:00:00:00:01"
    },
    "destination": {
    "dest-node": "openflow:1",
    "dest-tp": "openflow:1:1"
    }
    }
    ]
    }
    ]
    }
    }

json的本质就是一个字典,只不过信息量一般比较多。

0x04 流表的下发

1.L2层流表下发与验证

L2层即对应OSI模型的二层,也就是说通过匹配源MAC(Ether source)、目的MAC地址(Ether dst)、以太网类型(Ether Type)VLAN id、VLAN优先级等字段来实现流的转发。本实验将基于源和目的MAC进行数据流的转发。

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
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="urn:opendaylight:flow:inventory">
<priority>200</priority>
<flow-name>Foo1</flow-name>
<idle-timeout>0</idle-timeout>
<hard-timeout>0</hard-timeout>
<match>
<ethernet-match>
<ethernet-source>
<address>00:00:00:00:00:01</address>
</ethernet-source>
<ethernet-destination>
<address>00:00:00:00:00:02</address>
</ethernet-destination>
</ethernet-match>
</match>
<id>107</id>
<table_id>0</table_id>
<instructions>
<instruction>
<order>0</order>
<apply-actions>
<action>
<order>0</order>
<output-action>
<output-node-connector>2</output-node-connector>
</output-action>
</action>
</apply-actions>
</instruction>
</instructions>
</flow>

参数说明:

  • Priority:匹配流表的优先级。
  • flow-name:流表的名称。
  • idle-timeout:设定超时时间(seconds),参数为0表示永不超时。
  • hard-timeout:最大超时时间(seconds),参数为0表示永不超时。
  • match:匹配Fields。
  • instructions:修改action配置或pipeline处理。
  • ethernet-source:源MAC地址。
  • ethernet-destination:目的MAC地址。
  • 流表查询:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    root@SDN:/home/low/Desktop# ovs-ofctl dump-flows s1
    NXST_FLOW reply (xid=0x4):
    cookie=0x0, duration=49.262s, table=0, n_packets=0, n_bytes=0, idle_age=49, priority=200,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02 actions=output:2
    cookie=0x2b00000000000001, duration=324.868s, table=0, n_packets=0, n_bytes=0, idle_age=324, priority=100,dl_type=0x88cc actions=CONTROLLER:65535
    cookie=0x2b00000000000003, duration=322.871s, table=0, n_packets=9, n_bytes=650, idle_age=85, priority=2,in_port=2 actions=output:1,CONTROLLER:65535
    cookie=0x2b00000000000004, duration=322.871s, table=0, n_packets=10, n_bytes=740, idle_age=77, priority=2,in_port=1 actions=output:2,CONTROLLER:65535
    cookie=0x2b00000000000001, duration=324.868s, table=0, n_packets=7, n_bytes=622, idle_age=323, priority=0 actions=drop


  • 流表删除:

    提交方式:“DELETE”

    URL内容:“http://{controller-ip}:8080/restconf/config/opendaylight-inventory:nodes/node/{node-id}/table/{table-id}/flow/{flow-id}。”

    1
    2
    3
    4
    5
    6
    root@SDN:/home/low/Desktop# ovs-ofctl dump-flows s1
    NXST_FLOW reply (xid=0x4):
    cookie=0x2b00000000000001, duration=402.008s, table=0, n_packets=0, n_bytes=0, idle_age=402, priority=100,dl_type=0x88cc actions=CONTROLLER:65535
    cookie=0x2b00000000000003, duration=400.011s, table=0, n_packets=9, n_bytes=650, idle_age=162, priority=2,in_port=2 actions=output:1,CONTROLLER:65535
    cookie=0x2b00000000000004, duration=400.011s, table=0, n_packets=10, n_bytes=740, idle_age=154, priority=2,in_port=1 actions=output:2,CONTROLLER:65535
    cookie=0x2b00000000000001, duration=402.008s, table=0, n_packets=7, n_bytes=622, idle_age=400, priority=0 actions=drop

2.L3层流表下发与验证

L3层对应OSI模型的三层,三层流表主要匹配的是IP包的协议类型和IP地址。

下发、验证和删除和L2层相同,此处不再赘述。

场景1:匹配IP地址

匹配源IP地址为10.0.0.1/32的报文,并将其转发到2端口。注意ethernet-type为2048(0x0800)代表IPv4;

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
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="urn:opendaylight:flow:inventory">
<priority>200</priority>
<flow-name>Foo1</flow-name>
<idle-timeout>0</idle-timeout>
<hard-timeout>0</hard-timeout>
<match>
<ethernet-match>
<ethernet-type>
<type>2048</type>
</ethernet-type>
</ethernet-match>
<ipv4-source>10.0.0.1/32</ipv4-source>
</match>
<id>111</id>
<table_id>0</table_id>
<instructions>
<instruction>
<order>0</order>
<apply-actions>
<action>
<order>0</order>
<output-action>
<output-node-connector>2</output-node-connector>
</output-action>
</action>
</apply-actions>
</instruction>
</instructions>
</flow>

协议字段补充:

协议 字段值
IPv4 0x0800
ARP 0x0806
PPPoE 0x8864
IPv6 0x86DD
MPLS Label 0x8847
802.1Q tag 0x8100

场景二 匹配nw_proto字段

匹配到目的IP地址为10.0.0.2/32的ICMP报文,并将其转发到2端口。注意ip-protocol为1,代表ICMP。

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
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="urn:opendaylight:flow:inventory">
<priority>200</priority>
<flow-name>Foo1</flow-name>
<idle-timeout>0</idle-timeout>
<hard-timeout>0</hard-timeout>
<match>
<ethernet-match>
<ethernet-type>
<type>2048</type>
</ethernet-type>
</ethernet-match>
<ipv4-destination>10.0.0.2/32</ipv4-destination>
<ip-match>
<ip-protocol>1</ip-protocol>
</ip-match>
</match>
<id>114</id>
<table_id>0</table_id>
<instructions>
<instruction>
<order>0</order>
<apply-actions>
<action>
<order>0</order>
<output-action>
<output-node-connector>2</output-node-connector>
</output-action>
</action>
</apply-actions>
</instruction>
</instructions>
</flow>

IP协议字段(Protocol)补充:

数值 值描述
0 保留字段,用于IPv6(跳跃点到跳跃点选项)
1 Internet控制消息 (ICMP)
2 Internet组管理 (IGMP)
3 网关到网关 (GGP)
4 1P中的IP(封装)
5
6 传输控制 (TCP)
7 CBT
8 外部网关协议 (EGP)
9 任何私有内部网关(Cisco在它的IGRP实现中使用) (IGP)
10 BBNRCC监视
11 网络语音协议
12 PUP
13 ARGUS
14 EMCON
15 网络诊断工具
16 混乱(Chaos)
17 用户数据报文 (UDP)
18 复用
19 DCN测量子系统
20 主机监视
21 包无线测量
22 XEROXNSIDP
23 Trunk-1
24 Trunk-2
25 leaf-1
26 1eaf-2
27 可靠的数据协议
28 Internet可靠交易
29 1SO传输协议第四类 (TP4)
30 大块数据传输协议
31 MFE网络服务协议
32 MERIT节点之间协议
33 序列交换协议
34 第三方连接协议
35 域之间策略路由协议
36 XTP
37 数据报文传递协议
38 IDPR控制消息传输协议
39 TP+ +传输协议
40 IL传输协议
41 1Pv6
42 资源命令路由协议
43 1Pv6的路由报头
44 1Pv6的片报头
45 域之间路由协议
46 保留协议
47 通用路由封装
48 可移动主机路由协议
49 BNA
50 1Pv6封装安全有效负载
51 1Pv6验证报头
52 集成的网络层安全TUBA
53 带加密的IP
54 NBMA地址解析协议
55 IP可移动性
56 使用Kryptonet钥匙管理的传输层安全协议
57 SKIP
58 1Pv6的ICMP
59 1Pv6的无下一个报头
60 IPv6的信宿选项
61 任何主机内部协议
62 CFTP
63 任何本地网络
64 SATNET和BackroomEXPAK
65 Kryptolan
66 MIT远程虚拟磁盘协议
67 Internet Pluribus包核心
68 任何分布式文件系统
69 SATNET监视
70 VISA协议
71 Internet包核心工具
72 计算机协议Network Executive
73 计算机协议Heart Beat
74 Wang Span网络
75 包视频协议
76 Backroom SATNET监视
77 SUN ND PROTOCOL—临时
78 WIDEBAND监视
79 WIDEBAND EXPAK
80 ISO Internet协议
81 VMTP
82 SECURE—VMTP(安全的VMTP)
83 VINES
84 TTP
85 NSFNET—IGP
86 不同网关协议
87 TCF
88 EIGRP
89 OSPF IGP
90 Sprite RPC协议
9] Locus地址解析协议
92 多播传输协议
93 AX.25帧
94 IP内部的IP封装协议
95 可移动网络互连控制协议
96 旗语通讯安全协议
97 IP中的以太封装
98 封装报头
99 任何私有加密方案
100 GMTP
101 Ipsilon流量管理协议
102 PNNI over IP
103 协议独立多播
104 ARIS
105 SCPS
106 QNX
107 活动网络
108 IP有效负载压缩协议
109 Sitara网络协议
110 Compaq对等协议
111 IP中的IPX
112 虚拟路由器冗余协议
113 PGM可靠传输协议
114 任何0跳跃协议
115 第二层隧道协议
116 D-II数据交换(DDX)
117 交互式代理传输协议
118 日程计划传输协议
119 SpectraLink无线协议
120 UTI
121 简单消息协议
122 SM
123 性能透明性协议
124 ISIS over IPv4
125 FIRE
126 Combat无线传输协议
127 Combat无线用户数据报文
128 SSCOPMCE
129 IPLT
130 安全包防护
131 IP中的私有IP封装
132 流控制传输协议
133~254 未分配
255 保留

3.L4层流表下发与验证

L4对应的OSI模型中的四层,即流表对应的TCP/UDP源端口(TCP/UDP src port)、TCP/UDP目的端口号(TCP/UDP dst port)字段。本实验匹配TCP目的端口。

流表:匹配到目的IP地址为10.0.0.2/32且目的端口为5001的TCP报文,将其转发到2端口。

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
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="urn:opendaylight:flow:inventory">
<priority>200</priority>
<flow-name>Foo1</flow-name>
<idle-timeout>0</idle-timeout>
<hard-timeout>0</hard-timeout>
<match>
<tcp-destination-port>5001</tcp-destination-port>
<ethernet-match>
<ethernet-type>
<type>2048</type>
</ethernet-type>
</ethernet-match>
<ipv4-destination>10.0.0.2/32</ipv4-destination>
<ip-match>
<ip-protocol>6</ip-protocol>
</ip-match>
</match>
<id>117</id>
<table_id>0</table_id>
<instructions>
<instruction>
<order>0</order>
<apply-actions>
<action>
<order>0</order>
<output-action>
<output-node-connector>2</output-node-connector>
</output-action>
</action>
</apply-actions>
</instruction>
</instructions>
</flow>

流表:下发arp匹配流表。注意arp匹配的格式。

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
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="urn:opendaylight:flow:inventory">
<priority>200</priority>
<flow-name>Foo1</flow-name>
<idle-timeout>0</idle-timeout>
<hard-timeout>0</hard-timeout>
<match>
<ethernet-match>
<ethernet-type>
<type>2054</type>
</ethernet-type>
</ethernet-match>
</match>
<id>119</id>
<table_id>0</table_id>
<instructions>
<instruction>
<order>0</order>
<apply-actions>
<action>
<order>0</order>
<output-action>
<output-node-connector>FLOOD</output-node-connector>
<max-length>0</max-length>
</output-action>
</action>
</apply-actions>
</instruction>
</instructions>
</flow>

补充:

丢弃:

1
2
3
4
<action>
<order>0</order>
<drop-action></drop-action>
</action>
1
2
3
root@SDN:/home/low/Desktop# ovs-ofctl dump-flows s1
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=5.603s, table=0, n_packets=0, n_bytes=0, idle_age=5, priority=200,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02 actions=drop