blob: 4a82a8901032c14d303c42efb2fba11fc087f94b [file] [log] [blame]
Rich Lane102d71d2013-10-04 14:09:34 -07001# Distributed under the OpenFlow Software License (see LICENSE)
2# Copyright (c) 2010 The Board of Trustees of The Leland Stanford Junior University
3# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
4"""
5Flow stats test cases
6
7These tests check the behavior of the flow stats request.
8"""
9
10import logging
Rich Lane43ffb102013-10-07 10:24:05 -070011import random
Rich Lane102d71d2013-10-04 14:09:34 -070012
13from oftest import config
14import oftest.base_tests as base_tests
15import ofp
16import oftest.packet as scapy
17
18from oftest.testutils import *
19from oftest.parse import parse_ipv6
20
21class AllFlowStats(base_tests.SimpleDataPlane):
22 """
23 Retrieve all flows and verify the stats entries match the flow-mods sent
24 """
25 def runTest(self):
26 port1, port2, port3 = openflow_ports(3)
27 delete_all_flows(self.controller)
28
29 flow1 = ofp.message.flow_add(
30 table_id=0,
31 priority=0x11,
32 idle_timeout=0x21,
33 hard_timeout=0x31,
34 flags=ofp.OFPFF_NO_PKT_COUNTS,
35 cookie=1,
36 match=ofp.match([
37 ofp.oxm.in_port(port1),
38 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|1)]),
39 instructions=[
40 ofp.instruction.write_actions(
41 actions=[
42 ofp.action.output(
43 port=port1,
44 max_len=ofp.OFPCML_NO_BUFFER)])],
45 buffer_id=ofp.OFP_NO_BUFFER)
46
47 flow2 = ofp.message.flow_add(
48 table_id=0,
49 priority=0x12,
50 idle_timeout=0x22,
51 hard_timeout=0x32,
52 flags=ofp.OFPFF_NO_BYT_COUNTS,
53 cookie=2,
54 match=ofp.match([
55 ofp.oxm.in_port(port2),
56 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2)]),
57 instructions=[
58 ofp.instruction.write_actions(
59 actions=[
60 ofp.action.output(
61 port=port2,
62 max_len=ofp.OFPCML_NO_BUFFER)])],
63 buffer_id=ofp.OFP_NO_BUFFER)
64
65 flow3 = ofp.message.flow_add(
66 table_id=0,
67 priority=0x13,
68 idle_timeout=0x23,
69 hard_timeout=0x33,
70 flags=ofp.OFPFF_CHECK_OVERLAP,
71 cookie=3,
72 match=ofp.match([
73 ofp.oxm.in_port(port3),
74 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|3)]),
75 instructions=[
76 ofp.instruction.write_actions(
77 actions=[
78 ofp.action.output(
79 port=port3,
80 max_len=ofp.OFPCML_NO_BUFFER)])],
81 buffer_id=ofp.OFP_NO_BUFFER)
82
83 flows = [flow1, flow2, flow3]
84 for flow in flows:
85 logging.debug(flow.show())
86 self.controller.message_send(flow)
87
88 flows_by_cookie = { flow.cookie: flow for flow in flows }
89
90 do_barrier(self.controller)
91
92 logging.info("Sending flow stats request")
93 stats = get_flow_stats(self, ofp.match())
94 logging.info("Received %d flow stats entries", len(stats))
95
96 seen_cookies = set()
97 for entry in stats:
98 logging.debug(entry.show())
99 self.assertTrue(entry.cookie in flows_by_cookie, "Unexpected cookie")
100 self.assertTrue(entry.cookie not in seen_cookies, "Duplicate cookie")
101 flow = flows_by_cookie[entry.cookie]
102 seen_cookies.add(entry.cookie)
103
104 self.assertEqual(entry.table_id, flow.table_id)
105 self.assertEqual(entry.priority, flow.priority)
106 self.assertEqual(entry.idle_timeout, flow.idle_timeout)
107 self.assertEqual(entry.hard_timeout, flow.hard_timeout)
108 self.assertEqual(entry.flags, flow.flags)
109 self.assertEqual(entry.cookie, flow.cookie)
110 self.assertEqual(sorted(entry.match.oxm_list), sorted(flow.match.oxm_list))
111 self.assertEqual(sorted(entry.instructions), sorted(flow.instructions))
112
113 self.assertEqual(seen_cookies, set([1,2,3]))
Rich Laned15c6652013-10-04 14:42:26 -0700114
115class CookieFlowStats(base_tests.SimpleDataPlane):
116 """
117 Retrieve flows using various masks on the cookie
118 """
119 def runTest(self):
120 delete_all_flows(self.controller)
121
122 # Also used as masks
123 cookies = [
124 0x0000000000000000,
125 0xDDDDDDDD00000000,
126 0x00000000DDDDDDDD,
127 0xDDDDDDDDDDDDDDDD,
128 0xDDDD0000DDDD0000,
129 0x0000DDDD0000DDDD,
130 0xDD00DD00DD00DD00,
131 0xD0D0D0D0D0D0D0D0,
132 0xF000000000000000,
133 0xFF00000000000000,
134 0xFFF0000000000000,
135 0xFFFF000000000000,
136 ]
137
Rich Lane43ffb102013-10-07 10:24:05 -0700138 for i in range(0, 10):
139 cookies.append(random.getrandbits(64))
140
Rich Laned15c6652013-10-04 14:42:26 -0700141 # Generate the matching cookies for each combination of cookie and mask
142 matches = {}
Rich Lanef58cae22013-10-07 11:10:04 -0700143 for mask in cookies:
144 for cookie in cookies:
Rich Laned15c6652013-10-04 14:42:26 -0700145 matching = []
146 for cookie2 in cookies:
147 if cookie & mask == cookie2 & mask:
148 matching.append(cookie2)
149 matches[(cookie, mask)] = sorted(matching)
150
151 # Generate a flow for each cookie
152 flows = {}
153 for idx, cookie in enumerate(cookies):
154 flows[cookie] = ofp.message.flow_add(
155 table_id=0,
156 cookie=cookie,
157 match=ofp.match([ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|idx)]),
158 buffer_id=ofp.OFP_NO_BUFFER)
159
160 # Install flows
161 for flow in flows.values():
162 self.controller.message_send(flow)
163 do_barrier(self.controller)
164
165 # For each combination of cookie and match, verify the correct flows
166 # are retrieved
Rich Lane316204b2013-10-07 11:08:03 -0700167 for (cookie, mask), expected_cookies in matches.iteritems():
Rich Laned15c6652013-10-04 14:42:26 -0700168 stats = get_flow_stats(self, ofp.match(), cookie=cookie, cookie_mask=mask)
169 received_cookies = sorted([entry.cookie for entry in stats])
170 logging.debug("expected 0x%016x/0x%016x: %s", cookie, mask,
171 ' '.join(["0x%016x" % x for x in expected_cookies]))
172 logging.debug("received 0x%016x/0x%016x: %s", cookie, mask,
173 ' '.join(["0x%016x" % x for x in received_cookies]))
174 self.assertEqual(expected_cookies, received_cookies)