blob: 037209de66efc514ba434d5d18f140487b1ecfb2 [file] [log] [blame]
ShreyaPandita9306c772012-09-28 12:21:40 -04001"""These tests fall under Conformance Test-Suite (OF-SWITCH-1.0.0 TestCases).
2 Refer Documentation -- Detailed testing methodology
3 <Some of test-cases are directly taken from oftest> """
4
5"Test Suite 2 --> Openflow Protocol messages"
6
7
8import logging
9
10import unittest
11import random
12
Rich Lane477f4812012-10-04 22:49:00 -070013from oftest import config
ShreyaPandita9306c772012-09-28 12:21:40 -040014import oftest.controller as controller
15import oftest.cstruct as ofp
16import oftest.message as message
17import oftest.dataplane as dataplane
18import oftest.action as action
19import oftest.parse as parse
Rich Laneb90a1c42012-10-05 09:16:05 -070020import oftest.base_tests as base_tests
ShreyaPandita9306c772012-09-28 12:21:40 -040021
Rich Laneda3b5ad2012-10-03 09:05:32 -070022from oftest.testutils import *
ShreyaPandita9306c772012-09-28 12:21:40 -040023from time import sleep
24from FuncUtils import *
25
Rich Laneb90a1c42012-10-05 09:16:05 -070026class FeaturesRequest(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -040027
28 """Verify Features_Request-Reply is implemented
29 a) Send OFPT_FEATURES_REQUEST
30 b) Verify OFPT_FEATURES_REPLY is received without errors"""
31
32 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -070033 logging.info("Running Features_Request test")
ShreyaPandita9306c772012-09-28 12:21:40 -040034
Rich Lane477f4812012-10-04 22:49:00 -070035 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -040036 of_ports.sort()
37
38 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -070039 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -040040 self.assertEqual(rc, 0, "Failed to delete all flows")
41
Rich Lane9a003812012-10-04 17:17:59 -070042 logging.info("Sending Features_Request")
43 logging.info("Expecting Features_Reply")
ShreyaPandita9306c772012-09-28 12:21:40 -040044
45 request = message.features_request()
Rich Lane5c3151c2013-01-03 17:15:41 -080046 self.controller.message_send(request)
ShreyaPandita9306c772012-09-28 12:21:40 -040047
48 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_FEATURES_REPLY,
49 timeout=2)
50 self.assertTrue(response is not None,
51 'Did not receive Features Reply')
52
53
Rich Laneb90a1c42012-10-05 09:16:05 -070054class ConfigurationRequest(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -040055
56 """Check basic Get Config request is implemented
57 a) Send OFPT_GET_CONFIG_REQUEST
58 b) Verify OFPT_GET_CONFIG_REPLY is received without errors"""
59
60 def runTest(self):
61
Rich Lane9a003812012-10-04 17:17:59 -070062 logging.info("Running Configuration_Request test ")
ShreyaPandita9306c772012-09-28 12:21:40 -040063
Rich Lane477f4812012-10-04 22:49:00 -070064 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -040065 of_ports.sort()
66
67 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -070068 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -040069 self.assertEqual(rc, 0, "Failed to delete all flows")
70
Rich Lane9a003812012-10-04 17:17:59 -070071 logging.info("Sending OFPT_GET_CONFIG_REQUEST ")
72 logging.info("Expecting OFPT_GET_CONFIG_REPLY ")
ShreyaPandita9306c772012-09-28 12:21:40 -040073
74 request = message.get_config_request()
Rich Lane5c3151c2013-01-03 17:15:41 -080075 self.controller.message_send(request)
ShreyaPandita9306c772012-09-28 12:21:40 -040076
77 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
78 timeout=2)
79 self.assertTrue(response is not None,
80 'Did not receive OFPT_GET_CONFIG_REPLY')
81
Rich Laneb90a1c42012-10-05 09:16:05 -070082class ModifyStateAdd(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -040083
84 """Check basic Flow Add request is implemented
85 a) Send OFPT_FLOW_MOD , command = OFPFC_ADD
86 c) Send ofp_table_stats request , verify active_count=1 in reply"""
87
88 def runTest(self):
89
Rich Lane9a003812012-10-04 17:17:59 -070090 logging.info("Running Modify_State_Add test")
ShreyaPandita9306c772012-09-28 12:21:40 -040091
Rich Lane477f4812012-10-04 22:49:00 -070092 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -040093 of_ports.sort()
94
95 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -070096 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -040097 self.assertEqual(rc, 0, "Failed to delete all flows")
98
Rich Lane9a003812012-10-04 17:17:59 -070099 logging.info("Inserting a flow entry")
100 logging.info("Expecting active_count=1 in table_stats_reply")
ShreyaPandita9306c772012-09-28 12:21:40 -0400101
102 #Insert a flow entry matching on ingress_port
ShreyaPandita8dab4662012-11-02 13:40:14 -0400103 (pkt,match) = wildcard_all_except_ingress(self,of_ports)
ShreyaPandita9306c772012-09-28 12:21:40 -0400104
105 # Send Table_Stats_Request and verify flow gets inserted.
ShreyaPandita8dab4662012-11-02 13:40:14 -0400106 verify_tablestats(self,expect_active=1)
ShreyaPandita9306c772012-09-28 12:21:40 -0400107
108
Rich Laneb90a1c42012-10-05 09:16:05 -0700109class ModifyStateDelete(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400110
111 """Check Basic Flow Delete request is implemented
112 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD
113 b) Send ofp_table_stats request , verify active_count=1 in reply
114 c) Send OFPT_FLOW_MOD, command = OFPFC_DELETE
115 c) Send ofp_table_stats request , verify active_count=0 in reply"""
116
117 def runTest(self):
118
Rich Lane9a003812012-10-04 17:17:59 -0700119 logging.info("Running Modify_State_Delete test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400120
Rich Lane477f4812012-10-04 22:49:00 -0700121 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400122 of_ports.sort()
123
124 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700125 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400126 self.assertEqual(rc, 0, "Failed to delete all flows")
127
Rich Lane9a003812012-10-04 17:17:59 -0700128 logging.info("Inserting a flow entry and then deleting it")
129 logging.info("Expecting the active_count=0 in table_stats_reply")
ShreyaPandita9306c772012-09-28 12:21:40 -0400130
131 #Insert a flow matching on ingress_port
ShreyaPandita8dab4662012-11-02 13:40:14 -0400132 (pkt,match) = wildcard_all_except_ingress(self,of_ports)
ShreyaPandita9306c772012-09-28 12:21:40 -0400133
134 #Verify Flow inserted.
ShreyaPandita8dab4662012-11-02 13:40:14 -0400135 verify_tablestats(self,expect_active=1)
ShreyaPandita9306c772012-09-28 12:21:40 -0400136
137 #Delete the flow
ShreyaPandita8dab4662012-11-02 13:40:14 -0400138 nonstrict_delete(self,match)
ShreyaPandita9306c772012-09-28 12:21:40 -0400139
140 # Send Table_Stats_Request and verify flow deleted.
ShreyaPandita8dab4662012-11-02 13:40:14 -0400141 verify_tablestats(self,expect_active=0)
ShreyaPandita9306c772012-09-28 12:21:40 -0400142
143
144
Rich Laneb90a1c42012-10-05 09:16:05 -0700145class ModifyStateModify(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400146
147 """Verify basic Flow Modify request is implemented
148 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD, Action A
149 b) Send OFPT_FLOW_MOD, command = OFPFC_MODIFY , with output action A'
150 c) Send a packet matching the flow, verify packet implements action A' """
151
152 def runTest(self):
153
Rich Lane9a003812012-10-04 17:17:59 -0700154 logging.info("Running Modify_State_Modify test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400155
Rich Lane477f4812012-10-04 22:49:00 -0700156 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400157 of_ports.sort()
158
159 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700160 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400161 self.assertEqual(rc, 0, "Failed to delete all flows")
162
Rich Lane9a003812012-10-04 17:17:59 -0700163 logging.info("Inserting a flow entry and then modifying it")
164 logging.info("Expecting the Test Packet to implement the modified action")
ShreyaPandita9306c772012-09-28 12:21:40 -0400165
166 # Insert a flow matching on ingress_port with action A (output to of_port[1])
ShreyaPandita8dab4662012-11-02 13:40:14 -0400167 (pkt,match) = wildcard_all_except_ingress(self,of_ports)
ShreyaPandita9306c772012-09-28 12:21:40 -0400168
169 # Modify the flow action (output to of_port[2])
ShreyaPandita8dab4662012-11-02 13:40:14 -0400170 modify_flow_action(self,of_ports,match)
ShreyaPandita9306c772012-09-28 12:21:40 -0400171
172 # Send the Test Packet and verify action implemented is A' (output to of_port[2])
ShreyaPandita8dab4662012-11-02 13:40:14 -0400173 send_packet(self,pkt,of_ports[0],of_ports[2])
ShreyaPandita9306c772012-09-28 12:21:40 -0400174
175
Rich Laneb90a1c42012-10-05 09:16:05 -0700176class ReadState(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400177
178 """Test that a basic Read state request (like flow_stats_get request) does not generate an error
179 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD
180 b) Send ofp_flow_stats request
181 b) Verify switch replies without errors"""
182
183 def runTest(self):
184
Rich Lane9a003812012-10-04 17:17:59 -0700185 logging.info("Running Read_State test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400186
Rich Lane477f4812012-10-04 22:49:00 -0700187 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400188 of_ports.sort()
189
190 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700191 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400192 self.assertEqual(rc, 0, "Failed to delete all flows")
193
Rich Lane9a003812012-10-04 17:17:59 -0700194 logging.info("Inserting a flow entry and then sending flow_stats request")
195 logging.info("Expecting the a flow_stats_reply without errors")
ShreyaPandita9306c772012-09-28 12:21:40 -0400196
197 # Insert a flow with match on ingress_port
ShreyaPandita8dab4662012-11-02 13:40:14 -0400198 (pkt,match ) = wildcard_all_except_ingress(self,of_ports)
ShreyaPandita9306c772012-09-28 12:21:40 -0400199
200 #Verify Flow_Stats request does not generate errors
ShreyaPandita8dab4662012-11-02 13:40:14 -0400201 get_flowstats(self,match)
ShreyaPandita9306c772012-09-28 12:21:40 -0400202
Rich Laneb90a1c42012-10-05 09:16:05 -0700203class PacketOut(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400204
205 """Test packet out function
206 a) Send packet out message for each dataplane port.
207 b) Verify the packet appears on the appropriate dataplane port"""
208
209 def runTest(self):
210
Rich Lane9a003812012-10-04 17:17:59 -0700211 logging.info("Running Packet_Out test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400212
Rich Lane477f4812012-10-04 22:49:00 -0700213 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400214 of_ports.sort()
215
216 #Clear Switch state
Rich Lane9a003812012-10-04 17:17:59 -0700217 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400218 self.assertEqual(rc, 0, "Failed to delete all flows")
219
Rich Lane9a003812012-10-04 17:17:59 -0700220 logging.info("Sending a packet-out for each dataplane port")
221 logging.info("Expecting the packet on appropriate dataplane port")
ShreyaPandita9306c772012-09-28 12:21:40 -0400222
223 for dp_port in of_ports:
224 for outpkt, opt in [
225 (simple_tcp_packet(), "simple TCP packet"),
226 (simple_eth_packet(), "simple Ethernet packet"),
227 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
228
229 msg = message.packet_out()
230 msg.data = str(outpkt)
231 act = action.action_output()
232 act.port = dp_port
Rich Lanee30455b2013-01-03 16:24:44 -0800233 msg.actions.add(act)
ShreyaPandita9306c772012-09-28 12:21:40 -0400234
Rich Lane9a003812012-10-04 17:17:59 -0700235 logging.info("PacketOut to: " + str(dp_port))
Rich Lane5c3151c2013-01-03 17:15:41 -0800236 self.controller.message_send(msg)
ShreyaPandita9306c772012-09-28 12:21:40 -0400237
238 exp_pkt_arg = None
239 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700240 if config["relax"]:
ShreyaPandita9306c772012-09-28 12:21:40 -0400241 exp_pkt_arg = outpkt
242 exp_port = dp_port
243 (of_port, pkt, pkt_time) = self.dataplane.poll(timeout=2,
244 port_number=exp_port,
245 exp_pkt=exp_pkt_arg)
246
247 self.assertTrue(pkt is not None, 'Packet not received')
Rich Lane9a003812012-10-04 17:17:59 -0700248 logging.info("PacketOut: got pkt from " + str(of_port))
ShreyaPandita9306c772012-09-28 12:21:40 -0400249 if of_port is not None:
250 self.assertEqual(of_port, dp_port, "Unexpected receive port")
251 if not dataplane.match_exp_pkt(outpkt, pkt):
Rich Lane9a003812012-10-04 17:17:59 -0700252 logging.debug("Sent %s" % format_packet(outpkt))
253 logging.debug("Resp %s" % format_packet(
ShreyaPandita9306c772012-09-28 12:21:40 -0400254 str(pkt)[:len(str(outpkt))]))
255 self.assertEqual(str(outpkt), str(pkt)[:len(str(outpkt))],
256 'Response packet does not match send packet')
257
258
Rich Laneb90a1c42012-10-05 09:16:05 -0700259class PacketIn(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400260
261 """Test basic packet_in function
262 a) Send a simple tcp packet to a dataplane port, without any flow-entry
263 b) Verify that a packet_in event is sent to the controller"""
264
265 def runTest(self):
266
Rich Lane9a003812012-10-04 17:17:59 -0700267 logging.info("Running Packet_In test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400268
Rich Lane477f4812012-10-04 22:49:00 -0700269 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400270 of_ports.sort()
271 ingress_port = of_ports[0]
272
273 #Clear Switch state
Rich Lane9a003812012-10-04 17:17:59 -0700274 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400275 self.assertEqual(rc, 0, "Failed to delete all flows")
276 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
277
Rich Lane9a003812012-10-04 17:17:59 -0700278 logging.info("Sending a Simple tcp packet a dataplane port")
279 logging.info("Expecting a packet_in event on the control plane")
ShreyaPandita9306c772012-09-28 12:21:40 -0400280
281 # Send packet on dataplane port and verify packet_in event gets generated.
282 pkt = simple_tcp_packet()
283 self.dataplane.send(ingress_port, str(pkt))
Rich Lane9a003812012-10-04 17:17:59 -0700284 logging.info("Sending packet to dp port " + str(ingress_port) +
ShreyaPandita9306c772012-09-28 12:21:40 -0400285 ", expecting packet_in on control plane" )
286
287 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_PACKET_IN,
288 timeout=2)
289 self.assertTrue(response is not None,
290 'Packet in event is not sent to the controller')
291
292
Rich Laneb90a1c42012-10-05 09:16:05 -0700293class Hello(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400294
295 """Test Hello messages are implemented
296 a) Create Hello messages from controller
297 b) Verify switch also exchanges hello message -- (Poll the control plane)
298 d) Verify the version field in the hello messages is openflow 1.0.0 """
299
300 def runTest(self):
301
Rich Lane9a003812012-10-04 17:17:59 -0700302 logging.info("Running Hello test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400303
Rich Lane9a003812012-10-04 17:17:59 -0700304 logging.info("Sending Hello")
305 logging.info("Expecting a Hello on the control plane with version--1.0.0")
ShreyaPandita9306c772012-09-28 12:21:40 -0400306
307 #Send Hello message
308 request = message.hello()
309 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_HELLO,
310 timeout=1)
311 self.assertTrue(response is not None,
312 'Switch did not exchange hello message in return')
313 self.assertTrue(response.header.version == 0x01, 'switch openflow-version field is not 1.0.0')
314
315
316
Rich Laneb90a1c42012-10-05 09:16:05 -0700317class EchoWithoutBody(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400318
319 """Test basic echo-reply is implemented
320 a) Send echo-request from the controller side, note echo body is empty here.
321 b) Verify switch responds back with echo-reply with same xid """
322
323 def runTest(self):
324
Rich Lane9a003812012-10-04 17:17:59 -0700325 logging.info("Running Echo_Without_Body test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400326
Rich Lane9a003812012-10-04 17:17:59 -0700327 logging.info("Sending Echo Request")
328 logging.info("Expecting a Echo Reply with version--1.0.0 and same xid")
ShreyaPandita9306c772012-09-28 12:21:40 -0400329
330 # Send echo_request
331 request = message.echo_request()
332 (response, pkt) = self.controller.transact(request)
333 self.assertEqual(response.header.type, ofp.OFPT_ECHO_REPLY,'response is not echo_reply')
334 self.assertEqual(request.header.xid, response.header.xid,
335 'response xid != request xid')
336 self.assertTrue(response.header.version == 0x01, 'switch openflow-version field is not 1.0.1')
337 self.assertEqual(len(response.data), 0, 'response data non-empty')
338
339
Rich Laneb90a1c42012-10-05 09:16:05 -0700340class BarrierRequestReply(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400341
342 """ Check basic Barrier request is implemented
343 a) Send OFPT_BARRIER_REQUEST
344 c) Verify OFPT_BARRIER_REPLY is recieved"""
345
346 def runTest(self):
347
Rich Lane9a003812012-10-04 17:17:59 -0700348 logging.info("Running Barrier_Request_Reply test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400349
Rich Lane9a003812012-10-04 17:17:59 -0700350 logging.info("Sending Barrier Request")
351 logging.info("Expecting a Barrier Reply with same xid")
ShreyaPandita9306c772012-09-28 12:21:40 -0400352
353 #Send Barrier Request
354 request = message.barrier_request()
ShreyaPandita8dab4662012-11-02 13:40:14 -0400355 (response,pkt) = self.controller.transact(request)
ShreyaPandita9306c772012-09-28 12:21:40 -0400356 self.assertEqual(response.header.type, ofp.OFPT_BARRIER_REPLY,'response is not barrier_reply')
357 self.assertEqual(request.header.xid, response.header.xid,
358 'response xid != request xid')
359
360
361
362
363