blob: 2dc9a234c9ce898eb15813c021dd9f50a8362948 [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
11
12from oftest import config
13import oftest.base_tests as base_tests
14import ofp
15import oftest.packet as scapy
16
17from oftest.testutils import *
18from oftest.parse import parse_ipv6
19
20class AllFlowStats(base_tests.SimpleDataPlane):
21 """
22 Retrieve all flows and verify the stats entries match the flow-mods sent
23 """
24 def runTest(self):
25 port1, port2, port3 = openflow_ports(3)
26 delete_all_flows(self.controller)
27
28 flow1 = ofp.message.flow_add(
29 table_id=0,
30 priority=0x11,
31 idle_timeout=0x21,
32 hard_timeout=0x31,
33 flags=ofp.OFPFF_NO_PKT_COUNTS,
34 cookie=1,
35 match=ofp.match([
36 ofp.oxm.in_port(port1),
37 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|1)]),
38 instructions=[
39 ofp.instruction.write_actions(
40 actions=[
41 ofp.action.output(
42 port=port1,
43 max_len=ofp.OFPCML_NO_BUFFER)])],
44 buffer_id=ofp.OFP_NO_BUFFER)
45
46 flow2 = ofp.message.flow_add(
47 table_id=0,
48 priority=0x12,
49 idle_timeout=0x22,
50 hard_timeout=0x32,
51 flags=ofp.OFPFF_NO_BYT_COUNTS,
52 cookie=2,
53 match=ofp.match([
54 ofp.oxm.in_port(port2),
55 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2)]),
56 instructions=[
57 ofp.instruction.write_actions(
58 actions=[
59 ofp.action.output(
60 port=port2,
61 max_len=ofp.OFPCML_NO_BUFFER)])],
62 buffer_id=ofp.OFP_NO_BUFFER)
63
64 flow3 = ofp.message.flow_add(
65 table_id=0,
66 priority=0x13,
67 idle_timeout=0x23,
68 hard_timeout=0x33,
69 flags=ofp.OFPFF_CHECK_OVERLAP,
70 cookie=3,
71 match=ofp.match([
72 ofp.oxm.in_port(port3),
73 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|3)]),
74 instructions=[
75 ofp.instruction.write_actions(
76 actions=[
77 ofp.action.output(
78 port=port3,
79 max_len=ofp.OFPCML_NO_BUFFER)])],
80 buffer_id=ofp.OFP_NO_BUFFER)
81
82 flows = [flow1, flow2, flow3]
83 for flow in flows:
84 logging.debug(flow.show())
85 self.controller.message_send(flow)
86
87 flows_by_cookie = { flow.cookie: flow for flow in flows }
88
89 do_barrier(self.controller)
90
91 logging.info("Sending flow stats request")
92 stats = get_flow_stats(self, ofp.match())
93 logging.info("Received %d flow stats entries", len(stats))
94
95 seen_cookies = set()
96 for entry in stats:
97 logging.debug(entry.show())
98 self.assertTrue(entry.cookie in flows_by_cookie, "Unexpected cookie")
99 self.assertTrue(entry.cookie not in seen_cookies, "Duplicate cookie")
100 flow = flows_by_cookie[entry.cookie]
101 seen_cookies.add(entry.cookie)
102
103 self.assertEqual(entry.table_id, flow.table_id)
104 self.assertEqual(entry.priority, flow.priority)
105 self.assertEqual(entry.idle_timeout, flow.idle_timeout)
106 self.assertEqual(entry.hard_timeout, flow.hard_timeout)
107 self.assertEqual(entry.flags, flow.flags)
108 self.assertEqual(entry.cookie, flow.cookie)
109 self.assertEqual(sorted(entry.match.oxm_list), sorted(flow.match.oxm_list))
110 self.assertEqual(sorted(entry.instructions), sorted(flow.instructions))
111
112 self.assertEqual(seen_cookies, set([1,2,3]))
Rich Laned15c6652013-10-04 14:42:26 -0700113
114class CookieFlowStats(base_tests.SimpleDataPlane):
115 """
116 Retrieve flows using various masks on the cookie
117 """
118 def runTest(self):
119 delete_all_flows(self.controller)
120
121 # Also used as masks
122 cookies = [
123 0x0000000000000000,
124 0xDDDDDDDD00000000,
125 0x00000000DDDDDDDD,
126 0xDDDDDDDDDDDDDDDD,
127 0xDDDD0000DDDD0000,
128 0x0000DDDD0000DDDD,
129 0xDD00DD00DD00DD00,
130 0xD0D0D0D0D0D0D0D0,
131 0xF000000000000000,
132 0xFF00000000000000,
133 0xFFF0000000000000,
134 0xFFFF000000000000,
135 ]
136
137 # Generate the matching cookies for each combination of cookie and mask
138 matches = {}
139 for cookie in cookies:
140 for mask in cookies:
141 matching = []
142 for cookie2 in cookies:
143 if cookie & mask == cookie2 & mask:
144 matching.append(cookie2)
145 matches[(cookie, mask)] = sorted(matching)
146
147 # Generate a flow for each cookie
148 flows = {}
149 for idx, cookie in enumerate(cookies):
150 flows[cookie] = ofp.message.flow_add(
151 table_id=0,
152 cookie=cookie,
153 match=ofp.match([ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|idx)]),
154 buffer_id=ofp.OFP_NO_BUFFER)
155
156 # Install flows
157 for flow in flows.values():
158 self.controller.message_send(flow)
159 do_barrier(self.controller)
160
161 # For each combination of cookie and match, verify the correct flows
162 # are retrieved
163 for (cookie, mask), expected_cookies in matches.items():
164 stats = get_flow_stats(self, ofp.match(), cookie=cookie, cookie_mask=mask)
165 received_cookies = sorted([entry.cookie for entry in stats])
166 logging.debug("expected 0x%016x/0x%016x: %s", cookie, mask,
167 ' '.join(["0x%016x" % x for x in expected_cookies]))
168 logging.debug("received 0x%016x/0x%016x: %s", cookie, mask,
169 ' '.join(["0x%016x" % x for x in received_cookies]))
170 self.assertEqual(expected_cookies, received_cookies)