1 # Copyright (C) 2012 Nippon Telegraph and Telephone Corporation.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 # vim: tabstop=4 shiftwidth=4 softtabstop=4
23 from ryu.lib import mac
24 from ryu.base import app_manager
25 from ryu.controller import ofp_event
26 from ryu.controller import handler
27 from ryu.controller import dpset
28 from ryu.controller.handler import MAIN_DISPATCHER
29 from ryu.controller.handler import CONFIG_DISPATCHER
30 from ryu.controller.handler import set_ev_cls
31 from ryu.ofproto import ofproto_v1_0
32 from ryu.ofproto import ofproto_v1_2
35 LOG = logging.getLogger(__name__)
38 LOG_TEST_START = 'TEST_START: %s'
39 LOG_TEST_RESULTS = 'TEST_RESULTS:'
40 LOG_TEST_FINISH = 'TEST_FINISHED: Completed=[%s] (OK=%s NG=%s SKIP=%s)'
41 LOG_TEST_UNSUPPORTED = 'SKIP (unsupported)'
44 class TestFlowBase(app_manager.RyuApp):
46 To run the tests is required for the following pair of functions.
48 To send flows to switch.
50 2. verify_<test name>() or _verify_default()
51 To check flows of switch.
54 _CONTEXTS = {'dpset': dpset.DPSet}
56 def __init__(self, *args, **kwargs):
57 super(TestFlowBase, self).__init__(*args, **kwargs)
64 if t.startswith("test_"):
65 self.pending.append(t)
66 self.pending.sort(reverse=True)
67 self.unclear = len(self.pending)
69 def delete_all_flows(self, dp):
70 if dp.ofproto == ofproto_v1_0:
71 match = dp.ofproto_parser.OFPMatch(dp.ofproto.OFPFW_ALL,
74 m = dp.ofproto_parser.OFPFlowMod(dp, match, 0,
75 dp.ofproto.OFPFC_DELETE,
77 dp.ofproto.OFPP_NONE, 0, None)
78 elif dp.ofproto == ofproto_v1_2:
79 match = dp.ofproto_parser.OFPMatch()
80 m = dp.ofproto_parser.OFPFlowMod(dp, 0, 0, dp.ofproto.OFPTT_ALL,
81 dp.ofproto.OFPFC_DELETE,
89 def send_flow_stats(self, dp):
90 if dp.ofproto == ofproto_v1_0:
91 match = dp.ofproto_parser.OFPMatch(dp.ofproto.OFPFW_ALL,
94 m = dp.ofproto_parser.OFPFlowStatsRequest(dp, 0, match,
95 0, dp.ofproto.OFPP_NONE)
96 elif dp.ofproto == ofproto_v1_2:
97 match = dp.ofproto_parser.OFPMatch()
98 m = dp.ofproto_parser.OFPFlowStatsRequest(dp, dp.ofproto.OFPTT_ALL,
105 def verify_default(self, dp, stats):
106 return 'function %s() is not found.' % ("verify" + self.current[4:], )
108 def start_next_test(self, dp):
109 self.delete_all_flows(dp)
111 if len(self.pending):
112 t = self.pending.pop()
113 if self.is_supported(t):
114 LOG.info(LOG_TEST_START, t)
118 self.send_flow_stats(dp)
120 self.results[t] = LOG_TEST_UNSUPPORTED
122 self.start_next_test(dp)
126 def print_results(self):
127 LOG.info("TEST_RESULTS:")
131 for t in sorted(self.results.keys()):
132 if self.results[t] is True:
134 elif self.results[t] == LOG_TEST_UNSUPPORTED:
138 LOG.info(" %s: %s", t, self.results[t])
139 LOG.info(LOG_TEST_FINISH, self.unclear == 0, ok, ng, skip)
141 @handler.set_ev_cls(ofp_event.EventOFPFlowStatsReply,
142 handler.MAIN_DISPATCHER)
143 def flow_reply_handler(self, ev):
146 @handler.set_ev_cls(ofp_event.EventOFPStatsReply,
147 handler.MAIN_DISPATCHER)
148 def stats_reply_handler(self, ev):
151 def run_verify(self, ev):
155 verify_func = self.verify_default
156 v = "verify" + self.current[4:]
158 verify_func = getattr(self, v)
160 result = verify_func(dp, msg.body)
164 self.results[self.current] = result
165 self.start_next_test(dp)
167 @handler.set_ev_cls(dpset.EventDP)
168 def handler_datapath(self, ev):
170 self.start_next_test(ev.dp)
172 @set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER)
173 def barrier_replay_handler(self, ev):
176 def haddr_to_str(self, addr):
177 return mac.haddr_to_str(addr)
179 def haddr_to_bin(self, string):
180 return mac.haddr_to_bin(string)
182 def haddr_masked(self, haddr_bin, mask_bin):
183 return mac.haddr_bitand(haddr_bin, mask_bin)
185 def ipv4_to_str(self, integre):
186 ip_list = [str((integre >> (24 - (n * 8)) & 255)) for n in range(4)]
187 return '.'.join(ip_list)
189 def ipv4_to_int(self, string):
190 ip = string.split('.')
198 def ipv4_masked(self, ip_int, mask_int):
199 return ip_int & mask_int
201 def ipv6_to_str(self, integres):
202 return ':'.join(hex(x)[2:] for x in integres)
204 def ipv6_to_int(self, string):
205 ip = string.split(':')
207 return [int(x, 16) for x in ip]
209 def ipv6_masked(self, ipv6_int, mask_int):
210 return [x & y for (x, y) in
211 itertools.izip(ipv6_int, mask_int)]
213 def is_supported(self, t):