blob: 678758015a34bd0fb320c0dbfcbde304352f242a [file] [log] [blame]
Matteo Scandoloa229eca2017-08-08 13:05:28 -07001
2# Copyright 2017-present Open Networking Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
Rich Lane102d71d2013-10-04 14:09:34 -070017# Distributed under the OpenFlow Software License (see LICENSE)
18# Copyright (c) 2010 The Board of Trustees of The Leland Stanford Junior University
19# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
20"""
21Flow stats test cases
22
23These tests check the behavior of the flow stats request.
24"""
25
26import logging
Rich Lane43ffb102013-10-07 10:24:05 -070027import random
Rich Lane102d71d2013-10-04 14:09:34 -070028
29from oftest import config
30import oftest.base_tests as base_tests
31import ofp
32import oftest.packet as scapy
33
34from oftest.testutils import *
35from oftest.parse import parse_ipv6
36
37class AllFlowStats(base_tests.SimpleDataPlane):
38 """
39 Retrieve all flows and verify the stats entries match the flow-mods sent
40 """
41 def runTest(self):
42 port1, port2, port3 = openflow_ports(3)
Wilson Ng6f539642013-10-28 18:17:44 -070043 table_id = test_param_get("table", 0)
Rich Lane102d71d2013-10-04 14:09:34 -070044 delete_all_flows(self.controller)
45
46 flow1 = ofp.message.flow_add(
Wilson Ng42df57a2013-10-28 17:54:57 -070047 table_id=table_id,
Rich Lane102d71d2013-10-04 14:09:34 -070048 priority=0x11,
49 idle_timeout=0x21,
50 hard_timeout=0x31,
51 flags=ofp.OFPFF_NO_PKT_COUNTS,
52 cookie=1,
53 match=ofp.match([
54 ofp.oxm.in_port(port1),
55 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|1)]),
56 instructions=[
57 ofp.instruction.write_actions(
58 actions=[
59 ofp.action.output(
60 port=port1,
61 max_len=ofp.OFPCML_NO_BUFFER)])],
62 buffer_id=ofp.OFP_NO_BUFFER)
63
64 flow2 = ofp.message.flow_add(
Wilson Ng42df57a2013-10-28 17:54:57 -070065 table_id=table_id,
Rich Lane102d71d2013-10-04 14:09:34 -070066 priority=0x12,
67 idle_timeout=0x22,
68 hard_timeout=0x32,
69 flags=ofp.OFPFF_NO_BYT_COUNTS,
70 cookie=2,
71 match=ofp.match([
72 ofp.oxm.in_port(port2),
73 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2)]),
74 instructions=[
75 ofp.instruction.write_actions(
76 actions=[
77 ofp.action.output(
78 port=port2,
79 max_len=ofp.OFPCML_NO_BUFFER)])],
80 buffer_id=ofp.OFP_NO_BUFFER)
81
82 flow3 = ofp.message.flow_add(
Wilson Ng42df57a2013-10-28 17:54:57 -070083 table_id=table_id,
Rich Lane102d71d2013-10-04 14:09:34 -070084 priority=0x13,
85 idle_timeout=0x23,
86 hard_timeout=0x33,
87 flags=ofp.OFPFF_CHECK_OVERLAP,
88 cookie=3,
89 match=ofp.match([
90 ofp.oxm.in_port(port3),
91 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|3)]),
92 instructions=[
93 ofp.instruction.write_actions(
94 actions=[
95 ofp.action.output(
96 port=port3,
97 max_len=ofp.OFPCML_NO_BUFFER)])],
98 buffer_id=ofp.OFP_NO_BUFFER)
99
100 flows = [flow1, flow2, flow3]
101 for flow in flows:
102 logging.debug(flow.show())
103 self.controller.message_send(flow)
104
105 flows_by_cookie = { flow.cookie: flow for flow in flows }
106
107 do_barrier(self.controller)
108
109 logging.info("Sending flow stats request")
110 stats = get_flow_stats(self, ofp.match())
111 logging.info("Received %d flow stats entries", len(stats))
112
113 seen_cookies = set()
114 for entry in stats:
115 logging.debug(entry.show())
116 self.assertTrue(entry.cookie in flows_by_cookie, "Unexpected cookie")
117 self.assertTrue(entry.cookie not in seen_cookies, "Duplicate cookie")
118 flow = flows_by_cookie[entry.cookie]
119 seen_cookies.add(entry.cookie)
120
121 self.assertEqual(entry.table_id, flow.table_id)
122 self.assertEqual(entry.priority, flow.priority)
123 self.assertEqual(entry.idle_timeout, flow.idle_timeout)
124 self.assertEqual(entry.hard_timeout, flow.hard_timeout)
125 self.assertEqual(entry.flags, flow.flags)
126 self.assertEqual(entry.cookie, flow.cookie)
127 self.assertEqual(sorted(entry.match.oxm_list), sorted(flow.match.oxm_list))
128 self.assertEqual(sorted(entry.instructions), sorted(flow.instructions))
129
130 self.assertEqual(seen_cookies, set([1,2,3]))
Rich Laned15c6652013-10-04 14:42:26 -0700131
132class CookieFlowStats(base_tests.SimpleDataPlane):
133 """
134 Retrieve flows using various masks on the cookie
135 """
136 def runTest(self):
137 delete_all_flows(self.controller)
138
139 # Also used as masks
140 cookies = [
141 0x0000000000000000,
142 0xDDDDDDDD00000000,
143 0x00000000DDDDDDDD,
144 0xDDDDDDDDDDDDDDDD,
145 0xDDDD0000DDDD0000,
146 0x0000DDDD0000DDDD,
147 0xDD00DD00DD00DD00,
148 0xD0D0D0D0D0D0D0D0,
149 0xF000000000000000,
150 0xFF00000000000000,
151 0xFFF0000000000000,
152 0xFFFF000000000000,
153 ]
154
Rich Lane43ffb102013-10-07 10:24:05 -0700155 for i in range(0, 10):
156 cookies.append(random.getrandbits(64))
157
Rich Laned15c6652013-10-04 14:42:26 -0700158 # Generate the matching cookies for each combination of cookie and mask
159 matches = {}
Rich Lanef58cae22013-10-07 11:10:04 -0700160 for mask in cookies:
161 for cookie in cookies:
Rich Laned15c6652013-10-04 14:42:26 -0700162 matching = []
163 for cookie2 in cookies:
164 if cookie & mask == cookie2 & mask:
165 matching.append(cookie2)
166 matches[(cookie, mask)] = sorted(matching)
167
168 # Generate a flow for each cookie
169 flows = {}
Wilson Ng6f539642013-10-28 18:17:44 -0700170 table_id = test_param_get("table", 0)
Rich Laned15c6652013-10-04 14:42:26 -0700171 for idx, cookie in enumerate(cookies):
172 flows[cookie] = ofp.message.flow_add(
Wilson Ng6f539642013-10-28 18:17:44 -0700173 table_id=table_id,
Rich Laned15c6652013-10-04 14:42:26 -0700174 cookie=cookie,
175 match=ofp.match([ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|idx)]),
176 buffer_id=ofp.OFP_NO_BUFFER)
177
178 # Install flows
179 for flow in flows.values():
180 self.controller.message_send(flow)
181 do_barrier(self.controller)
182
183 # For each combination of cookie and match, verify the correct flows
184 # are retrieved
Rich Lane316204b2013-10-07 11:08:03 -0700185 for (cookie, mask), expected_cookies in matches.iteritems():
Rich Laned15c6652013-10-04 14:42:26 -0700186 stats = get_flow_stats(self, ofp.match(), cookie=cookie, cookie_mask=mask)
187 received_cookies = sorted([entry.cookie for entry in stats])
188 logging.debug("expected 0x%016x/0x%016x: %s", cookie, mask,
189 ' '.join(["0x%016x" % x for x in expected_cookies]))
190 logging.debug("received 0x%016x/0x%016x: %s", cookie, mask,
191 ' '.join(["0x%016x" % x for x in received_cookies]))
192 self.assertEqual(expected_cookies, received_cookies)