blob: b1820157c956e155cc9cc8e679a1817d0b542c27 [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 Lane32bf9482013-01-03 17:26:30 -080039 delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -040040
Rich Lane9a003812012-10-04 17:17:59 -070041 logging.info("Sending Features_Request")
42 logging.info("Expecting Features_Reply")
ShreyaPandita9306c772012-09-28 12:21:40 -040043
44 request = message.features_request()
Rich Lane5c3151c2013-01-03 17:15:41 -080045 self.controller.message_send(request)
ShreyaPandita9306c772012-09-28 12:21:40 -040046
47 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_FEATURES_REPLY,
48 timeout=2)
49 self.assertTrue(response is not None,
50 'Did not receive Features Reply')
51
52
Rich Laneb90a1c42012-10-05 09:16:05 -070053class ConfigurationRequest(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -040054
55 """Check basic Get Config request is implemented
56 a) Send OFPT_GET_CONFIG_REQUEST
57 b) Verify OFPT_GET_CONFIG_REPLY is received without errors"""
58
59 def runTest(self):
60
Rich Lane9a003812012-10-04 17:17:59 -070061 logging.info("Running Configuration_Request test ")
ShreyaPandita9306c772012-09-28 12:21:40 -040062
Rich Lane477f4812012-10-04 22:49:00 -070063 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -040064 of_ports.sort()
65
66 #Clear switch state
Rich Lane32bf9482013-01-03 17:26:30 -080067 delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -040068
Rich Lane9a003812012-10-04 17:17:59 -070069 logging.info("Sending OFPT_GET_CONFIG_REQUEST ")
70 logging.info("Expecting OFPT_GET_CONFIG_REPLY ")
ShreyaPandita9306c772012-09-28 12:21:40 -040071
72 request = message.get_config_request()
Rich Lane5c3151c2013-01-03 17:15:41 -080073 self.controller.message_send(request)
ShreyaPandita9306c772012-09-28 12:21:40 -040074
75 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
76 timeout=2)
77 self.assertTrue(response is not None,
78 'Did not receive OFPT_GET_CONFIG_REPLY')
79
Rich Laneb90a1c42012-10-05 09:16:05 -070080class ModifyStateAdd(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -040081
82 """Check basic Flow Add request is implemented
83 a) Send OFPT_FLOW_MOD , command = OFPFC_ADD
84 c) Send ofp_table_stats request , verify active_count=1 in reply"""
85
86 def runTest(self):
87
Rich Lane9a003812012-10-04 17:17:59 -070088 logging.info("Running Modify_State_Add test")
ShreyaPandita9306c772012-09-28 12:21:40 -040089
Rich Lane477f4812012-10-04 22:49:00 -070090 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -040091 of_ports.sort()
92
93 #Clear switch state
Rich Lane32bf9482013-01-03 17:26:30 -080094 delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -040095
Rich Lane9a003812012-10-04 17:17:59 -070096 logging.info("Inserting a flow entry")
97 logging.info("Expecting active_count=1 in table_stats_reply")
ShreyaPandita9306c772012-09-28 12:21:40 -040098
99 #Insert a flow entry matching on ingress_port
ShreyaPandita8dab4662012-11-02 13:40:14 -0400100 (pkt,match) = wildcard_all_except_ingress(self,of_ports)
ShreyaPandita9306c772012-09-28 12:21:40 -0400101
102 # Send Table_Stats_Request and verify flow gets inserted.
ShreyaPandita8dab4662012-11-02 13:40:14 -0400103 verify_tablestats(self,expect_active=1)
ShreyaPandita9306c772012-09-28 12:21:40 -0400104
105
Rich Laneb90a1c42012-10-05 09:16:05 -0700106class ModifyStateDelete(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400107
108 """Check Basic Flow Delete request is implemented
109 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD
110 b) Send ofp_table_stats request , verify active_count=1 in reply
111 c) Send OFPT_FLOW_MOD, command = OFPFC_DELETE
112 c) Send ofp_table_stats request , verify active_count=0 in reply"""
113
114 def runTest(self):
115
Rich Lane9a003812012-10-04 17:17:59 -0700116 logging.info("Running Modify_State_Delete test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400117
Rich Lane477f4812012-10-04 22:49:00 -0700118 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400119 of_ports.sort()
120
121 #Clear switch state
Rich Lane32bf9482013-01-03 17:26:30 -0800122 delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400123
Rich Lane9a003812012-10-04 17:17:59 -0700124 logging.info("Inserting a flow entry and then deleting it")
125 logging.info("Expecting the active_count=0 in table_stats_reply")
ShreyaPandita9306c772012-09-28 12:21:40 -0400126
127 #Insert a flow matching on ingress_port
ShreyaPandita8dab4662012-11-02 13:40:14 -0400128 (pkt,match) = wildcard_all_except_ingress(self,of_ports)
ShreyaPandita9306c772012-09-28 12:21:40 -0400129
130 #Verify Flow inserted.
ShreyaPandita8dab4662012-11-02 13:40:14 -0400131 verify_tablestats(self,expect_active=1)
ShreyaPandita9306c772012-09-28 12:21:40 -0400132
133 #Delete the flow
ShreyaPandita8dab4662012-11-02 13:40:14 -0400134 nonstrict_delete(self,match)
ShreyaPandita9306c772012-09-28 12:21:40 -0400135
136 # Send Table_Stats_Request and verify flow deleted.
ShreyaPandita8dab4662012-11-02 13:40:14 -0400137 verify_tablestats(self,expect_active=0)
ShreyaPandita9306c772012-09-28 12:21:40 -0400138
139
140
Rich Laneb90a1c42012-10-05 09:16:05 -0700141class ModifyStateModify(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400142
143 """Verify basic Flow Modify request is implemented
144 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD, Action A
145 b) Send OFPT_FLOW_MOD, command = OFPFC_MODIFY , with output action A'
146 c) Send a packet matching the flow, verify packet implements action A' """
147
148 def runTest(self):
149
Rich Lane9a003812012-10-04 17:17:59 -0700150 logging.info("Running Modify_State_Modify test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400151
Rich Lane477f4812012-10-04 22:49:00 -0700152 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400153 of_ports.sort()
154
155 #Clear switch state
Rich Lane32bf9482013-01-03 17:26:30 -0800156 delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400157
Rich Lane9a003812012-10-04 17:17:59 -0700158 logging.info("Inserting a flow entry and then modifying it")
159 logging.info("Expecting the Test Packet to implement the modified action")
ShreyaPandita9306c772012-09-28 12:21:40 -0400160
161 # Insert a flow matching on ingress_port with action A (output to of_port[1])
ShreyaPandita8dab4662012-11-02 13:40:14 -0400162 (pkt,match) = wildcard_all_except_ingress(self,of_ports)
ShreyaPandita9306c772012-09-28 12:21:40 -0400163
164 # Modify the flow action (output to of_port[2])
ShreyaPandita8dab4662012-11-02 13:40:14 -0400165 modify_flow_action(self,of_ports,match)
ShreyaPandita9306c772012-09-28 12:21:40 -0400166
167 # Send the Test Packet and verify action implemented is A' (output to of_port[2])
ShreyaPandita8dab4662012-11-02 13:40:14 -0400168 send_packet(self,pkt,of_ports[0],of_ports[2])
ShreyaPandita9306c772012-09-28 12:21:40 -0400169
170
Rich Laneb90a1c42012-10-05 09:16:05 -0700171class ReadState(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400172
173 """Test that a basic Read state request (like flow_stats_get request) does not generate an error
174 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD
175 b) Send ofp_flow_stats request
176 b) Verify switch replies without errors"""
177
178 def runTest(self):
179
Rich Lane9a003812012-10-04 17:17:59 -0700180 logging.info("Running Read_State test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400181
Rich Lane477f4812012-10-04 22:49:00 -0700182 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400183 of_ports.sort()
184
185 #Clear switch state
Rich Lane32bf9482013-01-03 17:26:30 -0800186 delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400187
Rich Lane9a003812012-10-04 17:17:59 -0700188 logging.info("Inserting a flow entry and then sending flow_stats request")
189 logging.info("Expecting the a flow_stats_reply without errors")
ShreyaPandita9306c772012-09-28 12:21:40 -0400190
191 # Insert a flow with match on ingress_port
ShreyaPandita8dab4662012-11-02 13:40:14 -0400192 (pkt,match ) = wildcard_all_except_ingress(self,of_ports)
ShreyaPandita9306c772012-09-28 12:21:40 -0400193
194 #Verify Flow_Stats request does not generate errors
ShreyaPandita8dab4662012-11-02 13:40:14 -0400195 get_flowstats(self,match)
ShreyaPandita9306c772012-09-28 12:21:40 -0400196
Rich Laneb90a1c42012-10-05 09:16:05 -0700197class PacketOut(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400198
199 """Test packet out function
200 a) Send packet out message for each dataplane port.
201 b) Verify the packet appears on the appropriate dataplane port"""
202
203 def runTest(self):
204
Rich Lane9a003812012-10-04 17:17:59 -0700205 logging.info("Running Packet_Out test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400206
Rich Lane477f4812012-10-04 22:49:00 -0700207 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400208 of_ports.sort()
209
210 #Clear Switch state
Rich Lane32bf9482013-01-03 17:26:30 -0800211 delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400212
Rich Lane9a003812012-10-04 17:17:59 -0700213 logging.info("Sending a packet-out for each dataplane port")
214 logging.info("Expecting the packet on appropriate dataplane port")
ShreyaPandita9306c772012-09-28 12:21:40 -0400215
216 for dp_port in of_ports:
217 for outpkt, opt in [
218 (simple_tcp_packet(), "simple TCP packet"),
219 (simple_eth_packet(), "simple Ethernet packet"),
220 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
221
222 msg = message.packet_out()
223 msg.data = str(outpkt)
224 act = action.action_output()
225 act.port = dp_port
Rich Lanee30455b2013-01-03 16:24:44 -0800226 msg.actions.add(act)
ShreyaPandita9306c772012-09-28 12:21:40 -0400227
Rich Lane9a003812012-10-04 17:17:59 -0700228 logging.info("PacketOut to: " + str(dp_port))
Rich Lane5c3151c2013-01-03 17:15:41 -0800229 self.controller.message_send(msg)
ShreyaPandita9306c772012-09-28 12:21:40 -0400230
231 exp_pkt_arg = None
232 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700233 if config["relax"]:
ShreyaPandita9306c772012-09-28 12:21:40 -0400234 exp_pkt_arg = outpkt
235 exp_port = dp_port
236 (of_port, pkt, pkt_time) = self.dataplane.poll(timeout=2,
237 port_number=exp_port,
238 exp_pkt=exp_pkt_arg)
239
240 self.assertTrue(pkt is not None, 'Packet not received')
Rich Lane9a003812012-10-04 17:17:59 -0700241 logging.info("PacketOut: got pkt from " + str(of_port))
ShreyaPandita9306c772012-09-28 12:21:40 -0400242 if of_port is not None:
243 self.assertEqual(of_port, dp_port, "Unexpected receive port")
244 if not dataplane.match_exp_pkt(outpkt, pkt):
Rich Lane9a003812012-10-04 17:17:59 -0700245 logging.debug("Sent %s" % format_packet(outpkt))
246 logging.debug("Resp %s" % format_packet(
ShreyaPandita9306c772012-09-28 12:21:40 -0400247 str(pkt)[:len(str(outpkt))]))
248 self.assertEqual(str(outpkt), str(pkt)[:len(str(outpkt))],
249 'Response packet does not match send packet')
250
251
Rich Laneb90a1c42012-10-05 09:16:05 -0700252class PacketIn(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400253
254 """Test basic packet_in function
255 a) Send a simple tcp packet to a dataplane port, without any flow-entry
256 b) Verify that a packet_in event is sent to the controller"""
257
258 def runTest(self):
259
Rich Lane9a003812012-10-04 17:17:59 -0700260 logging.info("Running Packet_In test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400261
Rich Lane477f4812012-10-04 22:49:00 -0700262 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400263 of_ports.sort()
264 ingress_port = of_ports[0]
265
266 #Clear Switch state
Rich Lane32bf9482013-01-03 17:26:30 -0800267 delete_all_flows(self.controller)
Rich Lane3a261d52013-01-03 17:45:08 -0800268 do_barrier(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400269
Rich Lane9a003812012-10-04 17:17:59 -0700270 logging.info("Sending a Simple tcp packet a dataplane port")
271 logging.info("Expecting a packet_in event on the control plane")
ShreyaPandita9306c772012-09-28 12:21:40 -0400272
273 # Send packet on dataplane port and verify packet_in event gets generated.
274 pkt = simple_tcp_packet()
275 self.dataplane.send(ingress_port, str(pkt))
Rich Lane9a003812012-10-04 17:17:59 -0700276 logging.info("Sending packet to dp port " + str(ingress_port) +
ShreyaPandita9306c772012-09-28 12:21:40 -0400277 ", expecting packet_in on control plane" )
278
279 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_PACKET_IN,
280 timeout=2)
281 self.assertTrue(response is not None,
282 'Packet in event is not sent to the controller')
283
284
Rich Laneb90a1c42012-10-05 09:16:05 -0700285class Hello(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400286
287 """Test Hello messages are implemented
288 a) Create Hello messages from controller
289 b) Verify switch also exchanges hello message -- (Poll the control plane)
290 d) Verify the version field in the hello messages is openflow 1.0.0 """
291
292 def runTest(self):
293
Rich Lane9a003812012-10-04 17:17:59 -0700294 logging.info("Running Hello test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400295
Rich Lane9a003812012-10-04 17:17:59 -0700296 logging.info("Sending Hello")
297 logging.info("Expecting a Hello on the control plane with version--1.0.0")
ShreyaPandita9306c772012-09-28 12:21:40 -0400298
299 #Send Hello message
300 request = message.hello()
301 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_HELLO,
302 timeout=1)
303 self.assertTrue(response is not None,
304 'Switch did not exchange hello message in return')
305 self.assertTrue(response.header.version == 0x01, 'switch openflow-version field is not 1.0.0')
306
307
308
Rich Laneb90a1c42012-10-05 09:16:05 -0700309class EchoWithoutBody(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400310
311 """Test basic echo-reply is implemented
312 a) Send echo-request from the controller side, note echo body is empty here.
313 b) Verify switch responds back with echo-reply with same xid """
314
315 def runTest(self):
316
Rich Lane9a003812012-10-04 17:17:59 -0700317 logging.info("Running Echo_Without_Body test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400318
Rich Lane9a003812012-10-04 17:17:59 -0700319 logging.info("Sending Echo Request")
320 logging.info("Expecting a Echo Reply with version--1.0.0 and same xid")
ShreyaPandita9306c772012-09-28 12:21:40 -0400321
322 # Send echo_request
323 request = message.echo_request()
324 (response, pkt) = self.controller.transact(request)
325 self.assertEqual(response.header.type, ofp.OFPT_ECHO_REPLY,'response is not echo_reply')
326 self.assertEqual(request.header.xid, response.header.xid,
327 'response xid != request xid')
328 self.assertTrue(response.header.version == 0x01, 'switch openflow-version field is not 1.0.1')
329 self.assertEqual(len(response.data), 0, 'response data non-empty')
330
331
Rich Laneb90a1c42012-10-05 09:16:05 -0700332class BarrierRequestReply(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400333
334 """ Check basic Barrier request is implemented
335 a) Send OFPT_BARRIER_REQUEST
336 c) Verify OFPT_BARRIER_REPLY is recieved"""
337
338 def runTest(self):
339
Rich Lane9a003812012-10-04 17:17:59 -0700340 logging.info("Running Barrier_Request_Reply test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400341
Rich Lane9a003812012-10-04 17:17:59 -0700342 logging.info("Sending Barrier Request")
343 logging.info("Expecting a Barrier Reply with same xid")
ShreyaPandita9306c772012-09-28 12:21:40 -0400344
345 #Send Barrier Request
346 request = message.barrier_request()
ShreyaPandita8dab4662012-11-02 13:40:14 -0400347 (response,pkt) = self.controller.transact(request)
ShreyaPandita9306c772012-09-28 12:21:40 -0400348 self.assertEqual(response.header.type, ofp.OFPT_BARRIER_REPLY,'response is not barrier_reply')
349 self.assertEqual(request.header.xid, response.header.xid,
350 'response xid != request xid')
351
352
353
354
355