blob: 5f29da597cc1a058ceb2131e0ea5d6340f4a7f09 [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
13import oftest.controller as controller
14import oftest.cstruct as ofp
15import oftest.message as message
16import oftest.dataplane as dataplane
17import oftest.action as action
18import oftest.parse as parse
19import basic
20
Rich Laneda3b5ad2012-10-03 09:05:32 -070021from oftest.testutils import *
ShreyaPandita9306c772012-09-28 12:21:40 -040022from time import sleep
23from FuncUtils import *
24
25
26of_port_map = None
ShreyaPandita9306c772012-09-28 12:21:40 -040027of_config = None
28
29def test_set_init(config):
30
31
32 basic.test_set_init(config)
33
34 global of_port_map
ShreyaPandita9306c772012-09-28 12:21:40 -040035 global of_config
36
ShreyaPandita9306c772012-09-28 12:21:40 -040037 of_port_map = config["port_map"]
38 of_config = config
39
40
41class FeaturesRequest(basic.SimpleProtocol):
42
43 """Verify Features_Request-Reply is implemented
44 a) Send OFPT_FEATURES_REQUEST
45 b) Verify OFPT_FEATURES_REPLY is received without errors"""
46
47 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -070048 logging.info("Running Features_Request test")
ShreyaPandita9306c772012-09-28 12:21:40 -040049
50 of_ports = of_port_map.keys()
51 of_ports.sort()
52
53 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -070054 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -040055 self.assertEqual(rc, 0, "Failed to delete all flows")
56
Rich Lane9a003812012-10-04 17:17:59 -070057 logging.info("Sending Features_Request")
58 logging.info("Expecting Features_Reply")
ShreyaPandita9306c772012-09-28 12:21:40 -040059
60 request = message.features_request()
61 rv = self.controller.message_send(request)
62 self.assertTrue(rv != -1, "Not able to send features request.")
63
64 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_FEATURES_REPLY,
65 timeout=2)
66 self.assertTrue(response is not None,
67 'Did not receive Features Reply')
68
69
70class ConfigurationRequest(basic.SimpleProtocol):
71
72 """Check basic Get Config request is implemented
73 a) Send OFPT_GET_CONFIG_REQUEST
74 b) Verify OFPT_GET_CONFIG_REPLY is received without errors"""
75
76 def runTest(self):
77
Rich Lane9a003812012-10-04 17:17:59 -070078 logging.info("Running Configuration_Request test ")
ShreyaPandita9306c772012-09-28 12:21:40 -040079
80 of_ports = of_port_map.keys()
81 of_ports.sort()
82
83 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -070084 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -040085 self.assertEqual(rc, 0, "Failed to delete all flows")
86
Rich Lane9a003812012-10-04 17:17:59 -070087 logging.info("Sending OFPT_GET_CONFIG_REQUEST ")
88 logging.info("Expecting OFPT_GET_CONFIG_REPLY ")
ShreyaPandita9306c772012-09-28 12:21:40 -040089
90 request = message.get_config_request()
91 rv = self.controller.message_send(request)
92 self.assertTrue(rv != -1, " Not able to send get_config request.")
93
94 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
95 timeout=2)
96 self.assertTrue(response is not None,
97 'Did not receive OFPT_GET_CONFIG_REPLY')
98
99class ModifyStateAdd(basic.SimpleProtocol):
100
101 """Check basic Flow Add request is implemented
102 a) Send OFPT_FLOW_MOD , command = OFPFC_ADD
103 c) Send ofp_table_stats request , verify active_count=1 in reply"""
104
105 def runTest(self):
106
Rich Lane9a003812012-10-04 17:17:59 -0700107 logging.info("Running Modify_State_Add test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400108
109 of_ports = of_port_map.keys()
110 of_ports.sort()
111
112 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700113 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400114 self.assertEqual(rc, 0, "Failed to delete all flows")
115
Rich Lane9a003812012-10-04 17:17:59 -0700116 logging.info("Inserting a flow entry")
117 logging.info("Expecting active_count=1 in table_stats_reply")
ShreyaPandita9306c772012-09-28 12:21:40 -0400118
119 #Insert a flow entry matching on ingress_port
120 (Pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
121
122 # Send Table_Stats_Request and verify flow gets inserted.
123 Verify_TableStats(self,active_entries=1)
124
125
126class ModifyStateDelete(basic.SimpleProtocol):
127
128 """Check Basic Flow Delete request is implemented
129 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD
130 b) Send ofp_table_stats request , verify active_count=1 in reply
131 c) Send OFPT_FLOW_MOD, command = OFPFC_DELETE
132 c) Send ofp_table_stats request , verify active_count=0 in reply"""
133
134 def runTest(self):
135
Rich Lane9a003812012-10-04 17:17:59 -0700136 logging.info("Running Modify_State_Delete test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400137
138 of_ports = of_port_map.keys()
139 of_ports.sort()
140
141 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700142 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400143 self.assertEqual(rc, 0, "Failed to delete all flows")
144
Rich Lane9a003812012-10-04 17:17:59 -0700145 logging.info("Inserting a flow entry and then deleting it")
146 logging.info("Expecting the active_count=0 in table_stats_reply")
ShreyaPandita9306c772012-09-28 12:21:40 -0400147
148 #Insert a flow matching on ingress_port
149 (Pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
150
151 #Verify Flow inserted.
152 Verify_TableStats(self,active_entries=1)
153
154 #Delete the flow
155 NonStrict_Delete(self,match)
156
157 # Send Table_Stats_Request and verify flow deleted.
158 Verify_TableStats(self,active_entries=0)
159
160
161
162class ModifyStateModify(basic.SimpleDataPlane):
163
164 """Verify basic Flow Modify request is implemented
165 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD, Action A
166 b) Send OFPT_FLOW_MOD, command = OFPFC_MODIFY , with output action A'
167 c) Send a packet matching the flow, verify packet implements action A' """
168
169 def runTest(self):
170
Rich Lane9a003812012-10-04 17:17:59 -0700171 logging.info("Running Modify_State_Modify test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400172
173 of_ports = of_port_map.keys()
174 of_ports.sort()
175
176 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700177 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400178 self.assertEqual(rc, 0, "Failed to delete all flows")
179
Rich Lane9a003812012-10-04 17:17:59 -0700180 logging.info("Inserting a flow entry and then modifying it")
181 logging.info("Expecting the Test Packet to implement the modified action")
ShreyaPandita9306c772012-09-28 12:21:40 -0400182
183 # Insert a flow matching on ingress_port with action A (output to of_port[1])
184 (pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
185
186 # Modify the flow action (output to of_port[2])
187 Modify_Flow_Action(self,of_ports,match)
188
189 # Send the Test Packet and verify action implemented is A' (output to of_port[2])
ShreyaPandita214a9c42012-09-28 13:14:59 -0400190 SendPacket(self,pkt,of_ports[0],of_ports[2])
ShreyaPandita9306c772012-09-28 12:21:40 -0400191
192
193class ReadState(basic.SimpleProtocol):
194
195 """Test that a basic Read state request (like flow_stats_get request) does not generate an error
196 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD
197 b) Send ofp_flow_stats request
198 b) Verify switch replies without errors"""
199
200 def runTest(self):
201
Rich Lane9a003812012-10-04 17:17:59 -0700202 logging.info("Running Read_State test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400203
204 of_ports = of_port_map.keys()
205 of_ports.sort()
206
207 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700208 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400209 self.assertEqual(rc, 0, "Failed to delete all flows")
210
Rich Lane9a003812012-10-04 17:17:59 -0700211 logging.info("Inserting a flow entry and then sending flow_stats request")
212 logging.info("Expecting the a flow_stats_reply without errors")
ShreyaPandita9306c772012-09-28 12:21:40 -0400213
214 # Insert a flow with match on ingress_port
215 (pkt,match ) = Wildcard_All_Except_Ingress(self,of_ports)
216
217 #Verify Flow_Stats request does not generate errors
218 Verify_FlowStats(self,match)
219
ShreyaPandita214a9c42012-09-28 13:14:59 -0400220class PacketOut(basic.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400221
222 """Test packet out function
223 a) Send packet out message for each dataplane port.
224 b) Verify the packet appears on the appropriate dataplane port"""
225
226 def runTest(self):
227
Rich Lane9a003812012-10-04 17:17:59 -0700228 logging.info("Running Packet_Out test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400229
230 of_ports = of_port_map.keys()
231 of_ports.sort()
232
233 #Clear Switch state
Rich Lane9a003812012-10-04 17:17:59 -0700234 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400235 self.assertEqual(rc, 0, "Failed to delete all flows")
236
Rich Lane9a003812012-10-04 17:17:59 -0700237 logging.info("Sending a packet-out for each dataplane port")
238 logging.info("Expecting the packet on appropriate dataplane port")
ShreyaPandita9306c772012-09-28 12:21:40 -0400239
240 for dp_port in of_ports:
241 for outpkt, opt in [
242 (simple_tcp_packet(), "simple TCP packet"),
243 (simple_eth_packet(), "simple Ethernet packet"),
244 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
245
246 msg = message.packet_out()
247 msg.data = str(outpkt)
248 act = action.action_output()
249 act.port = dp_port
250 self.assertTrue(msg.actions.add(act), 'Could not add action to msg')
251
Rich Lane9a003812012-10-04 17:17:59 -0700252 logging.info("PacketOut to: " + str(dp_port))
ShreyaPandita9306c772012-09-28 12:21:40 -0400253 rv = self.controller.message_send(msg)
254 self.assertTrue(rv == 0, "Error sending out message")
255
256 exp_pkt_arg = None
257 exp_port = None
258 if of_config["relax"]:
259 exp_pkt_arg = outpkt
260 exp_port = dp_port
261 (of_port, pkt, pkt_time) = self.dataplane.poll(timeout=2,
262 port_number=exp_port,
263 exp_pkt=exp_pkt_arg)
264
265 self.assertTrue(pkt is not None, 'Packet not received')
Rich Lane9a003812012-10-04 17:17:59 -0700266 logging.info("PacketOut: got pkt from " + str(of_port))
ShreyaPandita9306c772012-09-28 12:21:40 -0400267 if of_port is not None:
268 self.assertEqual(of_port, dp_port, "Unexpected receive port")
269 if not dataplane.match_exp_pkt(outpkt, pkt):
Rich Lane9a003812012-10-04 17:17:59 -0700270 logging.debug("Sent %s" % format_packet(outpkt))
271 logging.debug("Resp %s" % format_packet(
ShreyaPandita9306c772012-09-28 12:21:40 -0400272 str(pkt)[:len(str(outpkt))]))
273 self.assertEqual(str(outpkt), str(pkt)[:len(str(outpkt))],
274 'Response packet does not match send packet')
275
276
277class PacketIn(basic.SimpleDataPlane):
278
279 """Test basic packet_in function
280 a) Send a simple tcp packet to a dataplane port, without any flow-entry
281 b) Verify that a packet_in event is sent to the controller"""
282
283 def runTest(self):
284
Rich Lane9a003812012-10-04 17:17:59 -0700285 logging.info("Running Packet_In test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400286
287 of_ports = of_port_map.keys()
288 of_ports.sort()
289 ingress_port = of_ports[0]
290
291 #Clear Switch state
Rich Lane9a003812012-10-04 17:17:59 -0700292 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400293 self.assertEqual(rc, 0, "Failed to delete all flows")
294 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
295
Rich Lane9a003812012-10-04 17:17:59 -0700296 logging.info("Sending a Simple tcp packet a dataplane port")
297 logging.info("Expecting a packet_in event on the control plane")
ShreyaPandita9306c772012-09-28 12:21:40 -0400298
299 # Send packet on dataplane port and verify packet_in event gets generated.
300 pkt = simple_tcp_packet()
301 self.dataplane.send(ingress_port, str(pkt))
Rich Lane9a003812012-10-04 17:17:59 -0700302 logging.info("Sending packet to dp port " + str(ingress_port) +
ShreyaPandita9306c772012-09-28 12:21:40 -0400303 ", expecting packet_in on control plane" )
304
305 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_PACKET_IN,
306 timeout=2)
307 self.assertTrue(response is not None,
308 'Packet in event is not sent to the controller')
309
310
311class Hello(basic.SimpleDataPlane):
312
313 """Test Hello messages are implemented
314 a) Create Hello messages from controller
315 b) Verify switch also exchanges hello message -- (Poll the control plane)
316 d) Verify the version field in the hello messages is openflow 1.0.0 """
317
318 def runTest(self):
319
Rich Lane9a003812012-10-04 17:17:59 -0700320 logging.info("Running Hello test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400321
Rich Lane9a003812012-10-04 17:17:59 -0700322 logging.info("Sending Hello")
323 logging.info("Expecting a Hello on the control plane with version--1.0.0")
ShreyaPandita9306c772012-09-28 12:21:40 -0400324
325 #Send Hello message
326 request = message.hello()
327 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_HELLO,
328 timeout=1)
329 self.assertTrue(response is not None,
330 'Switch did not exchange hello message in return')
331 self.assertTrue(response.header.version == 0x01, 'switch openflow-version field is not 1.0.0')
332
333
334
335class EchoWithoutBody(basic.SimpleProtocol):
336
337 """Test basic echo-reply is implemented
338 a) Send echo-request from the controller side, note echo body is empty here.
339 b) Verify switch responds back with echo-reply with same xid """
340
341 def runTest(self):
342
Rich Lane9a003812012-10-04 17:17:59 -0700343 logging.info("Running Echo_Without_Body test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400344
Rich Lane9a003812012-10-04 17:17:59 -0700345 logging.info("Sending Echo Request")
346 logging.info("Expecting a Echo Reply with version--1.0.0 and same xid")
ShreyaPandita9306c772012-09-28 12:21:40 -0400347
348 # Send echo_request
349 request = message.echo_request()
350 (response, pkt) = self.controller.transact(request)
351 self.assertEqual(response.header.type, ofp.OFPT_ECHO_REPLY,'response is not echo_reply')
352 self.assertEqual(request.header.xid, response.header.xid,
353 'response xid != request xid')
354 self.assertTrue(response.header.version == 0x01, 'switch openflow-version field is not 1.0.1')
355 self.assertEqual(len(response.data), 0, 'response data non-empty')
356
357
358class BarrierRequestReply(basic.SimpleProtocol):
359
360 """ Check basic Barrier request is implemented
361 a) Send OFPT_BARRIER_REQUEST
362 c) Verify OFPT_BARRIER_REPLY is recieved"""
363
364 def runTest(self):
365
Rich Lane9a003812012-10-04 17:17:59 -0700366 logging.info("Running Barrier_Request_Reply test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400367
Rich Lane9a003812012-10-04 17:17:59 -0700368 logging.info("Sending Barrier Request")
369 logging.info("Expecting a Barrier Reply with same xid")
ShreyaPandita9306c772012-09-28 12:21:40 -0400370
371 #Send Barrier Request
372 request = message.barrier_request()
373 (response, pkt) = self.controller.transact(request)
374 self.assertEqual(response.header.type, ofp.OFPT_BARRIER_REPLY,'response is not barrier_reply')
375 self.assertEqual(request.header.xid, response.header.xid,
376 'response xid != request xid')
377
378
379
380
381