backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / lib / ofctl_v1_3.py
1 # Copyright (C) 2013 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 base64
17 import logging
18
19 from ryu.ofproto import ether
20 from ryu.ofproto import inet
21 from ryu.ofproto import ofproto_common
22 from ryu.ofproto import ofproto_v1_3
23 from ryu.ofproto import ofproto_v1_3_parser
24 from ryu.lib import ofctl_nicira_ext
25 from ryu.lib import ofctl_utils
26
27
28 LOG = logging.getLogger('ryu.lib.ofctl_v1_3')
29
30 DEFAULT_TIMEOUT = 1.0
31
32 UTIL = ofctl_utils.OFCtlUtil(ofproto_v1_3)
33 str_to_int = ofctl_utils.str_to_int
34
35
36 def to_action(dp, dic):
37     ofp = dp.ofproto
38     parser = dp.ofproto_parser
39     action_type = dic.get('type')
40     return ofctl_utils.to_action(dic, ofp, parser, action_type, UTIL)
41
42
43 def to_actions(dp, acts):
44     inst = []
45     actions = []
46     ofp = dp.ofproto
47     parser = dp.ofproto_parser
48
49     for a in acts:
50         action = to_action(dp, a)
51
52         if action is not None:
53             actions.append(action)
54         else:
55             action_type = a.get('type')
56             if action_type == 'WRITE_ACTIONS':
57                 write_actions = []
58                 write_acts = a.get('actions')
59                 for act in write_acts:
60                     action = to_action(dp, act)
61                     if action is not None:
62                         write_actions.append(action)
63                     else:
64                         LOG.error('Unknown action type: %s', action_type)
65                 if write_actions:
66                     inst.append(
67                         parser.OFPInstructionActions(ofp.OFPIT_WRITE_ACTIONS,
68                                                      write_actions))
69             elif action_type == 'CLEAR_ACTIONS':
70                 inst.append(
71                     parser.OFPInstructionActions(ofp.OFPIT_CLEAR_ACTIONS, []))
72             elif action_type == 'GOTO_TABLE':
73                 table_id = UTIL.ofp_table_from_user(a.get('table_id'))
74                 inst.append(parser.OFPInstructionGotoTable(table_id))
75             elif action_type == 'WRITE_METADATA':
76                 metadata = str_to_int(a.get('metadata'))
77                 metadata_mask = (str_to_int(a['metadata_mask'])
78                                  if 'metadata_mask' in a
79                                  else parser.UINT64_MAX)
80                 inst.append(
81                     parser.OFPInstructionWriteMetadata(
82                         metadata, metadata_mask))
83             elif action_type == 'METER':
84                 meter_id = UTIL.ofp_meter_from_user(a.get('meter_id'))
85                 inst.append(parser.OFPInstructionMeter(meter_id))
86             else:
87                 LOG.error('Unknown action type: %s', action_type)
88
89     if actions:
90         inst.append(parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
91                                                  actions))
92     return inst
93
94
95 def action_to_str(act):
96     action_type = act.cls_action_type
97
98     if action_type == ofproto_v1_3.OFPAT_OUTPUT:
99         port = UTIL.ofp_port_to_user(act.port)
100         buf = 'OUTPUT:' + str(port)
101     elif action_type == ofproto_v1_3.OFPAT_COPY_TTL_OUT:
102         buf = 'COPY_TTL_OUT'
103     elif action_type == ofproto_v1_3.OFPAT_COPY_TTL_IN:
104         buf = 'COPY_TTL_IN'
105     elif action_type == ofproto_v1_3.OFPAT_SET_MPLS_TTL:
106         buf = 'SET_MPLS_TTL:' + str(act.mpls_ttl)
107     elif action_type == ofproto_v1_3.OFPAT_DEC_MPLS_TTL:
108         buf = 'DEC_MPLS_TTL'
109     elif action_type == ofproto_v1_3.OFPAT_PUSH_VLAN:
110         buf = 'PUSH_VLAN:' + str(act.ethertype)
111     elif action_type == ofproto_v1_3.OFPAT_POP_VLAN:
112         buf = 'POP_VLAN'
113     elif action_type == ofproto_v1_3.OFPAT_PUSH_MPLS:
114         buf = 'PUSH_MPLS:' + str(act.ethertype)
115     elif action_type == ofproto_v1_3.OFPAT_POP_MPLS:
116         buf = 'POP_MPLS:' + str(act.ethertype)
117     elif action_type == ofproto_v1_3.OFPAT_SET_QUEUE:
118         queue_id = UTIL.ofp_queue_to_user(act.queue_id)
119         buf = 'SET_QUEUE:' + str(queue_id)
120     elif action_type == ofproto_v1_3.OFPAT_GROUP:
121         group_id = UTIL.ofp_group_to_user(act.group_id)
122         buf = 'GROUP:' + str(group_id)
123     elif action_type == ofproto_v1_3.OFPAT_SET_NW_TTL:
124         buf = 'SET_NW_TTL:' + str(act.nw_ttl)
125     elif action_type == ofproto_v1_3.OFPAT_DEC_NW_TTL:
126         buf = 'DEC_NW_TTL'
127     elif action_type == ofproto_v1_3.OFPAT_SET_FIELD:
128         buf = 'SET_FIELD: {%s:%s}' % (act.key, act.value)
129     elif action_type == ofproto_v1_3.OFPAT_PUSH_PBB:
130         buf = 'PUSH_PBB:' + str(act.ethertype)
131     elif action_type == ofproto_v1_3.OFPAT_POP_PBB:
132         buf = 'POP_PBB'
133     elif action_type == ofproto_v1_3.OFPAT_EXPERIMENTER:
134         if act.experimenter == ofproto_common.NX_EXPERIMENTER_ID:
135             try:
136                 return ofctl_nicira_ext.action_to_str(act, action_to_str)
137             except Exception:
138                 LOG.debug('Error parsing NX_ACTION(%s)',
139                           act.__class__.__name__, exc_info=True)
140
141         data_str = base64.b64encode(act.data)
142         buf = 'EXPERIMENTER: {experimenter:%s, data:%s}' % \
143             (act.experimenter, data_str.decode('utf-8'))
144     else:
145         buf = 'UNKNOWN'
146     return buf
147
148
149 def actions_to_str(instructions):
150     actions = []
151
152     for instruction in instructions:
153         if isinstance(instruction,
154                       ofproto_v1_3_parser.OFPInstructionActions):
155             if instruction.type == ofproto_v1_3.OFPIT_APPLY_ACTIONS:
156                 for a in instruction.actions:
157                     actions.append(action_to_str(a))
158             elif instruction.type == ofproto_v1_3.OFPIT_WRITE_ACTIONS:
159                 write_actions = []
160                 for a in instruction.actions:
161                     write_actions.append(action_to_str(a))
162                 if write_actions:
163                     actions.append({'WRITE_ACTIONS': write_actions})
164             elif instruction.type == ofproto_v1_3.OFPIT_CLEAR_ACTIONS:
165                 actions.append('CLEAR_ACTIONS')
166             else:
167                 actions.append('UNKNOWN')
168         elif isinstance(instruction,
169                         ofproto_v1_3_parser.OFPInstructionGotoTable):
170             table_id = UTIL.ofp_table_to_user(instruction.table_id)
171             buf = 'GOTO_TABLE:' + str(table_id)
172             actions.append(buf)
173
174         elif isinstance(instruction,
175                         ofproto_v1_3_parser.OFPInstructionWriteMetadata):
176             buf = ('WRITE_METADATA:0x%x/0x%x' % (instruction.metadata,
177                                                  instruction.metadata_mask)
178                    if instruction.metadata_mask
179                    else 'WRITE_METADATA:0x%x' % instruction.metadata)
180             actions.append(buf)
181
182         elif isinstance(instruction,
183                         ofproto_v1_3_parser.OFPInstructionMeter):
184             meter_id = UTIL.ofp_meter_to_user(instruction.meter_id)
185             buf = 'METER:' + str(meter_id)
186             actions.append(buf)
187
188         else:
189             continue
190
191     return actions
192
193
194 def to_match(dp, attrs):
195     convert = {'in_port': UTIL.ofp_port_from_user,
196                'in_phy_port': str_to_int,
197                'metadata': ofctl_utils.to_match_masked_int,
198                'dl_dst': ofctl_utils.to_match_eth,
199                'dl_src': ofctl_utils.to_match_eth,
200                'eth_dst': ofctl_utils.to_match_eth,
201                'eth_src': ofctl_utils.to_match_eth,
202                'dl_type': str_to_int,
203                'eth_type': str_to_int,
204                'dl_vlan': to_match_vid,
205                'vlan_vid': to_match_vid,
206                'vlan_pcp': str_to_int,
207                'ip_dscp': str_to_int,
208                'ip_ecn': str_to_int,
209                'nw_proto': str_to_int,
210                'ip_proto': str_to_int,
211                'nw_src': ofctl_utils.to_match_ip,
212                'nw_dst': ofctl_utils.to_match_ip,
213                'ipv4_src': ofctl_utils.to_match_ip,
214                'ipv4_dst': ofctl_utils.to_match_ip,
215                'tp_src': str_to_int,
216                'tp_dst': str_to_int,
217                'tcp_src': str_to_int,
218                'tcp_dst': str_to_int,
219                'udp_src': str_to_int,
220                'udp_dst': str_to_int,
221                'sctp_src': str_to_int,
222                'sctp_dst': str_to_int,
223                'icmpv4_type': str_to_int,
224                'icmpv4_code': str_to_int,
225                'arp_op': str_to_int,
226                'arp_spa': ofctl_utils.to_match_ip,
227                'arp_tpa': ofctl_utils.to_match_ip,
228                'arp_sha': ofctl_utils.to_match_eth,
229                'arp_tha': ofctl_utils.to_match_eth,
230                'ipv6_src': ofctl_utils.to_match_ip,
231                'ipv6_dst': ofctl_utils.to_match_ip,
232                'ipv6_flabel': str_to_int,
233                'icmpv6_type': str_to_int,
234                'icmpv6_code': str_to_int,
235                'ipv6_nd_target': ofctl_utils.to_match_ip,
236                'ipv6_nd_sll': ofctl_utils.to_match_eth,
237                'ipv6_nd_tll': ofctl_utils.to_match_eth,
238                'mpls_label': str_to_int,
239                'mpls_tc': str_to_int,
240                'mpls_bos': str_to_int,
241                'pbb_isid': ofctl_utils.to_match_masked_int,
242                'tunnel_id': ofctl_utils.to_match_masked_int,
243                'ipv6_exthdr': ofctl_utils.to_match_masked_int}
244
245     keys = {'dl_dst': 'eth_dst',
246             'dl_src': 'eth_src',
247             'dl_type': 'eth_type',
248             'dl_vlan': 'vlan_vid',
249             'nw_src': 'ipv4_src',
250             'nw_dst': 'ipv4_dst',
251             'nw_proto': 'ip_proto'}
252
253     if attrs.get('dl_type') == ether.ETH_TYPE_ARP or \
254             attrs.get('eth_type') == ether.ETH_TYPE_ARP:
255         if 'nw_src' in attrs and 'arp_spa' not in attrs:
256             attrs['arp_spa'] = attrs['nw_src']
257             del attrs['nw_src']
258         if 'nw_dst' in attrs and 'arp_tpa' not in attrs:
259             attrs['arp_tpa'] = attrs['nw_dst']
260             del attrs['nw_dst']
261
262     kwargs = {}
263     for key, value in attrs.items():
264         if key in keys:
265             # For old field name
266             key = keys[key]
267         if key in convert:
268             value = convert[key](value)
269             if key == 'tp_src' or key == 'tp_dst':
270                 # TCP/UDP port
271                 conv = {inet.IPPROTO_TCP: {'tp_src': 'tcp_src',
272                                            'tp_dst': 'tcp_dst'},
273                         inet.IPPROTO_UDP: {'tp_src': 'udp_src',
274                                            'tp_dst': 'udp_dst'}}
275                 ip_proto = attrs.get('nw_proto', attrs.get('ip_proto', 0))
276                 key = conv[ip_proto][key]
277                 kwargs[key] = value
278             else:
279                 # others
280                 kwargs[key] = value
281         else:
282             LOG.error('Unknown match field: %s', key)
283
284     return dp.ofproto_parser.OFPMatch(**kwargs)
285
286
287 def to_match_vid(value):
288     return ofctl_utils.to_match_vid(value, ofproto_v1_3.OFPVID_PRESENT)
289
290
291 def match_to_str(ofmatch):
292
293     keys = {'eth_src': 'dl_src',
294             'eth_dst': 'dl_dst',
295             'eth_type': 'dl_type',
296             'vlan_vid': 'dl_vlan',
297             'ipv4_src': 'nw_src',
298             'ipv4_dst': 'nw_dst',
299             'ip_proto': 'nw_proto',
300             'tcp_src': 'tp_src',
301             'tcp_dst': 'tp_dst',
302             'udp_src': 'tp_src',
303             'udp_dst': 'tp_dst'}
304
305     match = {}
306
307     ofmatch = ofmatch.to_jsondict()['OFPMatch']
308     ofmatch = ofmatch['oxm_fields']
309
310     for match_field in ofmatch:
311         key = match_field['OXMTlv']['field']
312         if key in keys:
313             key = keys[key]
314         mask = match_field['OXMTlv']['mask']
315         value = match_field['OXMTlv']['value']
316         if key == 'dl_vlan':
317             value = match_vid_to_str(value, mask)
318         elif key == 'in_port':
319             value = UTIL.ofp_port_to_user(value)
320         else:
321             if mask is not None:
322                 value = str(value) + '/' + str(mask)
323         match.setdefault(key, value)
324
325     return match
326
327
328 def match_vid_to_str(value, mask):
329     return ofctl_utils.match_vid_to_str(
330         value, mask, ofproto_v1_3.OFPVID_PRESENT)
331
332
333 def wrap_dpid_dict(dp, value, to_user=True):
334     if to_user:
335         return {str(dp.id): value}
336
337     return {dp.id: value}
338
339
340 def get_desc_stats(dp, waiters, to_user=True):
341     stats = dp.ofproto_parser.OFPDescStatsRequest(dp, 0)
342     msgs = []
343     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
344     s = {}
345
346     for msg in msgs:
347         stats = msg.body
348         s = stats.to_jsondict()[stats.__class__.__name__]
349
350     return wrap_dpid_dict(dp, s, to_user)
351
352
353 def get_queue_stats(dp, waiters, port=None, queue_id=None, to_user=True):
354     ofp = dp.ofproto
355
356     if port is None:
357         port = ofp.OFPP_ANY
358     else:
359         port = str_to_int(port)
360
361     if queue_id is None:
362         queue_id = ofp.OFPQ_ALL
363     else:
364         queue_id = str_to_int(queue_id)
365
366     stats = dp.ofproto_parser.OFPQueueStatsRequest(dp, 0, port,
367                                                    queue_id)
368     msgs = []
369     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
370
371     s = []
372     for msg in msgs:
373         stats = msg.body
374         for stat in stats:
375             s.append({'duration_nsec': stat.duration_nsec,
376                       'duration_sec': stat.duration_sec,
377                       'port_no': stat.port_no,
378                       'queue_id': stat.queue_id,
379                       'tx_bytes': stat.tx_bytes,
380                       'tx_errors': stat.tx_errors,
381                       'tx_packets': stat.tx_packets})
382
383     return wrap_dpid_dict(dp, s, to_user)
384
385
386 def get_queue_config(dp, waiters, port=None, to_user=True):
387     ofp = dp.ofproto
388     if port is None:
389         port = ofp.OFPP_ANY
390     else:
391         port = UTIL.ofp_port_from_user(str_to_int(port))
392     stats = dp.ofproto_parser.OFPQueueGetConfigRequest(dp, port)
393     msgs = []
394     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
395
396     prop_type = {dp.ofproto.OFPQT_MIN_RATE: 'MIN_RATE',
397                  dp.ofproto.OFPQT_MAX_RATE: 'MAX_RATE',
398                  dp.ofproto.OFPQT_EXPERIMENTER: 'EXPERIMENTER'}
399
400     configs = []
401     for config in msgs:
402         queue_list = []
403         for queue in config.queues:
404             prop_list = []
405             for prop in queue.properties:
406                 p = {'property': prop_type.get(prop.property, 'UNKNOWN')}
407                 if prop.property == dp.ofproto.OFPQT_MIN_RATE or \
408                    prop.property == dp.ofproto.OFPQT_MAX_RATE:
409                     p['rate'] = prop.rate
410                 elif prop.property == dp.ofproto.OFPQT_EXPERIMENTER:
411                     p['experimenter'] = prop.experimenter
412                     p['data'] = prop.data
413                 prop_list.append(p)
414
415             q = {'properties': prop_list}
416
417             if to_user:
418                 q['port'] = UTIL.ofp_port_to_user(queue.port)
419                 q['queue_id'] = UTIL.ofp_queue_to_user(queue.queue_id)
420
421             else:
422                 q['port'] = queue.port
423                 q['queue_id'] = queue.queue_id
424
425             queue_list.append(q)
426
427         c = {'queues': queue_list}
428
429         if to_user:
430             c['port'] = UTIL.ofp_port_to_user(config.port)
431
432         else:
433             c['port'] = config.port
434
435         configs.append(c)
436
437     return wrap_dpid_dict(dp, configs, to_user)
438
439
440 def get_flow_stats(dp, waiters, flow=None, to_user=True):
441     flow = flow if flow else {}
442     table_id = UTIL.ofp_table_from_user(
443         flow.get('table_id', dp.ofproto.OFPTT_ALL))
444     flags = str_to_int(flow.get('flags', 0))
445     out_port = UTIL.ofp_port_from_user(
446         flow.get('out_port', dp.ofproto.OFPP_ANY))
447     out_group = UTIL.ofp_group_from_user(
448         flow.get('out_group', dp.ofproto.OFPG_ANY))
449     cookie = str_to_int(flow.get('cookie', 0))
450     cookie_mask = str_to_int(flow.get('cookie_mask', 0))
451     match = to_match(dp, flow.get('match', {}))
452     # Note: OpenFlow does not allow to filter flow entries by priority,
453     # but for efficiency, ofctl provides the way to do it.
454     priority = str_to_int(flow.get('priority', -1))
455
456     stats = dp.ofproto_parser.OFPFlowStatsRequest(
457         dp, flags, table_id, out_port, out_group, cookie, cookie_mask,
458         match)
459
460     msgs = []
461     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
462
463     flows = []
464     for msg in msgs:
465         for stats in msg.body:
466             if 0 <= priority != stats.priority:
467                 continue
468
469             s = {'priority': stats.priority,
470                  'cookie': stats.cookie,
471                  'idle_timeout': stats.idle_timeout,
472                  'hard_timeout': stats.hard_timeout,
473                  'byte_count': stats.byte_count,
474                  'duration_sec': stats.duration_sec,
475                  'duration_nsec': stats.duration_nsec,
476                  'packet_count': stats.packet_count,
477                  'length': stats.length,
478                  'flags': stats.flags}
479
480             if to_user:
481                 s['actions'] = actions_to_str(stats.instructions)
482                 s['match'] = match_to_str(stats.match)
483                 s['table_id'] = UTIL.ofp_table_to_user(stats.table_id)
484
485             else:
486                 s['actions'] = stats.instructions
487                 s['instructions'] = stats.instructions
488                 s['match'] = stats.match
489                 s['table_id'] = stats.table_id
490
491             flows.append(s)
492
493     return wrap_dpid_dict(dp, flows, to_user)
494
495
496 def get_aggregate_flow_stats(dp, waiters, flow=None, to_user=True):
497     flow = flow if flow else {}
498     table_id = UTIL.ofp_table_from_user(
499         flow.get('table_id', dp.ofproto.OFPTT_ALL))
500     flags = str_to_int(flow.get('flags', 0))
501     out_port = UTIL.ofp_port_from_user(
502         flow.get('out_port', dp.ofproto.OFPP_ANY))
503     out_group = UTIL.ofp_group_from_user(
504         flow.get('out_group', dp.ofproto.OFPG_ANY))
505     cookie = str_to_int(flow.get('cookie', 0))
506     cookie_mask = str_to_int(flow.get('cookie_mask', 0))
507     match = to_match(dp, flow.get('match', {}))
508
509     stats = dp.ofproto_parser.OFPAggregateStatsRequest(
510         dp, flags, table_id, out_port, out_group, cookie, cookie_mask,
511         match)
512
513     msgs = []
514     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
515
516     flows = []
517     for msg in msgs:
518         stats = msg.body
519         s = {'packet_count': stats.packet_count,
520              'byte_count': stats.byte_count,
521              'flow_count': stats.flow_count}
522         flows.append(s)
523
524     return wrap_dpid_dict(dp, flows, to_user)
525
526
527 def get_table_stats(dp, waiters, to_user=True):
528     stats = dp.ofproto_parser.OFPTableStatsRequest(dp, 0)
529     msgs = []
530     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
531
532     tables = []
533     for msg in msgs:
534         stats = msg.body
535         for stat in stats:
536             s = {'active_count': stat.active_count,
537                  'lookup_count': stat.lookup_count,
538                  'matched_count': stat.matched_count}
539
540             if to_user:
541                 s['table_id'] = UTIL.ofp_table_to_user(stat.table_id)
542
543             else:
544                 s['table_id'] = stat.table_id
545
546             tables.append(s)
547
548     return wrap_dpid_dict(dp, tables, to_user)
549
550
551 def get_table_features(dp, waiters, to_user=True):
552     stats = dp.ofproto_parser.OFPTableFeaturesStatsRequest(dp, 0, [])
553     msgs = []
554     ofproto = dp.ofproto
555     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
556
557     prop_type = {ofproto.OFPTFPT_INSTRUCTIONS: 'INSTRUCTIONS',
558                  ofproto.OFPTFPT_INSTRUCTIONS_MISS: 'INSTRUCTIONS_MISS',
559                  ofproto.OFPTFPT_NEXT_TABLES: 'NEXT_TABLES',
560                  ofproto.OFPTFPT_NEXT_TABLES_MISS: 'NEXT_TABLES_MISS',
561                  ofproto.OFPTFPT_WRITE_ACTIONS: 'WRITE_ACTIONS',
562                  ofproto.OFPTFPT_WRITE_ACTIONS_MISS: 'WRITE_ACTIONS_MISS',
563                  ofproto.OFPTFPT_APPLY_ACTIONS: 'APPLY_ACTIONS',
564                  ofproto.OFPTFPT_APPLY_ACTIONS_MISS: 'APPLY_ACTIONS_MISS',
565                  ofproto.OFPTFPT_MATCH: 'MATCH',
566                  ofproto.OFPTFPT_WILDCARDS: 'WILDCARDS',
567                  ofproto.OFPTFPT_WRITE_SETFIELD: 'WRITE_SETFIELD',
568                  ofproto.OFPTFPT_WRITE_SETFIELD_MISS: 'WRITE_SETFIELD_MISS',
569                  ofproto.OFPTFPT_APPLY_SETFIELD: 'APPLY_SETFIELD',
570                  ofproto.OFPTFPT_APPLY_SETFIELD_MISS: 'APPLY_SETFIELD_MISS',
571                  ofproto.OFPTFPT_EXPERIMENTER: 'EXPERIMENTER',
572                  ofproto.OFPTFPT_EXPERIMENTER_MISS: 'EXPERIMENTER_MISS'}
573
574     if not to_user:
575         prop_type = dict((k, k) for k in prop_type.keys())
576
577     p_type_instructions = [ofproto.OFPTFPT_INSTRUCTIONS,
578                            ofproto.OFPTFPT_INSTRUCTIONS_MISS]
579
580     p_type_next_tables = [ofproto.OFPTFPT_NEXT_TABLES,
581                           ofproto.OFPTFPT_NEXT_TABLES_MISS]
582
583     p_type_actions = [ofproto.OFPTFPT_WRITE_ACTIONS,
584                       ofproto.OFPTFPT_WRITE_ACTIONS_MISS,
585                       ofproto.OFPTFPT_APPLY_ACTIONS,
586                       ofproto.OFPTFPT_APPLY_ACTIONS_MISS]
587
588     p_type_oxms = [ofproto.OFPTFPT_MATCH,
589                    ofproto.OFPTFPT_WILDCARDS,
590                    ofproto.OFPTFPT_WRITE_SETFIELD,
591                    ofproto.OFPTFPT_WRITE_SETFIELD_MISS,
592                    ofproto.OFPTFPT_APPLY_SETFIELD,
593                    ofproto.OFPTFPT_APPLY_SETFIELD_MISS]
594
595     p_type_experimenter = [ofproto.OFPTFPT_EXPERIMENTER,
596                            ofproto.OFPTFPT_EXPERIMENTER_MISS]
597
598     tables = []
599     for msg in msgs:
600         stats = msg.body
601         for stat in stats:
602             properties = []
603             for prop in stat.properties:
604                 p = {'type': prop_type.get(prop.type, 'UNKNOWN')}
605                 if prop.type in p_type_instructions:
606                     instruction_ids = []
607                     for i in prop.instruction_ids:
608                         inst = {'len': i.len,
609                                 'type': i.type}
610                         instruction_ids.append(inst)
611                     p['instruction_ids'] = instruction_ids
612                 elif prop.type in p_type_next_tables:
613                     table_ids = []
614                     for i in prop.table_ids:
615                         table_ids.append(i)
616                     p['table_ids'] = table_ids
617                 elif prop.type in p_type_actions:
618                     action_ids = []
619                     for i in prop.action_ids:
620                         act = {'len': i.len,
621                                'type': i.type}
622                         action_ids.append(act)
623                     p['action_ids'] = action_ids
624                 elif prop.type in p_type_oxms:
625                     oxm_ids = []
626                     for i in prop.oxm_ids:
627                         oxm = {'hasmask': i.hasmask,
628                                'length': i.length,
629                                'type': i.type}
630                         oxm_ids.append(oxm)
631                     p['oxm_ids'] = oxm_ids
632                 elif prop.type in p_type_experimenter:
633                     pass
634                 properties.append(p)
635             s = {
636                 'name': stat.name.decode('utf-8'),
637                 'metadata_match': stat.metadata_match,
638                 'metadata_write': stat.metadata_write,
639                 'config': stat.config,
640                 'max_entries': stat.max_entries,
641                 'properties': properties,
642             }
643
644             if to_user:
645                 s['table_id'] = UTIL.ofp_table_to_user(stat.table_id)
646
647             else:
648                 s['table_id'] = stat.table_id
649
650             tables.append(s)
651
652     return wrap_dpid_dict(dp, tables, to_user)
653
654
655 def get_port_stats(dp, waiters, port=None, to_user=True):
656     if port is None:
657         port = dp.ofproto.OFPP_ANY
658     else:
659         port = str_to_int(port)
660
661     stats = dp.ofproto_parser.OFPPortStatsRequest(
662         dp, 0, port)
663     msgs = []
664     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
665
666     ports = []
667     for msg in msgs:
668         for stats in msg.body:
669             s = {'rx_packets': stats.rx_packets,
670                  'tx_packets': stats.tx_packets,
671                  'rx_bytes': stats.rx_bytes,
672                  'tx_bytes': stats.tx_bytes,
673                  'rx_dropped': stats.rx_dropped,
674                  'tx_dropped': stats.tx_dropped,
675                  'rx_errors': stats.rx_errors,
676                  'tx_errors': stats.tx_errors,
677                  'rx_frame_err': stats.rx_frame_err,
678                  'rx_over_err': stats.rx_over_err,
679                  'rx_crc_err': stats.rx_crc_err,
680                  'collisions': stats.collisions,
681                  'duration_sec': stats.duration_sec,
682                  'duration_nsec': stats.duration_nsec}
683
684             if to_user:
685                 s['port_no'] = UTIL.ofp_port_to_user(stats.port_no)
686
687             else:
688                 s['port_no'] = stats.port_no
689
690             ports.append(s)
691
692     return wrap_dpid_dict(dp, ports, to_user)
693
694
695 def get_meter_stats(dp, waiters, meter_id=None, to_user=True):
696     if meter_id is None:
697         meter_id = dp.ofproto.OFPM_ALL
698     else:
699         meter_id = str_to_int(meter_id)
700
701     stats = dp.ofproto_parser.OFPMeterStatsRequest(
702         dp, 0, meter_id)
703     msgs = []
704     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
705
706     meters = []
707     for msg in msgs:
708         for stats in msg.body:
709             bands = []
710             for band in stats.band_stats:
711                 b = {'packet_band_count': band.packet_band_count,
712                      'byte_band_count': band.byte_band_count}
713                 bands.append(b)
714             s = {'len': stats.len,
715                  'flow_count': stats.flow_count,
716                  'packet_in_count': stats.packet_in_count,
717                  'byte_in_count': stats.byte_in_count,
718                  'duration_sec': stats.duration_sec,
719                  'duration_nsec': stats.duration_nsec,
720                  'band_stats': bands}
721
722             if to_user:
723                 s['meter_id'] = UTIL.ofp_meter_to_user(stats.meter_id)
724
725             else:
726                 s['meter_id'] = stats.meter_id
727
728             meters.append(s)
729
730     return wrap_dpid_dict(dp, meters, to_user)
731
732
733 def get_meter_features(dp, waiters, to_user=True):
734
735     ofp = dp.ofproto
736     type_convert = {ofp.OFPMBT_DROP: 'DROP',
737                     ofp.OFPMBT_DSCP_REMARK: 'DSCP_REMARK'}
738
739     capa_convert = {ofp.OFPMF_KBPS: 'KBPS',
740                     ofp.OFPMF_PKTPS: 'PKTPS',
741                     ofp.OFPMF_BURST: 'BURST',
742                     ofp.OFPMF_STATS: 'STATS'}
743
744     stats = dp.ofproto_parser.OFPMeterFeaturesStatsRequest(dp, 0)
745     msgs = []
746     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
747
748     features = []
749     for msg in msgs:
750         for feature in msg.body:
751             band_types = []
752             for k, v in type_convert.items():
753                 if (1 << k) & feature.band_types:
754
755                     if to_user:
756                         band_types.append(v)
757
758                     else:
759                         band_types.append(k)
760
761             capabilities = []
762             for k, v in sorted(capa_convert.items()):
763                 if k & feature.capabilities:
764
765                     if to_user:
766                         capabilities.append(v)
767
768                     else:
769                         capabilities.append(k)
770
771             f = {'max_meter': feature.max_meter,
772                  'band_types': band_types,
773                  'capabilities': capabilities,
774                  'max_bands': feature.max_bands,
775                  'max_color': feature.max_color}
776             features.append(f)
777
778     return wrap_dpid_dict(dp, features, to_user)
779
780
781 def get_meter_config(dp, waiters, meter_id=None, to_user=True):
782     flags = {dp.ofproto.OFPMF_KBPS: 'KBPS',
783              dp.ofproto.OFPMF_PKTPS: 'PKTPS',
784              dp.ofproto.OFPMF_BURST: 'BURST',
785              dp.ofproto.OFPMF_STATS: 'STATS'}
786
787     band_type = {dp.ofproto.OFPMBT_DROP: 'DROP',
788                  dp.ofproto.OFPMBT_DSCP_REMARK: 'DSCP_REMARK',
789                  dp.ofproto.OFPMBT_EXPERIMENTER: 'EXPERIMENTER'}
790
791     if meter_id is None:
792         meter_id = dp.ofproto.OFPM_ALL
793     else:
794         meter_id = str_to_int(meter_id)
795
796     stats = dp.ofproto_parser.OFPMeterConfigStatsRequest(
797         dp, 0, meter_id)
798     msgs = []
799     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
800
801     configs = []
802     for msg in msgs:
803         for config in msg.body:
804             bands = []
805             for band in config.bands:
806                 b = {'rate': band.rate,
807                      'burst_size': band.burst_size}
808
809                 if to_user:
810                     b['type'] = band_type.get(band.type, '')
811
812                 else:
813                     b['type'] = band.type
814
815                 if band.type == dp.ofproto.OFPMBT_DSCP_REMARK:
816                     b['prec_level'] = band.prec_level
817                 elif band.type == dp.ofproto.OFPMBT_EXPERIMENTER:
818                     b['experimenter'] = band.experimenter
819                 bands.append(b)
820             c_flags = []
821             for k, v in sorted(flags.items()):
822                 if k & config.flags:
823                     if to_user:
824                         c_flags.append(v)
825
826                     else:
827                         c_flags.append(k)
828
829             c = {'flags': c_flags,
830                  'bands': bands}
831
832             if to_user:
833                 c['meter_id'] = UTIL.ofp_meter_to_user(config.meter_id)
834
835             else:
836                 c['meter_id'] = config.meter_id
837
838             configs.append(c)
839
840     return wrap_dpid_dict(dp, configs, to_user)
841
842
843 def get_group_stats(dp, waiters, group_id=None, to_user=True):
844     if group_id is None:
845         group_id = dp.ofproto.OFPG_ALL
846     else:
847         group_id = str_to_int(group_id)
848
849     stats = dp.ofproto_parser.OFPGroupStatsRequest(
850         dp, 0, group_id)
851     msgs = []
852     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
853
854     groups = []
855     for msg in msgs:
856         for stats in msg.body:
857             bucket_stats = []
858             for bucket_stat in stats.bucket_stats:
859                 c = {'packet_count': bucket_stat.packet_count,
860                      'byte_count': bucket_stat.byte_count}
861                 bucket_stats.append(c)
862             g = {'length': stats.length,
863                  'ref_count': stats.ref_count,
864                  'packet_count': stats.packet_count,
865                  'byte_count': stats.byte_count,
866                  'duration_sec': stats.duration_sec,
867                  'duration_nsec': stats.duration_nsec,
868                  'bucket_stats': bucket_stats}
869
870             if to_user:
871                 g['group_id'] = UTIL.ofp_group_to_user(stats.group_id)
872
873             else:
874                 g['group_id'] = stats.group_id
875
876             groups.append(g)
877
878     return wrap_dpid_dict(dp, groups, to_user)
879
880
881 def get_group_features(dp, waiters, to_user=True):
882
883     ofp = dp.ofproto
884     type_convert = {ofp.OFPGT_ALL: 'ALL',
885                     ofp.OFPGT_SELECT: 'SELECT',
886                     ofp.OFPGT_INDIRECT: 'INDIRECT',
887                     ofp.OFPGT_FF: 'FF'}
888     cap_convert = {ofp.OFPGFC_SELECT_WEIGHT: 'SELECT_WEIGHT',
889                    ofp.OFPGFC_SELECT_LIVENESS: 'SELECT_LIVENESS',
890                    ofp.OFPGFC_CHAINING: 'CHAINING',
891                    ofp.OFPGFC_CHAINING_CHECKS: 'CHAINING_CHECKS'}
892     act_convert = {ofp.OFPAT_OUTPUT: 'OUTPUT',
893                    ofp.OFPAT_COPY_TTL_OUT: 'COPY_TTL_OUT',
894                    ofp.OFPAT_COPY_TTL_IN: 'COPY_TTL_IN',
895                    ofp.OFPAT_SET_MPLS_TTL: 'SET_MPLS_TTL',
896                    ofp.OFPAT_DEC_MPLS_TTL: 'DEC_MPLS_TTL',
897                    ofp.OFPAT_PUSH_VLAN: 'PUSH_VLAN',
898                    ofp.OFPAT_POP_VLAN: 'POP_VLAN',
899                    ofp.OFPAT_PUSH_MPLS: 'PUSH_MPLS',
900                    ofp.OFPAT_POP_MPLS: 'POP_MPLS',
901                    ofp.OFPAT_SET_QUEUE: 'SET_QUEUE',
902                    ofp.OFPAT_GROUP: 'GROUP',
903                    ofp.OFPAT_SET_NW_TTL: 'SET_NW_TTL',
904                    ofp.OFPAT_DEC_NW_TTL: 'DEC_NW_TTL',
905                    ofp.OFPAT_SET_FIELD: 'SET_FIELD',
906                    ofp.OFPAT_PUSH_PBB: 'PUSH_PBB',
907                    ofp.OFPAT_POP_PBB: 'POP_PBB'}
908
909     stats = dp.ofproto_parser.OFPGroupFeaturesStatsRequest(dp, 0)
910     msgs = []
911     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
912
913     features = []
914     for msg in msgs:
915         feature = msg.body
916         types = []
917         for k, v in type_convert.items():
918             if (1 << k) & feature.types:
919                 if to_user:
920                     types.append(v)
921
922                 else:
923                     types.append(k)
924
925         capabilities = []
926         for k, v in cap_convert.items():
927             if k & feature.capabilities:
928                 if to_user:
929                     capabilities.append(v)
930
931                 else:
932                     capabilities.append(k)
933
934         if to_user:
935             max_groups = []
936             for k, v in type_convert.items():
937                 max_groups.append({v: feature.max_groups[k]})
938
939         else:
940             max_groups = feature.max_groups
941
942         actions = []
943         for k1, v1 in type_convert.items():
944             acts = []
945             for k2, v2 in act_convert.items():
946                 if (1 << k2) & feature.actions[k1]:
947                     if to_user:
948                         acts.append(v2)
949
950                     else:
951                         acts.append(k2)
952
953             if to_user:
954                 actions.append({v1: acts})
955
956             else:
957                 actions.append({k1: acts})
958
959         f = {'types': types,
960              'capabilities': capabilities,
961              'max_groups': max_groups,
962              'actions': actions}
963         features.append(f)
964
965     return wrap_dpid_dict(dp, features, to_user)
966
967
968 def get_group_desc(dp, waiters, to_user=True):
969
970     type_convert = {dp.ofproto.OFPGT_ALL: 'ALL',
971                     dp.ofproto.OFPGT_SELECT: 'SELECT',
972                     dp.ofproto.OFPGT_INDIRECT: 'INDIRECT',
973                     dp.ofproto.OFPGT_FF: 'FF'}
974
975     stats = dp.ofproto_parser.OFPGroupDescStatsRequest(dp, 0)
976     msgs = []
977     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
978
979     descs = []
980     for msg in msgs:
981         for stats in msg.body:
982             buckets = []
983             for bucket in stats.buckets:
984                 actions = []
985                 for action in bucket.actions:
986                     if to_user:
987                         actions.append(action_to_str(action))
988
989                     else:
990                         actions.append(action)
991
992                 b = {'weight': bucket.weight,
993                      'watch_port': bucket.watch_port,
994                      'watch_group': bucket.watch_group,
995                      'actions': actions}
996                 buckets.append(b)
997
998             d = {'buckets': buckets}
999             if to_user:
1000                 d['group_id'] = UTIL.ofp_group_to_user(stats.group_id)
1001                 d['type'] = type_convert.get(stats.type)
1002
1003             else:
1004                 d['group_id'] = stats.group_id
1005                 d['type'] = stats.type
1006
1007             descs.append(d)
1008
1009     return wrap_dpid_dict(dp, descs, to_user)
1010
1011
1012 def get_port_desc(dp, waiters, to_user=True):
1013
1014     stats = dp.ofproto_parser.OFPPortDescStatsRequest(dp, 0)
1015     msgs = []
1016     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
1017
1018     descs = []
1019
1020     for msg in msgs:
1021         stats = msg.body
1022         for stat in stats:
1023             d = {'hw_addr': stat.hw_addr,
1024                  'name': stat.name.decode('utf-8', errors='replace'),
1025                  'config': stat.config,
1026                  'state': stat.state,
1027                  'curr': stat.curr,
1028                  'advertised': stat.advertised,
1029                  'supported': stat.supported,
1030                  'peer': stat.peer,
1031                  'curr_speed': stat.curr_speed,
1032                  'max_speed': stat.max_speed}
1033
1034             if to_user:
1035                 d['port_no'] = UTIL.ofp_port_to_user(stat.port_no)
1036
1037             else:
1038                 d['port_no'] = stat.port_no
1039
1040             descs.append(d)
1041
1042     return wrap_dpid_dict(dp, descs, to_user)
1043
1044
1045 def get_role(dp, waiters, to_user=True):
1046     return ofctl_utils.get_role(dp, waiters, to_user)
1047
1048
1049 def mod_flow_entry(dp, flow, cmd):
1050     cookie = str_to_int(flow.get('cookie', 0))
1051     cookie_mask = str_to_int(flow.get('cookie_mask', 0))
1052     table_id = UTIL.ofp_table_from_user(flow.get('table_id', 0))
1053     idle_timeout = str_to_int(flow.get('idle_timeout', 0))
1054     hard_timeout = str_to_int(flow.get('hard_timeout', 0))
1055     priority = str_to_int(flow.get('priority', 0))
1056     buffer_id = UTIL.ofp_buffer_from_user(
1057         flow.get('buffer_id', dp.ofproto.OFP_NO_BUFFER))
1058     out_port = UTIL.ofp_port_from_user(
1059         flow.get('out_port', dp.ofproto.OFPP_ANY))
1060     out_group = UTIL.ofp_group_from_user(
1061         flow.get('out_group', dp.ofproto.OFPG_ANY))
1062     flags = str_to_int(flow.get('flags', 0))
1063     match = to_match(dp, flow.get('match', {}))
1064     inst = to_actions(dp, flow.get('actions', []))
1065
1066     flow_mod = dp.ofproto_parser.OFPFlowMod(
1067         dp, cookie, cookie_mask, table_id, cmd, idle_timeout,
1068         hard_timeout, priority, buffer_id, out_port, out_group,
1069         flags, match, inst)
1070
1071     ofctl_utils.send_msg(dp, flow_mod, LOG)
1072
1073
1074 def mod_meter_entry(dp, meter, cmd):
1075
1076     flags_convert = {'KBPS': dp.ofproto.OFPMF_KBPS,
1077                      'PKTPS': dp.ofproto.OFPMF_PKTPS,
1078                      'BURST': dp.ofproto.OFPMF_BURST,
1079                      'STATS': dp.ofproto.OFPMF_STATS}
1080
1081     flags = 0
1082     if 'flags' in meter:
1083         meter_flags = meter['flags']
1084         if not isinstance(meter_flags, list):
1085             meter_flags = [meter_flags]
1086         for flag in meter_flags:
1087             if flag not in flags_convert:
1088                 LOG.error('Unknown meter flag: %s', flag)
1089                 continue
1090             flags |= flags_convert.get(flag)
1091
1092     meter_id = UTIL.ofp_meter_from_user(meter.get('meter_id', 0))
1093
1094     bands = []
1095     for band in meter.get('bands', []):
1096         band_type = band.get('type')
1097         rate = str_to_int(band.get('rate', 0))
1098         burst_size = str_to_int(band.get('burst_size', 0))
1099         if band_type == 'DROP':
1100             bands.append(
1101                 dp.ofproto_parser.OFPMeterBandDrop(rate, burst_size))
1102         elif band_type == 'DSCP_REMARK':
1103             prec_level = str_to_int(band.get('prec_level', 0))
1104             bands.append(
1105                 dp.ofproto_parser.OFPMeterBandDscpRemark(
1106                     rate, burst_size, prec_level))
1107         elif band_type == 'EXPERIMENTER':
1108             experimenter = str_to_int(band.get('experimenter', 0))
1109             bands.append(
1110                 dp.ofproto_parser.OFPMeterBandExperimenter(
1111                     rate, burst_size, experimenter))
1112         else:
1113             LOG.error('Unknown band type: %s', band_type)
1114
1115     meter_mod = dp.ofproto_parser.OFPMeterMod(
1116         dp, cmd, flags, meter_id, bands)
1117
1118     ofctl_utils.send_msg(dp, meter_mod, LOG)
1119
1120
1121 def mod_group_entry(dp, group, cmd):
1122
1123     type_convert = {'ALL': dp.ofproto.OFPGT_ALL,
1124                     'SELECT': dp.ofproto.OFPGT_SELECT,
1125                     'INDIRECT': dp.ofproto.OFPGT_INDIRECT,
1126                     'FF': dp.ofproto.OFPGT_FF}
1127
1128     type_ = type_convert.get(group.get('type', 'ALL'))
1129     if type_ is None:
1130         LOG.error('Unknown group type: %s', group.get('type'))
1131
1132     group_id = UTIL.ofp_group_from_user(group.get('group_id', 0))
1133
1134     buckets = []
1135     for bucket in group.get('buckets', []):
1136         weight = str_to_int(bucket.get('weight', 0))
1137         watch_port = str_to_int(
1138             bucket.get('watch_port', dp.ofproto.OFPP_ANY))
1139         watch_group = str_to_int(
1140             bucket.get('watch_group', dp.ofproto.OFPG_ANY))
1141         actions = []
1142         for dic in bucket.get('actions', []):
1143             action = to_action(dp, dic)
1144             if action is not None:
1145                 actions.append(action)
1146         buckets.append(dp.ofproto_parser.OFPBucket(
1147             weight, watch_port, watch_group, actions))
1148
1149     group_mod = dp.ofproto_parser.OFPGroupMod(
1150         dp, cmd, type_, group_id, buckets)
1151
1152     ofctl_utils.send_msg(dp, group_mod, LOG)
1153
1154
1155 def mod_port_behavior(dp, port_config):
1156     port_no = UTIL.ofp_port_from_user(port_config.get('port_no', 0))
1157     hw_addr = str(port_config.get('hw_addr'))
1158     config = str_to_int(port_config.get('config', 0))
1159     mask = str_to_int(port_config.get('mask', 0))
1160     advertise = str_to_int(port_config.get('advertise'))
1161
1162     port_mod = dp.ofproto_parser.OFPPortMod(
1163         dp, port_no, hw_addr, config, mask, advertise)
1164
1165     ofctl_utils.send_msg(dp, port_mod, LOG)
1166
1167
1168 def set_role(dp, role):
1169     r = UTIL.ofp_role_from_user(role.get('role', dp.ofproto.OFPCR_ROLE_EQUAL))
1170     role_request = dp.ofproto_parser.OFPRoleRequest(dp, r, 0)
1171     ofctl_utils.send_msg(dp, role_request, LOG)
1172
1173
1174 # NOTE(jkoelker) Alias common funcitons
1175 send_experimenter = ofctl_utils.send_experimenter