backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / lib / ofctl_v1_4.py
1 # Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.
2 #
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
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
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
12 # implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 import logging
17
18 from ryu.ofproto import ether
19 from ryu.ofproto import ofproto_v1_4
20 from ryu.ofproto import ofproto_v1_4_parser
21 from ryu.lib import ofctl_utils
22
23 LOG = logging.getLogger(__name__)
24
25 DEFAULT_TIMEOUT = 1.0
26
27 UTIL = ofctl_utils.OFCtlUtil(ofproto_v1_4)
28 str_to_int = ofctl_utils.str_to_int
29
30
31 def to_action(dp, dic):
32     ofp = dp.ofproto
33     parser = dp.ofproto_parser
34     action_type = dic.get('type')
35     return ofctl_utils.to_action(dic, ofp, parser, action_type, UTIL)
36
37
38 def _get_actions(dp, dics):
39     actions = []
40     for d in dics:
41         action = to_action(dp, d)
42         if action is not None:
43             actions.append(action)
44         else:
45             LOG.error('Unknown action type: %s', d)
46     return actions
47
48
49 def to_instructions(dp, insts):
50     instructions = []
51     ofp = dp.ofproto
52     parser = dp.ofproto_parser
53
54     for i in insts:
55         inst_type = i.get('type')
56         if inst_type in ['APPLY_ACTIONS', 'WRITE_ACTIONS']:
57             dics = i.get('actions', [])
58             actions = _get_actions(dp, dics)
59             if actions:
60                 if inst_type == 'APPLY_ACTIONS':
61                     instructions.append(
62                         parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
63                                                      actions))
64                 else:
65                     instructions.append(
66                         parser.OFPInstructionActions(ofp.OFPIT_WRITE_ACTIONS,
67                                                      actions))
68         elif inst_type == 'CLEAR_ACTIONS':
69             instructions.append(
70                 parser.OFPInstructionActions(ofp.OFPIT_CLEAR_ACTIONS, []))
71         elif inst_type == 'GOTO_TABLE':
72             table_id = str_to_int(i.get('table_id'))
73             instructions.append(parser.OFPInstructionGotoTable(table_id))
74         elif inst_type == 'WRITE_METADATA':
75             metadata = str_to_int(i.get('metadata'))
76             metadata_mask = (str_to_int(i['metadata_mask'])
77                              if 'metadata_mask' in i
78                              else parser.UINT64_MAX)
79             instructions.append(
80                 parser.OFPInstructionWriteMetadata(
81                     metadata, metadata_mask))
82         elif inst_type == 'METER':
83             meter_id = str_to_int(i.get('meter_id'))
84             instructions.append(parser.OFPInstructionMeter(meter_id))
85         else:
86             LOG.error('Unknown instruction type: %s', inst_type)
87
88     return instructions
89
90
91 def action_to_str(act):
92     s = act.to_jsondict()[act.__class__.__name__]
93     t = UTIL.ofp_action_type_to_user(s['type'])
94     s['type'] = t if t != s['type'] else 'UNKNOWN'
95
96     if 'field' in s:
97         field = s.pop('field')
98         s['field'] = field['OXMTlv']['field']
99         s['mask'] = field['OXMTlv']['mask']
100         s['value'] = field['OXMTlv']['value']
101
102     return s
103
104
105 def instructions_to_str(instructions):
106
107     s = []
108
109     for i in instructions:
110         v = i.to_jsondict()[i.__class__.__name__]
111         t = UTIL.ofp_instruction_type_to_user(v['type'])
112         inst_type = t if t != v['type'] else 'UNKNOWN'
113         # apply/write/clear-action instruction
114         if isinstance(i, ofproto_v1_4_parser.OFPInstructionActions):
115             acts = []
116             for a in i.actions:
117                 acts.append(action_to_str(a))
118             v['type'] = inst_type
119             v['actions'] = acts
120             s.append(v)
121         # others
122         else:
123             v['type'] = inst_type
124             s.append(v)
125
126     return s
127
128
129 def to_match(dp, attrs):
130     convert = {'in_port': UTIL.ofp_port_from_user,
131                'in_phy_port': str_to_int,
132                'metadata': ofctl_utils.to_match_masked_int,
133                'eth_dst': ofctl_utils.to_match_eth,
134                'eth_src': ofctl_utils.to_match_eth,
135                'eth_type': str_to_int,
136                'vlan_vid': to_match_vid,
137                'vlan_pcp': str_to_int,
138                'ip_dscp': str_to_int,
139                'ip_ecn': str_to_int,
140                'ip_proto': str_to_int,
141                'ipv4_src': ofctl_utils.to_match_ip,
142                'ipv4_dst': ofctl_utils.to_match_ip,
143                'tcp_src': str_to_int,
144                'tcp_dst': str_to_int,
145                'udp_src': str_to_int,
146                'udp_dst': str_to_int,
147                'sctp_src': str_to_int,
148                'sctp_dst': str_to_int,
149                'icmpv4_type': str_to_int,
150                'icmpv4_code': str_to_int,
151                'arp_op': str_to_int,
152                'arp_spa': ofctl_utils.to_match_ip,
153                'arp_tpa': ofctl_utils.to_match_ip,
154                'arp_sha': ofctl_utils.to_match_eth,
155                'arp_tha': ofctl_utils.to_match_eth,
156                'ipv6_src': ofctl_utils.to_match_ip,
157                'ipv6_dst': ofctl_utils.to_match_ip,
158                'ipv6_flabel': str_to_int,
159                'icmpv6_type': str_to_int,
160                'icmpv6_code': str_to_int,
161                'ipv6_nd_target': ofctl_utils.to_match_ip,
162                'ipv6_nd_sll': ofctl_utils.to_match_eth,
163                'ipv6_nd_tll': ofctl_utils.to_match_eth,
164                'mpls_label': str_to_int,
165                'mpls_tc': str_to_int,
166                'mpls_bos': str_to_int,
167                'pbb_isid': ofctl_utils.to_match_masked_int,
168                'tunnel_id': ofctl_utils.to_match_masked_int,
169                'ipv6_exthdr': ofctl_utils.to_match_masked_int,
170                'pbb_uca': str_to_int}
171
172     keys = {'dl_dst': 'eth_dst',
173             'dl_src': 'eth_src',
174             'dl_type': 'eth_type',
175             'dl_vlan': 'vlan_vid',
176             'nw_src': 'ipv4_src',
177             'nw_dst': 'ipv4_dst',
178             'nw_proto': 'ip_proto'}
179
180     if attrs.get('eth_type') == ether.ETH_TYPE_ARP:
181         if 'ipv4_src' in attrs and 'arp_spa' not in attrs:
182             attrs['arp_spa'] = attrs['ipv4_src']
183             del attrs['ipv4_src']
184         if 'ipv4_dst' in attrs and 'arp_tpa' not in attrs:
185             attrs['arp_tpa'] = attrs['ipv4_dst']
186             del attrs['ipv4_dst']
187
188     kwargs = {}
189     for key, value in attrs.items():
190         if key in keys:
191             # For old field name
192             key = keys[key]
193         if key in convert:
194             value = convert[key](value)
195             kwargs[key] = value
196         else:
197             LOG.error('Unknown match field: %s', key)
198
199     return dp.ofproto_parser.OFPMatch(**kwargs)
200
201
202 def to_match_vid(value):
203     return ofctl_utils.to_match_vid(value, ofproto_v1_4.OFPVID_PRESENT)
204
205
206 def match_to_str(ofmatch):
207     match = {}
208
209     ofmatch = ofmatch.to_jsondict()['OFPMatch']
210     ofmatch = ofmatch['oxm_fields']
211
212     for match_field in ofmatch:
213         key = match_field['OXMTlv']['field']
214         mask = match_field['OXMTlv']['mask']
215         value = match_field['OXMTlv']['value']
216         if key == 'vlan_vid':
217             value = match_vid_to_str(value, mask)
218         elif key == 'in_port':
219             value = UTIL.ofp_port_to_user(value)
220         else:
221             if mask is not None:
222                 value = str(value) + '/' + str(mask)
223         match.setdefault(key, value)
224
225     return match
226
227
228 def match_vid_to_str(value, mask):
229     return ofctl_utils.match_vid_to_str(
230         value, mask, ofproto_v1_4.OFPVID_PRESENT)
231
232
233 def wrap_dpid_dict(dp, value, to_user=True):
234     if to_user:
235         return {str(dp.id): value}
236
237     return {dp.id: value}
238
239
240 def get_desc_stats(dp, waiters, to_user=True):
241     stats = dp.ofproto_parser.OFPDescStatsRequest(dp, 0)
242     msgs = []
243     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
244     s = {}
245
246     for msg in msgs:
247         stats = msg.body
248         s = stats.to_jsondict()[stats.__class__.__name__]
249
250     return wrap_dpid_dict(dp, s, to_user)
251
252
253 def get_queue_stats(dp, waiters, port_no=None, queue_id=None, to_user=True):
254     if port_no is None:
255         port_no = dp.ofproto.OFPP_ANY
256     else:
257         port_no = UTIL.ofp_port_from_user(port_no)
258     if queue_id is None:
259         queue_id = dp.ofproto.OFPQ_ALL
260     else:
261         queue_id = UTIL.ofp_queue_from_user(queue_id)
262
263     stats = dp.ofproto_parser.OFPQueueStatsRequest(
264         dp, 0, port_no, queue_id)
265     msgs = []
266     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
267
268     desc = []
269     for msg in msgs:
270         stats = msg.body
271         for stat in stats:
272             s = stat.to_jsondict()[stat.__class__.__name__]
273             properties = []
274             for prop in stat.properties:
275                 p = prop.to_jsondict()[prop.__class__.__name__]
276                 if to_user:
277                     t = UTIL.ofp_queue_stats_prop_type_to_user(prop.type)
278                     p['type'] = t if t != p['type'] else 'UNKNOWN'
279                 properties.append(p)
280             s['properties'] = properties
281             desc.append(s)
282
283     return wrap_dpid_dict(dp, desc, to_user)
284
285
286 def get_queue_desc(dp, waiters, port_no=None, queue_id=None, to_user=True):
287     if port_no is None:
288         port_no = dp.ofproto.OFPP_ANY
289     else:
290         port_no = UTIL.ofp_port_from_user(port_no)
291     if queue_id is None:
292         queue_id = dp.ofproto.OFPQ_ALL
293     else:
294         queue_id = UTIL.ofp_queue_from_user(queue_id)
295
296     stats = dp.ofproto_parser.OFPQueueDescStatsRequest(
297         dp, 0, port_no, queue_id)
298     msgs = []
299     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
300
301     configs = []
302     for msg in msgs:
303         for queue in msg.body:
304             q = queue.to_jsondict()[queue.__class__.__name__]
305             prop_list = []
306             for prop in queue.properties:
307                 p = prop.to_jsondict()[prop.__class__.__name__]
308                 if to_user:
309                     t = UTIL.ofp_queue_desc_prop_type_to_user(prop.type)
310                     p['type'] = t if t != prop.type else 'UNKNOWN'
311                 prop_list.append(p)
312             q['properties'] = prop_list
313             configs.append(q)
314
315     return wrap_dpid_dict(dp, configs, to_user)
316
317
318 def get_flow_stats(dp, waiters, flow=None, to_user=True):
319     flow = flow if flow else {}
320     table_id = UTIL.ofp_table_from_user(
321         flow.get('table_id', dp.ofproto.OFPTT_ALL))
322     flags = str_to_int(flow.get('flags', 0))
323     out_port = UTIL.ofp_port_from_user(
324         flow.get('out_port', dp.ofproto.OFPP_ANY))
325     out_group = UTIL.ofp_group_from_user(
326         flow.get('out_group', dp.ofproto.OFPG_ANY))
327     cookie = str_to_int(flow.get('cookie', 0))
328     cookie_mask = str_to_int(flow.get('cookie_mask', 0))
329     match = to_match(dp, flow.get('match', {}))
330     # Note: OpenFlow does not allow to filter flow entries by priority,
331     # but for efficiency, ofctl provides the way to do it.
332     priority = str_to_int(flow.get('priority', -1))
333
334     stats = dp.ofproto_parser.OFPFlowStatsRequest(
335         dp, flags, table_id, out_port, out_group, cookie, cookie_mask,
336         match)
337
338     msgs = []
339     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
340
341     flows = []
342     for msg in msgs:
343         for stats in msg.body:
344             if 0 <= priority != stats.priority:
345                 continue
346
347             s = stats.to_jsondict()[stats.__class__.__name__]
348             s['instructions'] = instructions_to_str(stats.instructions)
349             s['match'] = match_to_str(stats.match)
350             flows.append(s)
351
352     return wrap_dpid_dict(dp, flows, to_user)
353
354
355 def get_aggregate_flow_stats(dp, waiters, flow=None, to_user=True):
356     flow = flow if flow else {}
357     table_id = UTIL.ofp_table_from_user(
358         flow.get('table_id', dp.ofproto.OFPTT_ALL))
359     flags = str_to_int(flow.get('flags', 0))
360     out_port = UTIL.ofp_port_from_user(
361         flow.get('out_port', dp.ofproto.OFPP_ANY))
362     out_group = UTIL.ofp_group_from_user(
363         flow.get('out_group', dp.ofproto.OFPG_ANY))
364     cookie = str_to_int(flow.get('cookie', 0))
365     cookie_mask = str_to_int(flow.get('cookie_mask', 0))
366     match = to_match(dp, flow.get('match', {}))
367
368     stats = dp.ofproto_parser.OFPAggregateStatsRequest(
369         dp, flags, table_id, out_port, out_group, cookie, cookie_mask,
370         match)
371
372     msgs = []
373     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
374
375     flows = []
376     for msg in msgs:
377         stats = msg.body
378         s = stats.to_jsondict()[stats.__class__.__name__]
379         flows.append(s)
380
381     return wrap_dpid_dict(dp, flows, to_user)
382
383
384 def get_table_stats(dp, waiters, to_user=True):
385     stats = dp.ofproto_parser.OFPTableStatsRequest(dp, 0)
386     msgs = []
387     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
388
389     tables = []
390     for msg in msgs:
391         stats = msg.body
392         for stat in stats:
393             s = stat.to_jsondict()[stat.__class__.__name__]
394
395             if to_user:
396                 s['table_id'] = UTIL.ofp_table_to_user(stat.table_id)
397
398             tables.append(s)
399
400     return wrap_dpid_dict(dp, tables, to_user)
401
402
403 def get_table_features(dp, waiters, to_user=True):
404     stats = dp.ofproto_parser.OFPTableFeaturesStatsRequest(dp, 0, [])
405     msgs = []
406     ofproto = dp.ofproto
407     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
408
409     p_type_instructions = [ofproto.OFPTFPT_INSTRUCTIONS,
410                            ofproto.OFPTFPT_INSTRUCTIONS_MISS]
411
412     p_type_next_tables = [ofproto.OFPTFPT_NEXT_TABLES,
413                           ofproto.OFPTFPT_NEXT_TABLES_MISS,
414                           ofproto.OFPTFPT_TABLE_SYNC_FROM]
415
416     p_type_actions = [ofproto.OFPTFPT_WRITE_ACTIONS,
417                       ofproto.OFPTFPT_WRITE_ACTIONS_MISS,
418                       ofproto.OFPTFPT_APPLY_ACTIONS,
419                       ofproto.OFPTFPT_APPLY_ACTIONS_MISS]
420
421     p_type_oxms = [ofproto.OFPTFPT_MATCH,
422                    ofproto.OFPTFPT_WILDCARDS,
423                    ofproto.OFPTFPT_WRITE_SETFIELD,
424                    ofproto.OFPTFPT_WRITE_SETFIELD_MISS,
425                    ofproto.OFPTFPT_APPLY_SETFIELD,
426                    ofproto.OFPTFPT_APPLY_SETFIELD_MISS]
427
428     p_type_experimenter = [ofproto.OFPTFPT_EXPERIMENTER,
429                            ofproto.OFPTFPT_EXPERIMENTER_MISS]
430
431     tables = []
432     for msg in msgs:
433         stats = msg.body
434         for stat in stats:
435             s = stat.to_jsondict()[stat.__class__.__name__]
436             properties = []
437             for prop in stat.properties:
438                 p = {}
439                 t = UTIL.ofp_table_feature_prop_type_to_user(prop.type)
440                 p['type'] = t if t != prop.type else 'UNKNOWN'
441                 if prop.type in p_type_instructions:
442                     instruction_ids = []
443                     for i in prop.instruction_ids:
444                         inst = {'len': i.len,
445                                 'type': i.type}
446                         instruction_ids.append(inst)
447                     p['instruction_ids'] = instruction_ids
448                 elif prop.type in p_type_next_tables:
449                     table_ids = []
450                     for i in prop.table_ids:
451                         table_ids.append(i)
452                     p['table_ids'] = table_ids
453                 elif prop.type in p_type_actions:
454                     action_ids = []
455                     for i in prop.action_ids:
456                         act = i.to_jsondict()[i.__class__.__name__]
457                         action_ids.append(act)
458                     p['action_ids'] = action_ids
459                 elif prop.type in p_type_oxms:
460                     oxm_ids = []
461                     for i in prop.oxm_ids:
462                         oxm = i.to_jsondict()[i.__class__.__name__]
463                         oxm_ids.append(oxm)
464                     p['oxm_ids'] = oxm_ids
465                 elif prop.type in p_type_experimenter:
466                     pass
467                 properties.append(p)
468             s['name'] = stat.name.decode('utf-8')
469             s['properties'] = properties
470
471             if to_user:
472                 s['table_id'] = UTIL.ofp_table_to_user(stat.table_id)
473
474             tables.append(s)
475
476     return wrap_dpid_dict(dp, tables, to_user)
477
478
479 def get_port_stats(dp, waiters, port_no=None, to_user=True):
480     if port_no is None:
481         port_no = dp.ofproto.OFPP_ANY
482     else:
483         port_no = UTIL.ofp_port_from_user(port_no)
484
485     stats = dp.ofproto_parser.OFPPortStatsRequest(dp, 0, port_no)
486     msgs = []
487     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
488
489     ports = []
490     for msg in msgs:
491         for stats in msg.body:
492             s = stats.to_jsondict()[stats.__class__.__name__]
493             properties = []
494             for prop in stats.properties:
495                 p = prop.to_jsondict()[prop.__class__.__name__]
496                 t = UTIL.ofp_port_stats_prop_type_to_user(prop.type)
497                 p['type'] = t if t != prop.type else 'UNKNOWN'
498                 properties.append(p)
499             s['properties'] = properties
500
501             if to_user:
502                 s['port_no'] = UTIL.ofp_port_to_user(stats.port_no)
503
504             ports.append(s)
505
506     return wrap_dpid_dict(dp, ports, to_user)
507
508
509 def get_meter_stats(dp, waiters, meter_id=None, to_user=True):
510     if meter_id is None:
511         meter_id = dp.ofproto.OFPM_ALL
512     else:
513         meter_id = UTIL.ofp_meter_from_user(meter_id)
514
515     stats = dp.ofproto_parser.OFPMeterStatsRequest(
516         dp, 0, meter_id)
517     msgs = []
518     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
519
520     meters = []
521     for msg in msgs:
522         for stats in msg.body:
523             s = stats.to_jsondict()[stats.__class__.__name__]
524             bands = []
525             for band in stats.band_stats:
526                 b = band.to_jsondict()[band.__class__.__name__]
527                 bands.append(b)
528             s['band_stats'] = bands
529
530             if to_user:
531                 s['meter_id'] = UTIL.ofp_meter_to_user(stats.meter_id)
532
533             meters.append(s)
534
535     return wrap_dpid_dict(dp, meters, to_user)
536
537
538 def get_meter_features(dp, waiters, to_user=True):
539     ofp = dp.ofproto
540     type_convert = {ofp.OFPMBT_DROP: 'DROP',
541                     ofp.OFPMBT_DSCP_REMARK: 'DSCP_REMARK'}
542
543     capa_convert = {ofp.OFPMF_KBPS: 'KBPS',
544                     ofp.OFPMF_PKTPS: 'PKTPS',
545                     ofp.OFPMF_BURST: 'BURST',
546                     ofp.OFPMF_STATS: 'STATS'}
547
548     stats = dp.ofproto_parser.OFPMeterFeaturesStatsRequest(dp, 0)
549     msgs = []
550     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
551
552     features = []
553     for msg in msgs:
554         for feature in msg.body:
555             band_types = []
556             for k, v in type_convert.items():
557                 if (1 << k) & feature.band_types:
558
559                     if to_user:
560                         band_types.append(v)
561
562                     else:
563                         band_types.append(k)
564
565             capabilities = []
566             for k, v in sorted(capa_convert.items()):
567                 if k & feature.capabilities:
568
569                     if to_user:
570                         capabilities.append(v)
571
572                     else:
573                         capabilities.append(k)
574
575             f = {'max_meter': feature.max_meter,
576                  'band_types': band_types,
577                  'capabilities': capabilities,
578                  'max_bands': feature.max_bands,
579                  'max_color': feature.max_color}
580             features.append(f)
581
582     return wrap_dpid_dict(dp, features, to_user)
583
584
585 def get_meter_config(dp, waiters, meter_id=None, to_user=True):
586     flags = {dp.ofproto.OFPMF_KBPS: 'KBPS',
587              dp.ofproto.OFPMF_PKTPS: 'PKTPS',
588              dp.ofproto.OFPMF_BURST: 'BURST',
589              dp.ofproto.OFPMF_STATS: 'STATS'}
590
591     if meter_id is None:
592         meter_id = dp.ofproto.OFPM_ALL
593     else:
594         meter_id = UTIL.ofp_meter_from_user(meter_id)
595
596     stats = dp.ofproto_parser.OFPMeterConfigStatsRequest(
597         dp, 0, meter_id)
598     msgs = []
599     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
600
601     configs = []
602     for msg in msgs:
603         for config in msg.body:
604             c = config.to_jsondict()[config.__class__.__name__]
605             bands = []
606             for band in config.bands:
607                 b = band.to_jsondict()[band.__class__.__name__]
608
609                 if to_user:
610                     t = UTIL.ofp_meter_band_type_to_user(band.type)
611                     b['type'] = t if t != band.type else 'UNKNOWN'
612
613                 bands.append(b)
614             c_flags = []
615             for k, v in sorted(flags.items()):
616                 if k & config.flags:
617                     if to_user:
618                         c_flags.append(v)
619
620                     else:
621                         c_flags.append(k)
622
623             c['flags'] = c_flags
624             c['bands'] = bands
625
626             if to_user:
627                 c['meter_id'] = UTIL.ofp_meter_to_user(config.meter_id)
628
629             configs.append(c)
630
631     return wrap_dpid_dict(dp, configs, to_user)
632
633
634 def get_group_stats(dp, waiters, group_id=None, to_user=True):
635     if group_id is None:
636         group_id = dp.ofproto.OFPG_ALL
637     else:
638         group_id = UTIL.ofp_group_from_user(group_id)
639
640     stats = dp.ofproto_parser.OFPGroupStatsRequest(
641         dp, 0, group_id)
642     msgs = []
643     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
644
645     groups = []
646     for msg in msgs:
647         for stats in msg.body:
648             g = stats.to_jsondict()[stats.__class__.__name__]
649             bucket_stats = []
650             for bucket_stat in stats.bucket_stats:
651                 c = bucket_stat.to_jsondict()[bucket_stat.__class__.__name__]
652                 bucket_stats.append(c)
653             g['bucket_stats'] = bucket_stats
654
655             if to_user:
656                 g['group_id'] = UTIL.ofp_group_to_user(stats.group_id)
657
658             groups.append(g)
659
660     return wrap_dpid_dict(dp, groups, to_user)
661
662
663 def get_group_features(dp, waiters, to_user=True):
664
665     ofp = dp.ofproto
666     type_convert = {ofp.OFPGT_ALL: 'ALL',
667                     ofp.OFPGT_SELECT: 'SELECT',
668                     ofp.OFPGT_INDIRECT: 'INDIRECT',
669                     ofp.OFPGT_FF: 'FF'}
670     cap_convert = {ofp.OFPGFC_SELECT_WEIGHT: 'SELECT_WEIGHT',
671                    ofp.OFPGFC_SELECT_LIVENESS: 'SELECT_LIVENESS',
672                    ofp.OFPGFC_CHAINING: 'CHAINING',
673                    ofp.OFPGFC_CHAINING_CHECKS: 'CHAINING_CHECKS'}
674     act_convert = {ofp.OFPAT_OUTPUT: 'OUTPUT',
675                    ofp.OFPAT_COPY_TTL_OUT: 'COPY_TTL_OUT',
676                    ofp.OFPAT_COPY_TTL_IN: 'COPY_TTL_IN',
677                    ofp.OFPAT_SET_MPLS_TTL: 'SET_MPLS_TTL',
678                    ofp.OFPAT_DEC_MPLS_TTL: 'DEC_MPLS_TTL',
679                    ofp.OFPAT_PUSH_VLAN: 'PUSH_VLAN',
680                    ofp.OFPAT_POP_VLAN: 'POP_VLAN',
681                    ofp.OFPAT_PUSH_MPLS: 'PUSH_MPLS',
682                    ofp.OFPAT_POP_MPLS: 'POP_MPLS',
683                    ofp.OFPAT_SET_QUEUE: 'SET_QUEUE',
684                    ofp.OFPAT_GROUP: 'GROUP',
685                    ofp.OFPAT_SET_NW_TTL: 'SET_NW_TTL',
686                    ofp.OFPAT_DEC_NW_TTL: 'DEC_NW_TTL',
687                    ofp.OFPAT_SET_FIELD: 'SET_FIELD',
688                    ofp.OFPAT_PUSH_PBB: 'PUSH_PBB',
689                    ofp.OFPAT_POP_PBB: 'POP_PBB',
690                    ofp.OFPAT_EXPERIMENTER: 'EXPERIMENTER'}
691
692     stats = dp.ofproto_parser.OFPGroupFeaturesStatsRequest(dp, 0)
693     msgs = []
694     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
695
696     features = []
697     for msg in msgs:
698         feature = msg.body
699         types = []
700         for k, v in type_convert.items():
701             if (1 << k) & feature.types:
702                 if to_user:
703                     types.append(v)
704
705                 else:
706                     types.append(k)
707
708         capabilities = []
709         for k, v in cap_convert.items():
710             if k & feature.capabilities:
711                 if to_user:
712                     capabilities.append(v)
713
714                 else:
715                     capabilities.append(k)
716
717         if to_user:
718             max_groups = []
719             for k, v in type_convert.items():
720                 max_groups.append({v: feature.max_groups[k]})
721
722         else:
723             max_groups = feature.max_groups
724
725         actions = []
726         for k1, v1 in type_convert.items():
727             acts = []
728             for k2, v2 in act_convert.items():
729                 if (1 << k2) & feature.actions[k1]:
730                     if to_user:
731                         acts.append(v2)
732
733                     else:
734                         acts.append(k2)
735
736             if to_user:
737                 actions.append({v1: acts})
738
739             else:
740                 actions.append({k1: acts})
741
742         f = {'types': types,
743              'capabilities': capabilities,
744              'max_groups': max_groups,
745              'actions': actions}
746         features.append(f)
747
748     return wrap_dpid_dict(dp, features, to_user)
749
750
751 def get_group_desc(dp, waiters, to_user=True):
752     stats = dp.ofproto_parser.OFPGroupDescStatsRequest(dp, 0)
753     msgs = []
754     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
755
756     descs = []
757     for msg in msgs:
758         for stats in msg.body:
759             d = stats.to_jsondict()[stats.__class__.__name__]
760             buckets = []
761             for bucket in stats.buckets:
762                 b = bucket.to_jsondict()[bucket.__class__.__name__]
763                 actions = []
764                 for action in bucket.actions:
765                     if to_user:
766                         actions.append(action_to_str(action))
767
768                     else:
769                         actions.append(action)
770                 b['actions'] = actions
771                 buckets.append(b)
772
773             d['buckets'] = buckets
774             if to_user:
775                 d['group_id'] = UTIL.ofp_group_to_user(stats.group_id)
776                 t = UTIL.ofp_group_type_to_user(stats.type)
777                 d['type'] = t if t != stats.type else 'UNKNOWN'
778
779             descs.append(d)
780
781     return wrap_dpid_dict(dp, descs, to_user)
782
783
784 def get_port_desc(dp, waiters, port_no=None, to_user=True):
785     if port_no is None:
786         port_no = dp.ofproto.OFPP_ANY
787     else:
788         port_no = UTIL.ofp_port_from_user(port_no)
789
790     stats = dp.ofproto_parser.OFPPortDescStatsRequest(dp, 0, port_no)
791     msgs = []
792     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
793
794     descs = []
795
796     for msg in msgs:
797         stats = msg.body
798         for stat in stats:
799             d = stat.to_jsondict()[stat.__class__.__name__]
800             properties = []
801             for prop in stat.properties:
802                 p = prop.to_jsondict()[prop.__class__.__name__]
803
804                 if to_user:
805                     t = UTIL.ofp_port_desc_prop_type_to_user(prop.type)
806                     p['type'] = t if t != prop.type else 'UNKNOWN'
807
808                 properties.append(p)
809             d['name'] = stat.name.decode('utf-8')
810             d['properties'] = properties
811
812             if to_user:
813                 d['port_no'] = UTIL.ofp_port_to_user(stat.port_no)
814
815             descs.append(d)
816
817     return wrap_dpid_dict(dp, descs, to_user)
818
819
820 def get_role(dp, waiters, to_user=True):
821     return ofctl_utils.get_role(dp, waiters, to_user)
822
823
824 def mod_flow_entry(dp, flow, cmd):
825     cookie = str_to_int(flow.get('cookie', 0))
826     cookie_mask = str_to_int(flow.get('cookie_mask', 0))
827     table_id = UTIL.ofp_table_from_user(flow.get('table_id', 0))
828     idle_timeout = str_to_int(flow.get('idle_timeout', 0))
829     hard_timeout = str_to_int(flow.get('hard_timeout', 0))
830     priority = str_to_int(flow.get('priority', 0))
831     buffer_id = UTIL.ofp_buffer_from_user(
832         flow.get('buffer_id', dp.ofproto.OFP_NO_BUFFER))
833     out_port = UTIL.ofp_port_from_user(
834         flow.get('out_port', dp.ofproto.OFPP_ANY))
835     out_group = UTIL.ofp_group_from_user(
836         flow.get('out_group', dp.ofproto.OFPG_ANY))
837     importance = str_to_int(flow.get('importance', 0))
838     flags = str_to_int(flow.get('flags', 0))
839     match = to_match(dp, flow.get('match', {}))
840     inst = to_instructions(dp, flow.get('instructions', []))
841
842     flow_mod = dp.ofproto_parser.OFPFlowMod(
843         dp, cookie, cookie_mask, table_id, cmd, idle_timeout,
844         hard_timeout, priority, buffer_id, out_port, out_group,
845         flags, importance, match, inst)
846
847     ofctl_utils.send_msg(dp, flow_mod, LOG)
848
849
850 def mod_meter_entry(dp, meter, cmd):
851     flags = 0
852     if 'flags' in meter:
853         meter_flags = meter['flags']
854         if not isinstance(meter_flags, list):
855             meter_flags = [meter_flags]
856         for flag in meter_flags:
857             t = UTIL.ofp_meter_flags_from_user(flag)
858             f = t if t != flag else None
859             if f is None:
860                 LOG.error('Unknown meter flag: %s', flag)
861                 continue
862             flags |= f
863
864     meter_id = UTIL.ofp_meter_from_user(meter.get('meter_id', 0))
865
866     bands = []
867     for band in meter.get('bands', []):
868         band_type = band.get('type')
869         rate = str_to_int(band.get('rate', 0))
870         burst_size = str_to_int(band.get('burst_size', 0))
871         if band_type == 'DROP':
872             bands.append(
873                 dp.ofproto_parser.OFPMeterBandDrop(rate, burst_size))
874         elif band_type == 'DSCP_REMARK':
875             prec_level = str_to_int(band.get('prec_level', 0))
876             bands.append(
877                 dp.ofproto_parser.OFPMeterBandDscpRemark(
878                     rate, burst_size, prec_level))
879         elif band_type == 'EXPERIMENTER':
880             experimenter = str_to_int(band.get('experimenter', 0))
881             bands.append(
882                 dp.ofproto_parser.OFPMeterBandExperimenter(
883                     rate, burst_size, experimenter))
884         else:
885             LOG.error('Unknown band type: %s', band_type)
886
887     meter_mod = dp.ofproto_parser.OFPMeterMod(
888         dp, cmd, flags, meter_id, bands)
889
890     ofctl_utils.send_msg(dp, meter_mod, LOG)
891
892
893 def mod_group_entry(dp, group, cmd):
894     group_type = str(group.get('type', 'ALL'))
895     t = UTIL.ofp_group_type_from_user(group_type)
896     group_type = t if t != group_type else None
897     if group_type is None:
898         LOG.error('Unknown group type: %s', group.get('type'))
899
900     group_id = UTIL.ofp_group_from_user(group.get('group_id', 0))
901
902     buckets = []
903     for bucket in group.get('buckets', []):
904         weight = str_to_int(bucket.get('weight', 0))
905         watch_port = str_to_int(
906             bucket.get('watch_port', dp.ofproto.OFPP_ANY))
907         watch_group = str_to_int(
908             bucket.get('watch_group', dp.ofproto.OFPG_ANY))
909         actions = []
910         for dic in bucket.get('actions', []):
911             action = to_action(dp, dic)
912             if action is not None:
913                 actions.append(action)
914         buckets.append(dp.ofproto_parser.OFPBucket(
915             weight, watch_port, watch_group, actions))
916
917     group_mod = dp.ofproto_parser.OFPGroupMod(
918         dp, cmd, group_type, group_id, buckets)
919
920     ofctl_utils.send_msg(dp, group_mod, LOG)
921
922
923 def mod_port_behavior(dp, port_config):
924     ofp = dp.ofproto
925     parser = dp.ofproto_parser
926     port_no = UTIL.ofp_port_from_user(port_config.get('port_no', 0))
927     hw_addr = str(port_config.get('hw_addr'))
928     config = str_to_int(port_config.get('config', 0))
929     mask = str_to_int(port_config.get('mask', 0))
930     properties = port_config.get('properties')
931
932     prop = []
933     for p in properties:
934         type_ = UTIL.ofp_port_mod_prop_type_from_user(p['type'])
935         length = None
936         if type_ == ofp.OFPPDPT_ETHERNET:
937             advertise = UTIL.ofp_port_features_from_user(p['advertise'])
938             prop.append(
939                 parser.OFPPortModPropEthernet(type_, length, advertise))
940         elif type_ == ofp.OFPPDPT_OPTICAL:
941             prop.append(
942                 parser.OFPPortModPropOptical(
943                     type_, length, p['configure'], p['freq_lmda'],
944                     p['fl_offset'], p['grid_span'], p['tx_pwr']))
945         elif type_ == ofp.OFPPDPT_EXPERIMENTER:
946             prop.append(
947                 parser.OFPPortModPropExperimenter(
948                     type_, length, p['experimenter'], p['exp_type'],
949                     p['data']))
950         else:
951             LOG.error('Unknown port desc prop type: %s', type_)
952
953     port_mod = dp.ofproto_parser.OFPPortMod(
954         dp, port_no, hw_addr, config, mask, prop)
955
956     ofctl_utils.send_msg(dp, port_mod, LOG)
957
958
959 def set_role(dp, role):
960     r = UTIL.ofp_role_from_user(role.get('role', dp.ofproto.OFPCR_ROLE_EQUAL))
961     role_request = dp.ofproto_parser.OFPRoleRequest(dp, r, 0)
962     ofctl_utils.send_msg(dp, role_request, LOG)
963
964
965 # NOTE(jkoelker) Alias common funcitons
966 send_experimenter = ofctl_utils.send_experimenter