blob: c803a62282215997351b6f583b381bdb12657def [file] [log] [blame]
Matteo Scandoloa229eca2017-08-08 13:05:28 -07001
2# Copyright 2017-present Open Networking Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
ShreyaPandita9306c772012-09-28 12:21:40 -040017"""These tests fall under Conformance Test-Suite (OF-SWITCH-1.0.0 TestCases).
18 Refer Documentation -- Detailed testing methodology
19 <Some of test-cases are directly taken from oftest> """
20
21"Test Suite 2 --> Openflow Protocol messages"
22
23
24import logging
25
26import unittest
27import random
28
Rich Lane477f4812012-10-04 22:49:00 -070029from oftest import config
ShreyaPandita9306c772012-09-28 12:21:40 -040030import oftest.controller as controller
Rich Laned7b0ffa2013-03-08 15:53:42 -080031import ofp
ShreyaPandita9306c772012-09-28 12:21:40 -040032import oftest.dataplane as dataplane
ShreyaPandita9306c772012-09-28 12:21:40 -040033import oftest.parse as parse
Rich Laneb90a1c42012-10-05 09:16:05 -070034import oftest.base_tests as base_tests
ShreyaPandita9306c772012-09-28 12:21:40 -040035
Rich Laneda3b5ad2012-10-03 09:05:32 -070036from oftest.testutils import *
ShreyaPandita9306c772012-09-28 12:21:40 -040037from time import sleep
38from FuncUtils import *
39
Rich Laneb90a1c42012-10-05 09:16:05 -070040class FeaturesRequest(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -040041
42 """Verify Features_Request-Reply is implemented
43 a) Send OFPT_FEATURES_REQUEST
44 b) Verify OFPT_FEATURES_REPLY is received without errors"""
45
46 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -070047 logging.info("Running Features_Request test")
ShreyaPandita9306c772012-09-28 12:21:40 -040048
Rich Lane477f4812012-10-04 22:49:00 -070049 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -040050 of_ports.sort()
51
52 #Clear switch state
Rich Lane32bf9482013-01-03 17:26:30 -080053 delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -040054
Rich Lane9a003812012-10-04 17:17:59 -070055 logging.info("Sending Features_Request")
56 logging.info("Expecting Features_Reply")
ShreyaPandita9306c772012-09-28 12:21:40 -040057
Rich Lane28fa9272013-03-08 16:00:25 -080058 request = ofp.message.features_request()
Rich Lane5c3151c2013-01-03 17:15:41 -080059 self.controller.message_send(request)
ShreyaPandita9306c772012-09-28 12:21:40 -040060
61 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_FEATURES_REPLY,
62 timeout=2)
63 self.assertTrue(response is not None,
64 'Did not receive Features Reply')
65
66
Rich Laneb90a1c42012-10-05 09:16:05 -070067class ConfigurationRequest(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -040068
69 """Check basic Get Config request is implemented
70 a) Send OFPT_GET_CONFIG_REQUEST
71 b) Verify OFPT_GET_CONFIG_REPLY is received without errors"""
72
73 def runTest(self):
74
Rich Lane9a003812012-10-04 17:17:59 -070075 logging.info("Running Configuration_Request test ")
ShreyaPandita9306c772012-09-28 12:21:40 -040076
Rich Lane477f4812012-10-04 22:49:00 -070077 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -040078 of_ports.sort()
79
80 #Clear switch state
Rich Lane32bf9482013-01-03 17:26:30 -080081 delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -040082
Rich Lane9a003812012-10-04 17:17:59 -070083 logging.info("Sending OFPT_GET_CONFIG_REQUEST ")
84 logging.info("Expecting OFPT_GET_CONFIG_REPLY ")
ShreyaPandita9306c772012-09-28 12:21:40 -040085
Rich Lane28fa9272013-03-08 16:00:25 -080086 request = ofp.message.get_config_request()
Rich Lane5c3151c2013-01-03 17:15:41 -080087 self.controller.message_send(request)
ShreyaPandita9306c772012-09-28 12:21:40 -040088
89 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
90 timeout=2)
91 self.assertTrue(response is not None,
92 'Did not receive OFPT_GET_CONFIG_REPLY')
93
Rich Laneb90a1c42012-10-05 09:16:05 -070094class ModifyStateAdd(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -040095
96 """Check basic Flow Add request is implemented
97 a) Send OFPT_FLOW_MOD , command = OFPFC_ADD
98 c) Send ofp_table_stats request , verify active_count=1 in reply"""
99
100 def runTest(self):
101
Rich Lane9a003812012-10-04 17:17:59 -0700102 logging.info("Running Modify_State_Add test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400103
Rich Lane477f4812012-10-04 22:49:00 -0700104 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400105 of_ports.sort()
106
107 #Clear switch state
Rich Lane32bf9482013-01-03 17:26:30 -0800108 delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400109
Rich Lane9a003812012-10-04 17:17:59 -0700110 logging.info("Inserting a flow entry")
111 logging.info("Expecting active_count=1 in table_stats_reply")
ShreyaPandita9306c772012-09-28 12:21:40 -0400112
113 #Insert a flow entry matching on ingress_port
ShreyaPandita8dab4662012-11-02 13:40:14 -0400114 (pkt,match) = wildcard_all_except_ingress(self,of_ports)
ShreyaPandita9306c772012-09-28 12:21:40 -0400115
116 # Send Table_Stats_Request and verify flow gets inserted.
ShreyaPandita8dab4662012-11-02 13:40:14 -0400117 verify_tablestats(self,expect_active=1)
ShreyaPandita9306c772012-09-28 12:21:40 -0400118
119
Rich Laneb90a1c42012-10-05 09:16:05 -0700120class ModifyStateDelete(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400121
122 """Check Basic Flow Delete request is implemented
123 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD
124 b) Send ofp_table_stats request , verify active_count=1 in reply
125 c) Send OFPT_FLOW_MOD, command = OFPFC_DELETE
126 c) Send ofp_table_stats request , verify active_count=0 in reply"""
127
128 def runTest(self):
129
Rich Lane9a003812012-10-04 17:17:59 -0700130 logging.info("Running Modify_State_Delete test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400131
Rich Lane477f4812012-10-04 22:49:00 -0700132 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400133 of_ports.sort()
134
135 #Clear switch state
Rich Lane32bf9482013-01-03 17:26:30 -0800136 delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400137
Rich Lane9a003812012-10-04 17:17:59 -0700138 logging.info("Inserting a flow entry and then deleting it")
139 logging.info("Expecting the active_count=0 in table_stats_reply")
ShreyaPandita9306c772012-09-28 12:21:40 -0400140
141 #Insert a flow matching on ingress_port
ShreyaPandita8dab4662012-11-02 13:40:14 -0400142 (pkt,match) = wildcard_all_except_ingress(self,of_ports)
ShreyaPandita9306c772012-09-28 12:21:40 -0400143
144 #Verify Flow inserted.
ShreyaPandita8dab4662012-11-02 13:40:14 -0400145 verify_tablestats(self,expect_active=1)
ShreyaPandita9306c772012-09-28 12:21:40 -0400146
147 #Delete the flow
ShreyaPandita8dab4662012-11-02 13:40:14 -0400148 nonstrict_delete(self,match)
ShreyaPandita9306c772012-09-28 12:21:40 -0400149
150 # Send Table_Stats_Request and verify flow deleted.
ShreyaPandita8dab4662012-11-02 13:40:14 -0400151 verify_tablestats(self,expect_active=0)
ShreyaPandita9306c772012-09-28 12:21:40 -0400152
153
154
Rich Laneb90a1c42012-10-05 09:16:05 -0700155class ModifyStateModify(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400156
157 """Verify basic Flow Modify request is implemented
158 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD, Action A
159 b) Send OFPT_FLOW_MOD, command = OFPFC_MODIFY , with output action A'
160 c) Send a packet matching the flow, verify packet implements action A' """
161
162 def runTest(self):
163
Rich Lane9a003812012-10-04 17:17:59 -0700164 logging.info("Running Modify_State_Modify test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400165
Rich Lane477f4812012-10-04 22:49:00 -0700166 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400167 of_ports.sort()
168
169 #Clear switch state
Rich Lane32bf9482013-01-03 17:26:30 -0800170 delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400171
Rich Lane9a003812012-10-04 17:17:59 -0700172 logging.info("Inserting a flow entry and then modifying it")
173 logging.info("Expecting the Test Packet to implement the modified action")
ShreyaPandita9306c772012-09-28 12:21:40 -0400174
175 # Insert a flow matching on ingress_port with action A (output to of_port[1])
ShreyaPandita8dab4662012-11-02 13:40:14 -0400176 (pkt,match) = wildcard_all_except_ingress(self,of_ports)
ShreyaPandita9306c772012-09-28 12:21:40 -0400177
178 # Modify the flow action (output to of_port[2])
ShreyaPandita8dab4662012-11-02 13:40:14 -0400179 modify_flow_action(self,of_ports,match)
ShreyaPandita9306c772012-09-28 12:21:40 -0400180
181 # Send the Test Packet and verify action implemented is A' (output to of_port[2])
ShreyaPandita8dab4662012-11-02 13:40:14 -0400182 send_packet(self,pkt,of_ports[0],of_ports[2])
ShreyaPandita9306c772012-09-28 12:21:40 -0400183
184
Rich Laneb90a1c42012-10-05 09:16:05 -0700185class ReadState(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400186
187 """Test that a basic Read state request (like flow_stats_get request) does not generate an error
188 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD
189 b) Send ofp_flow_stats request
190 b) Verify switch replies without errors"""
191
192 def runTest(self):
193
Rich Lane9a003812012-10-04 17:17:59 -0700194 logging.info("Running Read_State test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400195
Rich Lane477f4812012-10-04 22:49:00 -0700196 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400197 of_ports.sort()
198
199 #Clear switch state
Rich Lane32bf9482013-01-03 17:26:30 -0800200 delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400201
Rich Lane9a003812012-10-04 17:17:59 -0700202 logging.info("Inserting a flow entry and then sending flow_stats request")
203 logging.info("Expecting the a flow_stats_reply without errors")
ShreyaPandita9306c772012-09-28 12:21:40 -0400204
205 # Insert a flow with match on ingress_port
ShreyaPandita8dab4662012-11-02 13:40:14 -0400206 (pkt,match ) = wildcard_all_except_ingress(self,of_ports)
ShreyaPandita9306c772012-09-28 12:21:40 -0400207
208 #Verify Flow_Stats request does not generate errors
ShreyaPandita8dab4662012-11-02 13:40:14 -0400209 get_flowstats(self,match)
ShreyaPandita9306c772012-09-28 12:21:40 -0400210
Rich Laneb90a1c42012-10-05 09:16:05 -0700211class PacketOut(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400212
213 """Test packet out function
214 a) Send packet out message for each dataplane port.
215 b) Verify the packet appears on the appropriate dataplane port"""
216
217 def runTest(self):
218
Rich Lane9a003812012-10-04 17:17:59 -0700219 logging.info("Running Packet_Out test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400220
Rich Lane477f4812012-10-04 22:49:00 -0700221 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400222 of_ports.sort()
223
224 #Clear Switch state
Rich Lane32bf9482013-01-03 17:26:30 -0800225 delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400226
Rich Lane9a003812012-10-04 17:17:59 -0700227 logging.info("Sending a packet-out for each dataplane port")
228 logging.info("Expecting the packet on appropriate dataplane port")
ShreyaPandita9306c772012-09-28 12:21:40 -0400229
230 for dp_port in of_ports:
231 for outpkt, opt in [
232 (simple_tcp_packet(), "simple TCP packet"),
233 (simple_eth_packet(), "simple Ethernet packet"),
234 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
235
Rich Lane28fa9272013-03-08 16:00:25 -0800236 msg = ofp.message.packet_out()
ShreyaPandita9306c772012-09-28 12:21:40 -0400237 msg.data = str(outpkt)
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800238 act = ofp.action.output()
ShreyaPandita9306c772012-09-28 12:21:40 -0400239 act.port = dp_port
Rich Lanec495d9e2013-03-08 17:43:36 -0800240 msg.actions.append(act)
Rich Laneea8c4722013-04-04 15:30:20 -0700241 msg.buffer_id = 0xffffffff
ShreyaPandita9306c772012-09-28 12:21:40 -0400242
Rich Lane9a003812012-10-04 17:17:59 -0700243 logging.info("PacketOut to: " + str(dp_port))
Rich Lane5c3151c2013-01-03 17:15:41 -0800244 self.controller.message_send(msg)
ShreyaPandita9306c772012-09-28 12:21:40 -0400245
246 exp_pkt_arg = None
247 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700248 if config["relax"]:
ShreyaPandita9306c772012-09-28 12:21:40 -0400249 exp_pkt_arg = outpkt
250 exp_port = dp_port
251 (of_port, pkt, pkt_time) = self.dataplane.poll(timeout=2,
252 port_number=exp_port,
253 exp_pkt=exp_pkt_arg)
254
255 self.assertTrue(pkt is not None, 'Packet not received')
Rich Lane9a003812012-10-04 17:17:59 -0700256 logging.info("PacketOut: got pkt from " + str(of_port))
ShreyaPandita9306c772012-09-28 12:21:40 -0400257 if of_port is not None:
258 self.assertEqual(of_port, dp_port, "Unexpected receive port")
259 if not dataplane.match_exp_pkt(outpkt, pkt):
Rich Lane9a003812012-10-04 17:17:59 -0700260 logging.debug("Sent %s" % format_packet(outpkt))
261 logging.debug("Resp %s" % format_packet(
ShreyaPandita9306c772012-09-28 12:21:40 -0400262 str(pkt)[:len(str(outpkt))]))
263 self.assertEqual(str(outpkt), str(pkt)[:len(str(outpkt))],
264 'Response packet does not match send packet')
265
266
Rich Laneb90a1c42012-10-05 09:16:05 -0700267class PacketIn(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400268
269 """Test basic packet_in function
270 a) Send a simple tcp packet to a dataplane port, without any flow-entry
271 b) Verify that a packet_in event is sent to the controller"""
272
273 def runTest(self):
274
Rich Lane9a003812012-10-04 17:17:59 -0700275 logging.info("Running Packet_In test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400276
Rich Lane477f4812012-10-04 22:49:00 -0700277 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400278 of_ports.sort()
279 ingress_port = of_ports[0]
280
281 #Clear Switch state
Rich Lane32bf9482013-01-03 17:26:30 -0800282 delete_all_flows(self.controller)
Rich Lane3a261d52013-01-03 17:45:08 -0800283 do_barrier(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400284
Rich Lane9a003812012-10-04 17:17:59 -0700285 logging.info("Sending a Simple tcp packet a dataplane port")
286 logging.info("Expecting a packet_in event on the control plane")
ShreyaPandita9306c772012-09-28 12:21:40 -0400287
288 # Send packet on dataplane port and verify packet_in event gets generated.
289 pkt = simple_tcp_packet()
290 self.dataplane.send(ingress_port, str(pkt))
Rich Lane9a003812012-10-04 17:17:59 -0700291 logging.info("Sending packet to dp port " + str(ingress_port) +
ShreyaPandita9306c772012-09-28 12:21:40 -0400292 ", expecting packet_in on control plane" )
293
Rich Lane4c504f32013-06-07 17:24:14 -0700294 verify_packet_in(self, str(pkt), ingress_port, ofp.OFPR_NO_MATCH)
ShreyaPandita9306c772012-09-28 12:21:40 -0400295
296
Rich Laneb90a1c42012-10-05 09:16:05 -0700297class EchoWithoutBody(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400298
299 """Test basic echo-reply is implemented
300 a) Send echo-request from the controller side, note echo body is empty here.
301 b) Verify switch responds back with echo-reply with same xid """
302
303 def runTest(self):
304
Rich Lane9a003812012-10-04 17:17:59 -0700305 logging.info("Running Echo_Without_Body test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400306
Rich Lane9a003812012-10-04 17:17:59 -0700307 logging.info("Sending Echo Request")
308 logging.info("Expecting a Echo Reply with version--1.0.0 and same xid")
ShreyaPandita9306c772012-09-28 12:21:40 -0400309
310 # Send echo_request
Rich Lane28fa9272013-03-08 16:00:25 -0800311 request = ofp.message.echo_request()
ShreyaPandita9306c772012-09-28 12:21:40 -0400312 (response, pkt) = self.controller.transact(request)
Rich Laneb73808c2013-03-11 15:22:23 -0700313 self.assertEqual(response.type, ofp.OFPT_ECHO_REPLY,'response is not echo_reply')
314 self.assertEqual(request.xid, response.xid,
ShreyaPandita9306c772012-09-28 12:21:40 -0400315 'response xid != request xid')
Rich Laneb73808c2013-03-11 15:22:23 -0700316 self.assertTrue(response.version == 0x01, 'switch openflow-version field is not 1.0.1')
ShreyaPandita9306c772012-09-28 12:21:40 -0400317 self.assertEqual(len(response.data), 0, 'response data non-empty')
318
319
Rich Laneb90a1c42012-10-05 09:16:05 -0700320class BarrierRequestReply(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400321
322 """ Check basic Barrier request is implemented
323 a) Send OFPT_BARRIER_REQUEST
324 c) Verify OFPT_BARRIER_REPLY is recieved"""
325
326 def runTest(self):
327
Rich Lane9a003812012-10-04 17:17:59 -0700328 logging.info("Running Barrier_Request_Reply test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400329
Rich Lane9a003812012-10-04 17:17:59 -0700330 logging.info("Sending Barrier Request")
331 logging.info("Expecting a Barrier Reply with same xid")
ShreyaPandita9306c772012-09-28 12:21:40 -0400332
333 #Send Barrier Request
Rich Lane28fa9272013-03-08 16:00:25 -0800334 request = ofp.message.barrier_request()
ShreyaPandita8dab4662012-11-02 13:40:14 -0400335 (response,pkt) = self.controller.transact(request)
Rich Laneb73808c2013-03-11 15:22:23 -0700336 self.assertEqual(response.type, ofp.OFPT_BARRIER_REPLY,'response is not barrier_reply')
337 self.assertEqual(request.xid, response.xid,
ShreyaPandita9306c772012-09-28 12:21:40 -0400338 'response xid != request xid')
339
340
341
342
343