blob: 80828c1f4da2ce7105b07245256effd9e5e044c9 [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()
46 rv = self.controller.message_send(request)
47 self.assertTrue(rv != -1, "Not able to send features request.")
48
49 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_FEATURES_REPLY,
50 timeout=2)
51 self.assertTrue(response is not None,
52 'Did not receive Features Reply')
53
54
Rich Laneb90a1c42012-10-05 09:16:05 -070055class ConfigurationRequest(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -040056
57 """Check basic Get Config request is implemented
58 a) Send OFPT_GET_CONFIG_REQUEST
59 b) Verify OFPT_GET_CONFIG_REPLY is received without errors"""
60
61 def runTest(self):
62
Rich Lane9a003812012-10-04 17:17:59 -070063 logging.info("Running Configuration_Request test ")
ShreyaPandita9306c772012-09-28 12:21:40 -040064
Rich Lane477f4812012-10-04 22:49:00 -070065 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -040066 of_ports.sort()
67
68 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -070069 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -040070 self.assertEqual(rc, 0, "Failed to delete all flows")
71
Rich Lane9a003812012-10-04 17:17:59 -070072 logging.info("Sending OFPT_GET_CONFIG_REQUEST ")
73 logging.info("Expecting OFPT_GET_CONFIG_REPLY ")
ShreyaPandita9306c772012-09-28 12:21:40 -040074
75 request = message.get_config_request()
76 rv = self.controller.message_send(request)
77 self.assertTrue(rv != -1, " Not able to send get_config request.")
78
79 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
80 timeout=2)
81 self.assertTrue(response is not None,
82 'Did not receive OFPT_GET_CONFIG_REPLY')
83
Rich Laneb90a1c42012-10-05 09:16:05 -070084class ModifyStateAdd(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -040085
86 """Check basic Flow Add request is implemented
87 a) Send OFPT_FLOW_MOD , command = OFPFC_ADD
88 c) Send ofp_table_stats request , verify active_count=1 in reply"""
89
90 def runTest(self):
91
Rich Lane9a003812012-10-04 17:17:59 -070092 logging.info("Running Modify_State_Add test")
ShreyaPandita9306c772012-09-28 12:21:40 -040093
Rich Lane477f4812012-10-04 22:49:00 -070094 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -040095 of_ports.sort()
96
97 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -070098 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -040099 self.assertEqual(rc, 0, "Failed to delete all flows")
100
Rich Lane9a003812012-10-04 17:17:59 -0700101 logging.info("Inserting a flow entry")
102 logging.info("Expecting active_count=1 in table_stats_reply")
ShreyaPandita9306c772012-09-28 12:21:40 -0400103
104 #Insert a flow entry matching on ingress_port
ShreyaPandita8dab4662012-11-02 13:40:14 -0400105 (pkt,match) = wildcard_all_except_ingress(self,of_ports)
ShreyaPandita9306c772012-09-28 12:21:40 -0400106
107 # Send Table_Stats_Request and verify flow gets inserted.
ShreyaPandita8dab4662012-11-02 13:40:14 -0400108 verify_tablestats(self,expect_active=1)
ShreyaPandita9306c772012-09-28 12:21:40 -0400109
110
Rich Laneb90a1c42012-10-05 09:16:05 -0700111class ModifyStateDelete(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400112
113 """Check Basic Flow Delete request is implemented
114 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD
115 b) Send ofp_table_stats request , verify active_count=1 in reply
116 c) Send OFPT_FLOW_MOD, command = OFPFC_DELETE
117 c) Send ofp_table_stats request , verify active_count=0 in reply"""
118
119 def runTest(self):
120
Rich Lane9a003812012-10-04 17:17:59 -0700121 logging.info("Running Modify_State_Delete test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400122
Rich Lane477f4812012-10-04 22:49:00 -0700123 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400124 of_ports.sort()
125
126 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700127 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400128 self.assertEqual(rc, 0, "Failed to delete all flows")
129
Rich Lane9a003812012-10-04 17:17:59 -0700130 logging.info("Inserting a flow entry and then deleting it")
131 logging.info("Expecting the active_count=0 in table_stats_reply")
ShreyaPandita9306c772012-09-28 12:21:40 -0400132
133 #Insert a flow matching on ingress_port
ShreyaPandita8dab4662012-11-02 13:40:14 -0400134 (pkt,match) = wildcard_all_except_ingress(self,of_ports)
ShreyaPandita9306c772012-09-28 12:21:40 -0400135
136 #Verify Flow inserted.
ShreyaPandita8dab4662012-11-02 13:40:14 -0400137 verify_tablestats(self,expect_active=1)
ShreyaPandita9306c772012-09-28 12:21:40 -0400138
139 #Delete the flow
ShreyaPandita8dab4662012-11-02 13:40:14 -0400140 nonstrict_delete(self,match)
ShreyaPandita9306c772012-09-28 12:21:40 -0400141
142 # Send Table_Stats_Request and verify flow deleted.
ShreyaPandita8dab4662012-11-02 13:40:14 -0400143 verify_tablestats(self,expect_active=0)
ShreyaPandita9306c772012-09-28 12:21:40 -0400144
145
146
Rich Laneb90a1c42012-10-05 09:16:05 -0700147class ModifyStateModify(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400148
149 """Verify basic Flow Modify request is implemented
150 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD, Action A
151 b) Send OFPT_FLOW_MOD, command = OFPFC_MODIFY , with output action A'
152 c) Send a packet matching the flow, verify packet implements action A' """
153
154 def runTest(self):
155
Rich Lane9a003812012-10-04 17:17:59 -0700156 logging.info("Running Modify_State_Modify test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400157
Rich Lane477f4812012-10-04 22:49:00 -0700158 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400159 of_ports.sort()
160
161 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700162 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400163 self.assertEqual(rc, 0, "Failed to delete all flows")
164
Rich Lane9a003812012-10-04 17:17:59 -0700165 logging.info("Inserting a flow entry and then modifying it")
166 logging.info("Expecting the Test Packet to implement the modified action")
ShreyaPandita9306c772012-09-28 12:21:40 -0400167
168 # Insert a flow matching on ingress_port with action A (output to of_port[1])
ShreyaPandita8dab4662012-11-02 13:40:14 -0400169 (pkt,match) = wildcard_all_except_ingress(self,of_ports)
ShreyaPandita9306c772012-09-28 12:21:40 -0400170
171 # Modify the flow action (output to of_port[2])
ShreyaPandita8dab4662012-11-02 13:40:14 -0400172 modify_flow_action(self,of_ports,match)
ShreyaPandita9306c772012-09-28 12:21:40 -0400173
174 # Send the Test Packet and verify action implemented is A' (output to of_port[2])
ShreyaPandita8dab4662012-11-02 13:40:14 -0400175 send_packet(self,pkt,of_ports[0],of_ports[2])
ShreyaPandita9306c772012-09-28 12:21:40 -0400176
177
Rich Laneb90a1c42012-10-05 09:16:05 -0700178class ReadState(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400179
180 """Test that a basic Read state request (like flow_stats_get request) does not generate an error
181 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD
182 b) Send ofp_flow_stats request
183 b) Verify switch replies without errors"""
184
185 def runTest(self):
186
Rich Lane9a003812012-10-04 17:17:59 -0700187 logging.info("Running Read_State test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400188
Rich Lane477f4812012-10-04 22:49:00 -0700189 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400190 of_ports.sort()
191
192 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700193 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400194 self.assertEqual(rc, 0, "Failed to delete all flows")
195
Rich Lane9a003812012-10-04 17:17:59 -0700196 logging.info("Inserting a flow entry and then sending flow_stats request")
197 logging.info("Expecting the a flow_stats_reply without errors")
ShreyaPandita9306c772012-09-28 12:21:40 -0400198
199 # Insert a flow with match on ingress_port
ShreyaPandita8dab4662012-11-02 13:40:14 -0400200 (pkt,match ) = wildcard_all_except_ingress(self,of_ports)
ShreyaPandita9306c772012-09-28 12:21:40 -0400201
202 #Verify Flow_Stats request does not generate errors
ShreyaPandita8dab4662012-11-02 13:40:14 -0400203 get_flowstats(self,match)
ShreyaPandita9306c772012-09-28 12:21:40 -0400204
Rich Laneb90a1c42012-10-05 09:16:05 -0700205class PacketOut(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400206
207 """Test packet out function
208 a) Send packet out message for each dataplane port.
209 b) Verify the packet appears on the appropriate dataplane port"""
210
211 def runTest(self):
212
Rich Lane9a003812012-10-04 17:17:59 -0700213 logging.info("Running Packet_Out test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400214
Rich Lane477f4812012-10-04 22:49:00 -0700215 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400216 of_ports.sort()
217
218 #Clear Switch state
Rich Lane9a003812012-10-04 17:17:59 -0700219 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400220 self.assertEqual(rc, 0, "Failed to delete all flows")
221
Rich Lane9a003812012-10-04 17:17:59 -0700222 logging.info("Sending a packet-out for each dataplane port")
223 logging.info("Expecting the packet on appropriate dataplane port")
ShreyaPandita9306c772012-09-28 12:21:40 -0400224
225 for dp_port in of_ports:
226 for outpkt, opt in [
227 (simple_tcp_packet(), "simple TCP packet"),
228 (simple_eth_packet(), "simple Ethernet packet"),
229 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
230
231 msg = message.packet_out()
232 msg.data = str(outpkt)
233 act = action.action_output()
234 act.port = dp_port
235 self.assertTrue(msg.actions.add(act), 'Could not add action to msg')
236
Rich Lane9a003812012-10-04 17:17:59 -0700237 logging.info("PacketOut to: " + str(dp_port))
ShreyaPandita9306c772012-09-28 12:21:40 -0400238 rv = self.controller.message_send(msg)
239 self.assertTrue(rv == 0, "Error sending out message")
240
241 exp_pkt_arg = None
242 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700243 if config["relax"]:
ShreyaPandita9306c772012-09-28 12:21:40 -0400244 exp_pkt_arg = outpkt
245 exp_port = dp_port
246 (of_port, pkt, pkt_time) = self.dataplane.poll(timeout=2,
247 port_number=exp_port,
248 exp_pkt=exp_pkt_arg)
249
250 self.assertTrue(pkt is not None, 'Packet not received')
Rich Lane9a003812012-10-04 17:17:59 -0700251 logging.info("PacketOut: got pkt from " + str(of_port))
ShreyaPandita9306c772012-09-28 12:21:40 -0400252 if of_port is not None:
253 self.assertEqual(of_port, dp_port, "Unexpected receive port")
254 if not dataplane.match_exp_pkt(outpkt, pkt):
Rich Lane9a003812012-10-04 17:17:59 -0700255 logging.debug("Sent %s" % format_packet(outpkt))
256 logging.debug("Resp %s" % format_packet(
ShreyaPandita9306c772012-09-28 12:21:40 -0400257 str(pkt)[:len(str(outpkt))]))
258 self.assertEqual(str(outpkt), str(pkt)[:len(str(outpkt))],
259 'Response packet does not match send packet')
260
261
Rich Laneb90a1c42012-10-05 09:16:05 -0700262class PacketIn(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400263
264 """Test basic packet_in function
265 a) Send a simple tcp packet to a dataplane port, without any flow-entry
266 b) Verify that a packet_in event is sent to the controller"""
267
268 def runTest(self):
269
Rich Lane9a003812012-10-04 17:17:59 -0700270 logging.info("Running Packet_In test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400271
Rich Lane477f4812012-10-04 22:49:00 -0700272 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400273 of_ports.sort()
274 ingress_port = of_ports[0]
275
276 #Clear Switch state
Rich Lane9a003812012-10-04 17:17:59 -0700277 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400278 self.assertEqual(rc, 0, "Failed to delete all flows")
279 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
280
Rich Lane9a003812012-10-04 17:17:59 -0700281 logging.info("Sending a Simple tcp packet a dataplane port")
282 logging.info("Expecting a packet_in event on the control plane")
ShreyaPandita9306c772012-09-28 12:21:40 -0400283
284 # Send packet on dataplane port and verify packet_in event gets generated.
285 pkt = simple_tcp_packet()
286 self.dataplane.send(ingress_port, str(pkt))
Rich Lane9a003812012-10-04 17:17:59 -0700287 logging.info("Sending packet to dp port " + str(ingress_port) +
ShreyaPandita9306c772012-09-28 12:21:40 -0400288 ", expecting packet_in on control plane" )
289
290 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_PACKET_IN,
291 timeout=2)
292 self.assertTrue(response is not None,
293 'Packet in event is not sent to the controller')
294
295
Rich Laneb90a1c42012-10-05 09:16:05 -0700296class Hello(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400297
298 """Test Hello messages are implemented
299 a) Create Hello messages from controller
300 b) Verify switch also exchanges hello message -- (Poll the control plane)
301 d) Verify the version field in the hello messages is openflow 1.0.0 """
302
303 def runTest(self):
304
Rich Lane9a003812012-10-04 17:17:59 -0700305 logging.info("Running Hello test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400306
Rich Lane9a003812012-10-04 17:17:59 -0700307 logging.info("Sending Hello")
308 logging.info("Expecting a Hello on the control plane with version--1.0.0")
ShreyaPandita9306c772012-09-28 12:21:40 -0400309
310 #Send Hello message
311 request = message.hello()
312 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_HELLO,
313 timeout=1)
314 self.assertTrue(response is not None,
315 'Switch did not exchange hello message in return')
316 self.assertTrue(response.header.version == 0x01, 'switch openflow-version field is not 1.0.0')
317
318
319
Rich Laneb90a1c42012-10-05 09:16:05 -0700320class EchoWithoutBody(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400321
322 """Test basic echo-reply is implemented
323 a) Send echo-request from the controller side, note echo body is empty here.
324 b) Verify switch responds back with echo-reply with same xid """
325
326 def runTest(self):
327
Rich Lane9a003812012-10-04 17:17:59 -0700328 logging.info("Running Echo_Without_Body test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400329
Rich Lane9a003812012-10-04 17:17:59 -0700330 logging.info("Sending Echo Request")
331 logging.info("Expecting a Echo Reply with version--1.0.0 and same xid")
ShreyaPandita9306c772012-09-28 12:21:40 -0400332
333 # Send echo_request
334 request = message.echo_request()
335 (response, pkt) = self.controller.transact(request)
336 self.assertEqual(response.header.type, ofp.OFPT_ECHO_REPLY,'response is not echo_reply')
337 self.assertEqual(request.header.xid, response.header.xid,
338 'response xid != request xid')
339 self.assertTrue(response.header.version == 0x01, 'switch openflow-version field is not 1.0.1')
340 self.assertEqual(len(response.data), 0, 'response data non-empty')
341
342
Rich Laneb90a1c42012-10-05 09:16:05 -0700343class BarrierRequestReply(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400344
345 """ Check basic Barrier request is implemented
346 a) Send OFPT_BARRIER_REQUEST
347 c) Verify OFPT_BARRIER_REPLY is recieved"""
348
349 def runTest(self):
350
Rich Lane9a003812012-10-04 17:17:59 -0700351 logging.info("Running Barrier_Request_Reply test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400352
Rich Lane9a003812012-10-04 17:17:59 -0700353 logging.info("Sending Barrier Request")
354 logging.info("Expecting a Barrier Reply with same xid")
ShreyaPandita9306c772012-09-28 12:21:40 -0400355
356 #Send Barrier Request
357 request = message.barrier_request()
ShreyaPandita8dab4662012-11-02 13:40:14 -0400358 (response,pkt) = self.controller.transact(request)
ShreyaPandita9306c772012-09-28 12:21:40 -0400359 self.assertEqual(response.header.type, ofp.OFPT_BARRIER_REPLY,'response is not barrier_reply')
360 self.assertEqual(request.header.xid, response.header.xid,
361 'response xid != request xid')
362
363
364
365
366