blob: 8f2593f6971fad271f554595e9164cb13d1d42d8 [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
21from testutils import *
22from time import sleep
23from FuncUtils import *
24
25
26of_port_map = None
27of_logger = None
28of_config = None
29
30def test_set_init(config):
31
32
33 basic.test_set_init(config)
34
35 global of_port_map
36 global of_logger
37 global of_config
38
39 of_logger = logging.getLogger("Start Openflow_Protocol_Messages Conformance Test-suite")
40 of_logger.info("Initializing test set")
41 of_port_map = config["port_map"]
42 of_config = config
43
44
45class FeaturesRequest(basic.SimpleProtocol):
46
47 """Verify Features_Request-Reply is implemented
48 a) Send OFPT_FEATURES_REQUEST
49 b) Verify OFPT_FEATURES_REPLY is received without errors"""
50
51 def runTest(self):
52 of_logger.info("Running Features_Request test")
53
54 of_ports = of_port_map.keys()
55 of_ports.sort()
56
57 #Clear switch state
58 rc = delete_all_flows(self.controller, of_logger)
59 self.assertEqual(rc, 0, "Failed to delete all flows")
60
61 of_logger.info("Sending Features_Request")
62 of_logger.info("Expecting Features_Reply")
63
64 request = message.features_request()
65 rv = self.controller.message_send(request)
66 self.assertTrue(rv != -1, "Not able to send features request.")
67
68 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_FEATURES_REPLY,
69 timeout=2)
70 self.assertTrue(response is not None,
71 'Did not receive Features Reply')
72
73
74class ConfigurationRequest(basic.SimpleProtocol):
75
76 """Check basic Get Config request is implemented
77 a) Send OFPT_GET_CONFIG_REQUEST
78 b) Verify OFPT_GET_CONFIG_REPLY is received without errors"""
79
80 def runTest(self):
81
82 of_logger.info("Running Configuration_Request test ")
83
84 of_ports = of_port_map.keys()
85 of_ports.sort()
86
87 #Clear switch state
88 rc = delete_all_flows(self.controller, of_logger)
89 self.assertEqual(rc, 0, "Failed to delete all flows")
90
91 of_logger.info("Sending OFPT_GET_CONFIG_REQUEST ")
92 of_logger.info("Expecting OFPT_GET_CONFIG_REPLY ")
93
94 request = message.get_config_request()
95 rv = self.controller.message_send(request)
96 self.assertTrue(rv != -1, " Not able to send get_config request.")
97
98 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
99 timeout=2)
100 self.assertTrue(response is not None,
101 'Did not receive OFPT_GET_CONFIG_REPLY')
102
103class ModifyStateAdd(basic.SimpleProtocol):
104
105 """Check basic Flow Add request is implemented
106 a) Send OFPT_FLOW_MOD , command = OFPFC_ADD
107 c) Send ofp_table_stats request , verify active_count=1 in reply"""
108
109 def runTest(self):
110
111 of_logger.info("Running Modify_State_Add test")
112
113 of_ports = of_port_map.keys()
114 of_ports.sort()
115
116 #Clear switch state
117 rc = delete_all_flows(self.controller,of_logger)
118 self.assertEqual(rc, 0, "Failed to delete all flows")
119
120 of_logger.info("Inserting a flow entry")
121 of_logger.info("Expecting active_count=1 in table_stats_reply")
122
123 #Insert a flow entry matching on ingress_port
124 (Pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
125
126 # Send Table_Stats_Request and verify flow gets inserted.
127 Verify_TableStats(self,active_entries=1)
128
129
130class ModifyStateDelete(basic.SimpleProtocol):
131
132 """Check Basic Flow Delete request is implemented
133 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD
134 b) Send ofp_table_stats request , verify active_count=1 in reply
135 c) Send OFPT_FLOW_MOD, command = OFPFC_DELETE
136 c) Send ofp_table_stats request , verify active_count=0 in reply"""
137
138 def runTest(self):
139
140 of_logger.info("Running Modify_State_Delete test")
141
142 of_ports = of_port_map.keys()
143 of_ports.sort()
144
145 #Clear switch state
146 rc = delete_all_flows(self.controller,of_logger)
147 self.assertEqual(rc, 0, "Failed to delete all flows")
148
149 of_logger.info("Inserting a flow entry and then deleting it")
150 of_logger.info("Expecting the active_count=0 in table_stats_reply")
151
152 #Insert a flow matching on ingress_port
153 (Pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
154
155 #Verify Flow inserted.
156 Verify_TableStats(self,active_entries=1)
157
158 #Delete the flow
159 NonStrict_Delete(self,match)
160
161 # Send Table_Stats_Request and verify flow deleted.
162 Verify_TableStats(self,active_entries=0)
163
164
165
166class ModifyStateModify(basic.SimpleDataPlane):
167
168 """Verify basic Flow Modify request is implemented
169 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD, Action A
170 b) Send OFPT_FLOW_MOD, command = OFPFC_MODIFY , with output action A'
171 c) Send a packet matching the flow, verify packet implements action A' """
172
173 def runTest(self):
174
175 of_logger.info("Running Modify_State_Modify test")
176
177 of_ports = of_port_map.keys()
178 of_ports.sort()
179
180 #Clear switch state
181 rc = delete_all_flows(self.controller, of_logger)
182 self.assertEqual(rc, 0, "Failed to delete all flows")
183
184 of_logger.info("Inserting a flow entry and then modifying it")
185 of_logger.info("Expecting the Test Packet to implement the modified action")
186
187 # Insert a flow matching on ingress_port with action A (output to of_port[1])
188 (pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
189
190 # Modify the flow action (output to of_port[2])
191 Modify_Flow_Action(self,of_ports,match)
192
193 # Send the Test Packet and verify action implemented is A' (output to of_port[2])
ShreyaPandita214a9c42012-09-28 13:14:59 -0400194 SendPacket(self,pkt,of_ports[0],of_ports[2])
ShreyaPandita9306c772012-09-28 12:21:40 -0400195
196
197class ReadState(basic.SimpleProtocol):
198
199 """Test that a basic Read state request (like flow_stats_get request) does not generate an error
200 a) Send OFPT_FLOW_MOD, command = OFPFC_ADD
201 b) Send ofp_flow_stats request
202 b) Verify switch replies without errors"""
203
204 def runTest(self):
205
206 of_logger.info("Running Read_State test")
207
208 of_ports = of_port_map.keys()
209 of_ports.sort()
210
211 #Clear switch state
212 rc = delete_all_flows(self.controller, of_logger)
213 self.assertEqual(rc, 0, "Failed to delete all flows")
214
215 of_logger.info("Inserting a flow entry and then sending flow_stats request")
216 of_logger.info("Expecting the a flow_stats_reply without errors")
217
218 # Insert a flow with match on ingress_port
219 (pkt,match ) = Wildcard_All_Except_Ingress(self,of_ports)
220
221 #Verify Flow_Stats request does not generate errors
222 Verify_FlowStats(self,match)
223
ShreyaPandita214a9c42012-09-28 13:14:59 -0400224class PacketOut(basic.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400225
226 """Test packet out function
227 a) Send packet out message for each dataplane port.
228 b) Verify the packet appears on the appropriate dataplane port"""
229
230 def runTest(self):
231
ShreyaPandita214a9c42012-09-28 13:14:59 -0400232 of_logger.info("Running Packet_Out test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400233
234 of_ports = of_port_map.keys()
235 of_ports.sort()
236
237 #Clear Switch state
238 rc = delete_all_flows(self.controller, of_logger)
239 self.assertEqual(rc, 0, "Failed to delete all flows")
240
241 of_logger.info("Sending a packet-out for each dataplane port")
242 of_logger.info("Expecting the packet on appropriate dataplane port")
243
244 for dp_port in of_ports:
245 for outpkt, opt in [
246 (simple_tcp_packet(), "simple TCP packet"),
247 (simple_eth_packet(), "simple Ethernet packet"),
248 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
249
250 msg = message.packet_out()
251 msg.data = str(outpkt)
252 act = action.action_output()
253 act.port = dp_port
254 self.assertTrue(msg.actions.add(act), 'Could not add action to msg')
255
256 of_logger.info("PacketOut to: " + str(dp_port))
257 rv = self.controller.message_send(msg)
258 self.assertTrue(rv == 0, "Error sending out message")
259
260 exp_pkt_arg = None
261 exp_port = None
262 if of_config["relax"]:
263 exp_pkt_arg = outpkt
264 exp_port = dp_port
265 (of_port, pkt, pkt_time) = self.dataplane.poll(timeout=2,
266 port_number=exp_port,
267 exp_pkt=exp_pkt_arg)
268
269 self.assertTrue(pkt is not None, 'Packet not received')
270 of_logger.info("PacketOut: got pkt from " + str(of_port))
271 if of_port is not None:
272 self.assertEqual(of_port, dp_port, "Unexpected receive port")
273 if not dataplane.match_exp_pkt(outpkt, pkt):
274 of_logger.debug("Sent %s" % format_packet(outpkt))
275 of_logger.debug("Resp %s" % format_packet(
276 str(pkt)[:len(str(outpkt))]))
277 self.assertEqual(str(outpkt), str(pkt)[:len(str(outpkt))],
278 'Response packet does not match send packet')
279
280
281class PacketIn(basic.SimpleDataPlane):
282
283 """Test basic packet_in function
284 a) Send a simple tcp packet to a dataplane port, without any flow-entry
285 b) Verify that a packet_in event is sent to the controller"""
286
287 def runTest(self):
288
289 of_logger.info("Running Packet_In test")
290
291 of_ports = of_port_map.keys()
292 of_ports.sort()
293 ingress_port = of_ports[0]
294
295 #Clear Switch state
296 rc = delete_all_flows(self.controller, of_logger)
297 self.assertEqual(rc, 0, "Failed to delete all flows")
298 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
299
300 of_logger.info("Sending a Simple tcp packet a dataplane port")
301 of_logger.info("Expecting a packet_in event on the control plane")
302
303 # Send packet on dataplane port and verify packet_in event gets generated.
304 pkt = simple_tcp_packet()
305 self.dataplane.send(ingress_port, str(pkt))
306 of_logger.info("Sending packet to dp port " + str(ingress_port) +
307 ", expecting packet_in on control plane" )
308
309 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_PACKET_IN,
310 timeout=2)
311 self.assertTrue(response is not None,
312 'Packet in event is not sent to the controller')
313
314
315class Hello(basic.SimpleDataPlane):
316
317 """Test Hello messages are implemented
318 a) Create Hello messages from controller
319 b) Verify switch also exchanges hello message -- (Poll the control plane)
320 d) Verify the version field in the hello messages is openflow 1.0.0 """
321
322 def runTest(self):
323
324 of_logger.info("Running Hello test")
325
326 of_logger.info("Sending Hello")
327 of_logger.info("Expecting a Hello on the control plane with version--1.0.0")
328
329 #Send Hello message
330 request = message.hello()
331 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_HELLO,
332 timeout=1)
333 self.assertTrue(response is not None,
334 'Switch did not exchange hello message in return')
335 self.assertTrue(response.header.version == 0x01, 'switch openflow-version field is not 1.0.0')
336
337
338
339class EchoWithoutBody(basic.SimpleProtocol):
340
341 """Test basic echo-reply is implemented
342 a) Send echo-request from the controller side, note echo body is empty here.
343 b) Verify switch responds back with echo-reply with same xid """
344
345 def runTest(self):
346
347 of_logger.info("Running Echo_Without_Body test")
348
349 of_logger.info("Sending Echo Request")
350 of_logger.info("Expecting a Echo Reply with version--1.0.0 and same xid")
351
352 # Send echo_request
353 request = message.echo_request()
354 (response, pkt) = self.controller.transact(request)
355 self.assertEqual(response.header.type, ofp.OFPT_ECHO_REPLY,'response is not echo_reply')
356 self.assertEqual(request.header.xid, response.header.xid,
357 'response xid != request xid')
358 self.assertTrue(response.header.version == 0x01, 'switch openflow-version field is not 1.0.1')
359 self.assertEqual(len(response.data), 0, 'response data non-empty')
360
361
362class BarrierRequestReply(basic.SimpleProtocol):
363
364 """ Check basic Barrier request is implemented
365 a) Send OFPT_BARRIER_REQUEST
366 c) Verify OFPT_BARRIER_REPLY is recieved"""
367
368 def runTest(self):
369
370 of_logger.info("Running Barrier_Request_Reply test")
371
372 of_logger.info("Sending Barrier Request")
373 of_logger.info("Expecting a Barrier Reply with same xid")
374
375 #Send Barrier Request
376 request = message.barrier_request()
377 (response, pkt) = self.controller.transact(request)
378 self.assertEqual(response.header.type, ofp.OFPT_BARRIER_REPLY,'response is not barrier_reply')
379 self.assertEqual(request.header.xid, response.header.xid,
380 'response xid != request xid')
381
382
383
384
385