Se reinstalo ryu para configurar STP y que el restAPI no sea publico(127.0.0.1)
[vsorcdistro/.git] / ryu / ryu / lib / ofctl_v1_2.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 logging
17 import netaddr
18
19 from ryu.ofproto import ether
20 from ryu.ofproto import inet
21 from ryu.ofproto import ofproto_v1_2
22 from ryu.ofproto import ofproto_v1_2_parser
23 from ryu.lib import ofctl_utils
24
25
26 LOG = logging.getLogger('ryu.lib.ofctl_v1_2')
27
28 DEFAULT_TIMEOUT = 1.0
29
30 UTIL = ofctl_utils.OFCtlUtil(ofproto_v1_2)
31 str_to_int = ofctl_utils.str_to_int
32
33
34 def to_action(dp, dic):
35     ofp = dp.ofproto
36     parser = dp.ofproto_parser
37     action_type = dic.get('type')
38     return ofctl_utils.to_action(dic, ofp, parser, action_type, UTIL)
39
40
41 def to_actions(dp, acts):
42     inst = []
43     actions = []
44     ofp = dp.ofproto
45     parser = dp.ofproto_parser
46
47     for a in acts:
48         action = to_action(dp, a)
49         if action is not None:
50             actions.append(action)
51         else:
52             action_type = a.get('type')
53             if action_type == 'WRITE_ACTIONS':
54                 write_actions = []
55                 write_acts = a.get('actions')
56                 for act in write_acts:
57                     action = to_action(dp, act)
58                     if action is not None:
59                         write_actions.append(action)
60                     else:
61                         LOG.error('Unknown action type: %s', action_type)
62                 if write_actions:
63                     inst.append(
64                         parser.OFPInstructionActions(ofp.OFPIT_WRITE_ACTIONS,
65                                                      write_actions))
66             elif action_type == 'CLEAR_ACTIONS':
67                 inst.append(
68                     parser.OFPInstructionActions(ofp.OFPIT_CLEAR_ACTIONS, []))
69             elif action_type == 'GOTO_TABLE':
70                 table_id = UTIL.ofp_table_from_user(a.get('table_id'))
71                 inst.append(parser.OFPInstructionGotoTable(table_id))
72             elif action_type == 'WRITE_METADATA':
73                 metadata = str_to_int(a.get('metadata'))
74                 metadata_mask = (str_to_int(a['metadata_mask'])
75                                  if 'metadata_mask' in a
76                                  else parser.UINT64_MAX)
77                 inst.append(
78                     parser.OFPInstructionWriteMetadata(
79                         metadata, metadata_mask))
80             else:
81                 LOG.error('Unknown action type: %s', action_type)
82
83     if actions:
84         inst.append(parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
85                                                  actions))
86     return inst
87
88
89 def action_to_str(act):
90     action_type = act.cls_action_type
91
92     if action_type == ofproto_v1_2.OFPAT_OUTPUT:
93         port = UTIL.ofp_port_to_user(act.port)
94         buf = 'OUTPUT:' + str(port)
95     elif action_type == ofproto_v1_2.OFPAT_COPY_TTL_OUT:
96         buf = 'COPY_TTL_OUT'
97     elif action_type == ofproto_v1_2.OFPAT_COPY_TTL_IN:
98         buf = 'COPY_TTL_IN'
99     elif action_type == ofproto_v1_2.OFPAT_SET_MPLS_TTL:
100         buf = 'SET_MPLS_TTL:' + str(act.mpls_ttl)
101     elif action_type == ofproto_v1_2.OFPAT_DEC_MPLS_TTL:
102         buf = 'DEC_MPLS_TTL'
103     elif action_type == ofproto_v1_2.OFPAT_PUSH_VLAN:
104         buf = 'PUSH_VLAN:' + str(act.ethertype)
105     elif action_type == ofproto_v1_2.OFPAT_POP_VLAN:
106         buf = 'POP_VLAN'
107     elif action_type == ofproto_v1_2.OFPAT_PUSH_MPLS:
108         buf = 'PUSH_MPLS:' + str(act.ethertype)
109     elif action_type == ofproto_v1_2.OFPAT_POP_MPLS:
110         buf = 'POP_MPLS:' + str(act.ethertype)
111     elif action_type == ofproto_v1_2.OFPAT_SET_QUEUE:
112         queue_id = UTIL.ofp_queue_to_user(act.queue_id)
113         buf = 'SET_QUEUE:' + str(queue_id)
114     elif action_type == ofproto_v1_2.OFPAT_GROUP:
115         group_id = UTIL.ofp_group_to_user(act.group_id)
116         buf = 'GROUP:' + str(group_id)
117     elif action_type == ofproto_v1_2.OFPAT_SET_NW_TTL:
118         buf = 'SET_NW_TTL:' + str(act.nw_ttl)
119     elif action_type == ofproto_v1_2.OFPAT_DEC_NW_TTL:
120         buf = 'DEC_NW_TTL'
121     elif action_type == ofproto_v1_2.OFPAT_SET_FIELD:
122         buf = 'SET_FIELD: {%s:%s}' % (act.key, act.value)
123     else:
124         buf = 'UNKNOWN'
125     return buf
126
127
128 def actions_to_str(instructions):
129     actions = []
130
131     for instruction in instructions:
132         if isinstance(instruction,
133                       ofproto_v1_2_parser.OFPInstructionActions):
134             if instruction.type == ofproto_v1_2.OFPIT_APPLY_ACTIONS:
135                 for a in instruction.actions:
136                     actions.append(action_to_str(a))
137             elif instruction.type == ofproto_v1_2.OFPIT_WRITE_ACTIONS:
138                 write_actions = []
139                 for a in instruction.actions:
140                     write_actions.append(action_to_str(a))
141                 if write_actions:
142                     actions.append({'WRITE_ACTIONS': write_actions})
143             elif instruction.type == ofproto_v1_2.OFPIT_CLEAR_ACTIONS:
144                 actions.append('CLEAR_ACTIONS')
145             else:
146                 actions.append('UNKNOWN')
147         elif isinstance(instruction,
148                         ofproto_v1_2_parser.OFPInstructionGotoTable):
149             table_id = UTIL.ofp_table_to_user(instruction.table_id)
150             buf = 'GOTO_TABLE:' + str(table_id)
151             actions.append(buf)
152
153         elif isinstance(instruction,
154                         ofproto_v1_2_parser.OFPInstructionWriteMetadata):
155             buf = ('WRITE_METADATA:0x%x/0x%x' % (instruction.metadata,
156                                                  instruction.metadata_mask)
157                    if instruction.metadata_mask
158                    else 'WRITE_METADATA:0x%x' % instruction.metadata)
159             actions.append(buf)
160
161         else:
162             continue
163
164     return actions
165
166
167 def to_match(dp, attrs):
168     convert = {'in_port': UTIL.ofp_port_from_user,
169                'in_phy_port': str_to_int,
170                'metadata': ofctl_utils.to_match_masked_int,
171                'dl_dst': ofctl_utils.to_match_eth,
172                'dl_src': ofctl_utils.to_match_eth,
173                'eth_dst': ofctl_utils.to_match_eth,
174                'eth_src': ofctl_utils.to_match_eth,
175                'dl_type': str_to_int,
176                'eth_type': str_to_int,
177                'dl_vlan': to_match_vid,
178                'vlan_vid': to_match_vid,
179                'vlan_pcp': str_to_int,
180                'ip_dscp': str_to_int,
181                'ip_ecn': str_to_int,
182                'nw_proto': str_to_int,
183                'ip_proto': str_to_int,
184                'nw_src': ofctl_utils.to_match_ip,
185                'nw_dst': ofctl_utils.to_match_ip,
186                'ipv4_src': ofctl_utils.to_match_ip,
187                'ipv4_dst': ofctl_utils.to_match_ip,
188                'tp_src': str_to_int,
189                'tp_dst': str_to_int,
190                'tcp_src': str_to_int,
191                'tcp_dst': str_to_int,
192                'udp_src': str_to_int,
193                'udp_dst': str_to_int,
194                'sctp_src': str_to_int,
195                'sctp_dst': str_to_int,
196                'icmpv4_type': str_to_int,
197                'icmpv4_code': str_to_int,
198                'arp_op': str_to_int,
199                'arp_spa': ofctl_utils.to_match_ip,
200                'arp_tpa': ofctl_utils.to_match_ip,
201                'arp_sha': ofctl_utils.to_match_eth,
202                'arp_tha': ofctl_utils.to_match_eth,
203                'ipv6_src': ofctl_utils.to_match_ip,
204                'ipv6_dst': ofctl_utils.to_match_ip,
205                'ipv6_flabel': str_to_int,
206                'icmpv6_type': str_to_int,
207                'icmpv6_code': str_to_int,
208                'ipv6_nd_target': ofctl_utils.to_match_ip,
209                'ipv6_nd_sll': ofctl_utils.to_match_eth,
210                'ipv6_nd_tll': ofctl_utils.to_match_eth,
211                'mpls_label': str_to_int,
212                'mpls_tc': str_to_int}
213
214     keys = {'dl_dst': 'eth_dst',
215             'dl_src': 'eth_src',
216             'dl_type': 'eth_type',
217             'dl_vlan': 'vlan_vid',
218             'nw_src': 'ipv4_src',
219             'nw_dst': 'ipv4_dst',
220             'nw_proto': 'ip_proto'}
221
222     if attrs.get('dl_type') == ether.ETH_TYPE_ARP or \
223             attrs.get('eth_type') == ether.ETH_TYPE_ARP:
224         if 'nw_src' in attrs and 'arp_spa' not in attrs:
225             attrs['arp_spa'] = attrs['nw_src']
226             del attrs['nw_src']
227         if 'nw_dst' in attrs and 'arp_tpa' not in attrs:
228             attrs['arp_tpa'] = attrs['nw_dst']
229             del attrs['nw_dst']
230
231     kwargs = {}
232     for key, value in attrs.items():
233         if key in keys:
234             # For old field name
235             key = keys[key]
236         if key in convert:
237             value = convert[key](value)
238             if key == 'tp_src' or key == 'tp_dst':
239                 # TCP/UDP port
240                 conv = {inet.IPPROTO_TCP: {'tp_src': 'tcp_src',
241                                            'tp_dst': 'tcp_dst'},
242                         inet.IPPROTO_UDP: {'tp_src': 'udp_src',
243                                            'tp_dst': 'udp_dst'}}
244                 ip_proto = attrs.get('nw_proto', attrs.get('ip_proto', 0))
245                 key = conv[ip_proto][key]
246                 kwargs[key] = value
247             else:
248                 # others
249                 kwargs[key] = value
250         else:
251             LOG.error('Unknown match field: %s', key)
252
253     return dp.ofproto_parser.OFPMatch(**kwargs)
254
255
256 def to_match_vid(value):
257     return ofctl_utils.to_match_vid(value, ofproto_v1_2.OFPVID_PRESENT)
258
259
260 def match_to_str(ofmatch):
261
262     keys = {'eth_src': 'dl_src',
263             'eth_dst': 'dl_dst',
264             'eth_type': 'dl_type',
265             'vlan_vid': 'dl_vlan',
266             'ipv4_src': 'nw_src',
267             'ipv4_dst': 'nw_dst',
268             'ip_proto': 'nw_proto',
269             'tcp_src': 'tp_src',
270             'tcp_dst': 'tp_dst',
271             'udp_src': 'tp_src',
272             'udp_dst': 'tp_dst'}
273
274     match = {}
275
276     ofmatch = ofmatch.to_jsondict()['OFPMatch']
277     ofmatch = ofmatch['oxm_fields']
278     for match_field in ofmatch:
279         key = match_field['OXMTlv']['field']
280         if key in keys:
281             key = keys[key]
282         mask = match_field['OXMTlv']['mask']
283         value = match_field['OXMTlv']['value']
284         if key == 'dl_vlan':
285             value = match_vid_to_str(value, mask)
286         elif key == 'in_port':
287             value = UTIL.ofp_port_to_user(value)
288         else:
289             if mask is not None:
290                 value = str(value) + '/' + str(mask)
291         match.setdefault(key, value)
292
293     return match
294
295
296 def match_vid_to_str(value, mask):
297     return ofctl_utils.match_vid_to_str(
298         value, mask, ofproto_v1_2.OFPVID_PRESENT)
299
300
301 def get_desc_stats(dp, waiters):
302     stats = dp.ofproto_parser.OFPDescStatsRequest(dp)
303     msgs = []
304     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
305
306     s = {}
307     for msg in msgs:
308         stats = msg.body
309         s = stats.to_jsondict()[stats.__class__.__name__]
310
311     return {str(dp.id): s}
312
313
314 def get_queue_stats(dp, waiters, port=None, queue_id=None):
315     ofp = dp.ofproto
316
317     if port is None:
318         port = ofp.OFPP_ANY
319     else:
320         port = str_to_int(port)
321
322     if queue_id is None:
323         queue_id = ofp.OFPQ_ALL
324     else:
325         queue_id = str_to_int(queue_id)
326
327     stats = dp.ofproto_parser.OFPQueueStatsRequest(dp, port,
328                                                    queue_id, 0)
329     msgs = []
330     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
331
332     s = []
333     for msg in msgs:
334         stats = msg.body
335         for stat in stats:
336             s.append({'port_no': stat.port_no,
337                       'queue_id': stat.queue_id,
338                       'tx_bytes': stat.tx_bytes,
339                       'tx_errors': stat.tx_errors,
340                       'tx_packets': stat.tx_packets})
341
342     return {str(dp.id): s}
343
344
345 def get_queue_config(dp, waiters, port=None):
346     ofp = dp.ofproto
347     if port is None:
348         port = ofp.OFPP_ANY
349     else:
350         port = UTIL.ofp_port_from_user(str_to_int(port))
351     stats = dp.ofproto_parser.OFPQueueGetConfigRequest(dp, port)
352     msgs = []
353     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
354
355     prop_type = {
356         dp.ofproto.OFPQT_MIN_RATE: 'MIN_RATE',
357         dp.ofproto.OFPQT_MAX_RATE: 'MAX_RATE',
358         dp.ofproto.OFPQT_EXPERIMENTER: 'EXPERIMENTER',
359     }
360
361     configs = []
362     for config in msgs:
363         queue_list = []
364         for queue in config.queues:
365             prop_list = []
366             for prop in queue.properties:
367                 p = {'property': prop_type.get(prop.property, 'UNKNOWN')}
368                 if prop.property == dp.ofproto.OFPQT_MIN_RATE or \
369                    prop.property == dp.ofproto.OFPQT_MAX_RATE:
370                     p['rate'] = prop.rate
371                 elif prop.property == dp.ofproto.OFPQT_EXPERIMENTER:
372                     p['experimenter'] = prop.experimenter
373                     p['data'] = prop.data
374                 prop_list.append(p)
375             q = {'port': UTIL.ofp_port_to_user(queue.port),
376                  'properties': prop_list,
377                  'queue_id': UTIL.ofp_queue_to_user(queue.queue_id)}
378             queue_list.append(q)
379         c = {'port': UTIL.ofp_port_to_user(config.port),
380              'queues': queue_list}
381         configs.append(c)
382
383     return {str(dp.id): configs}
384
385
386 def get_flow_stats(dp, waiters, flow=None):
387     flow = flow if flow else {}
388     table_id = UTIL.ofp_table_from_user(
389         flow.get('table_id', dp.ofproto.OFPTT_ALL))
390     out_port = UTIL.ofp_port_from_user(
391         flow.get('out_port', dp.ofproto.OFPP_ANY))
392     out_group = UTIL.ofp_group_from_user(
393         flow.get('out_group', dp.ofproto.OFPG_ANY))
394     cookie = str_to_int(flow.get('cookie', 0))
395     cookie_mask = str_to_int(flow.get('cookie_mask', 0))
396     match = to_match(dp, flow.get('match', {}))
397     # Note: OpenFlow does not allow to filter flow entries by priority,
398     # but for efficiency, ofctl provides the way to do it.
399     priority = str_to_int(flow.get('priority', -1))
400
401     stats = dp.ofproto_parser.OFPFlowStatsRequest(
402         dp, table_id, out_port, out_group, cookie, cookie_mask, match)
403
404     msgs = []
405     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
406
407     flows = []
408     for msg in msgs:
409         for stats in msg.body:
410             if 0 <= priority != stats.priority:
411                 continue
412
413             actions = actions_to_str(stats.instructions)
414             match = match_to_str(stats.match)
415             s = {'priority': stats.priority,
416                  'cookie': stats.cookie,
417                  'idle_timeout': stats.idle_timeout,
418                  'hard_timeout': stats.hard_timeout,
419                  'actions': actions,
420                  'match': match,
421                  'byte_count': stats.byte_count,
422                  'duration_sec': stats.duration_sec,
423                  'duration_nsec': stats.duration_nsec,
424                  'packet_count': stats.packet_count,
425                  'table_id': UTIL.ofp_table_to_user(stats.table_id),
426                  'length': stats.length}
427             flows.append(s)
428
429     return {str(dp.id): flows}
430
431
432 def get_aggregate_flow_stats(dp, waiters, flow=None):
433     flow = flow if flow else {}
434     table_id = UTIL.ofp_table_from_user(
435         flow.get('table_id', dp.ofproto.OFPTT_ALL))
436     out_port = UTIL.ofp_port_from_user(
437         flow.get('out_port', dp.ofproto.OFPP_ANY))
438     out_group = UTIL.ofp_group_from_user(
439         flow.get('out_group', dp.ofproto.OFPG_ANY))
440     cookie = str_to_int(flow.get('cookie', 0))
441     cookie_mask = str_to_int(flow.get('cookie_mask', 0))
442     match = to_match(dp, flow.get('match', {}))
443
444     stats = dp.ofproto_parser.OFPAggregateStatsRequest(
445         dp, table_id, out_port, out_group, cookie, cookie_mask, match)
446
447     msgs = []
448     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
449
450     flows = []
451     for msg in msgs:
452         stats = msg.body
453         s = {'packet_count': stats.packet_count,
454              'byte_count': stats.byte_count,
455              'flow_count': stats.flow_count}
456         flows.append(s)
457
458     return {str(dp.id): flows}
459
460
461 def get_table_stats(dp, waiters):
462     stats = dp.ofproto_parser.OFPTableStatsRequest(dp)
463     ofp = dp.ofproto
464     msgs = []
465     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
466
467     oxm_type_convert = {ofp.OFPXMT_OFB_IN_PORT: 'IN_PORT',
468                         ofp.OFPXMT_OFB_IN_PHY_PORT: 'IN_PHY_PORT',
469                         ofp.OFPXMT_OFB_METADATA: 'METADATA',
470                         ofp.OFPXMT_OFB_ETH_DST: 'ETH_DST',
471                         ofp.OFPXMT_OFB_ETH_SRC: 'ETH_SRC',
472                         ofp.OFPXMT_OFB_ETH_TYPE: 'ETH_TYPE',
473                         ofp.OFPXMT_OFB_VLAN_VID: 'VLAN_VID',
474                         ofp.OFPXMT_OFB_VLAN_PCP: 'VLAN_PCP',
475                         ofp.OFPXMT_OFB_IP_DSCP: 'IP_DSCP',
476                         ofp.OFPXMT_OFB_IP_ECN: 'IP_ECN',
477                         ofp.OFPXMT_OFB_IP_PROTO: 'IP_PROTO',
478                         ofp.OFPXMT_OFB_IPV4_SRC: 'IPV4_SRC',
479                         ofp.OFPXMT_OFB_IPV4_DST: 'IPV4_DST',
480                         ofp.OFPXMT_OFB_TCP_SRC: 'TCP_SRC',
481                         ofp.OFPXMT_OFB_TCP_DST: 'TCP_DST',
482                         ofp.OFPXMT_OFB_UDP_SRC: 'UDP_SRC',
483                         ofp.OFPXMT_OFB_UDP_DST: 'UDP_DST',
484                         ofp.OFPXMT_OFB_SCTP_SRC: 'SCTP_SRC',
485                         ofp.OFPXMT_OFB_SCTP_DST: 'SCTP_DST',
486                         ofp.OFPXMT_OFB_ICMPV4_TYPE: 'ICMPV4_TYPE',
487                         ofp.OFPXMT_OFB_ICMPV4_CODE: 'ICMPV4_CODE',
488                         ofp.OFPXMT_OFB_ARP_OP: 'ARP_OP',
489                         ofp.OFPXMT_OFB_ARP_SPA: 'ARP_SPA',
490                         ofp.OFPXMT_OFB_ARP_TPA: 'ARP_TPA',
491                         ofp.OFPXMT_OFB_ARP_SHA: 'ARP_SHA',
492                         ofp.OFPXMT_OFB_ARP_THA: 'ARP_THA',
493                         ofp.OFPXMT_OFB_IPV6_SRC: 'IPV6_SRC',
494                         ofp.OFPXMT_OFB_IPV6_DST: 'IPV6_DST',
495                         ofp.OFPXMT_OFB_IPV6_FLABEL: 'IPV6_FLABEL',
496                         ofp.OFPXMT_OFB_ICMPV6_TYPE: 'ICMPV6_TYPE',
497                         ofp.OFPXMT_OFB_ICMPV6_CODE: 'ICMPV6_CODE',
498                         ofp.OFPXMT_OFB_IPV6_ND_TARGET: 'IPV6_ND_TARGET',
499                         ofp.OFPXMT_OFB_IPV6_ND_SLL: 'IPV6_ND_SLL',
500                         ofp.OFPXMT_OFB_IPV6_ND_TLL: 'IPV6_ND_TLL',
501                         ofp.OFPXMT_OFB_MPLS_LABEL: 'MPLS_LABEL',
502                         ofp.OFPXMT_OFB_MPLS_TC: 'MPLS_TC'}
503
504     act_convert = {ofp.OFPAT_OUTPUT: 'OUTPUT',
505                    ofp.OFPAT_COPY_TTL_OUT: 'COPY_TTL_OUT',
506                    ofp.OFPAT_COPY_TTL_IN: 'COPY_TTL_IN',
507                    ofp.OFPAT_SET_MPLS_TTL: 'SET_MPLS_TTL',
508                    ofp.OFPAT_DEC_MPLS_TTL: 'DEC_MPLS_TTL',
509                    ofp.OFPAT_PUSH_VLAN: 'PUSH_VLAN',
510                    ofp.OFPAT_POP_VLAN: 'POP_VLAN',
511                    ofp.OFPAT_PUSH_MPLS: 'PUSH_MPLS',
512                    ofp.OFPAT_POP_MPLS: 'POP_MPLS',
513                    ofp.OFPAT_SET_QUEUE: 'SET_QUEUE',
514                    ofp.OFPAT_GROUP: 'GROUP',
515                    ofp.OFPAT_SET_NW_TTL: 'SET_NW_TTL',
516                    ofp.OFPAT_DEC_NW_TTL: 'DEC_NW_TTL',
517                    ofp.OFPAT_SET_FIELD: 'SET_FIELD'}
518
519     inst_convert = {ofp.OFPIT_GOTO_TABLE: 'GOTO_TABLE',
520                     ofp.OFPIT_WRITE_METADATA: 'WRITE_METADATA',
521                     ofp.OFPIT_WRITE_ACTIONS: 'WRITE_ACTIONS',
522                     ofp.OFPIT_APPLY_ACTIONS: 'APPLY_ACTIONS',
523                     ofp.OFPIT_CLEAR_ACTIONS: 'CLEAR_ACTIONS',
524                     ofp.OFPIT_EXPERIMENTER: 'EXPERIMENTER'}
525
526     table_conf_convert = {
527         ofp.OFPTC_TABLE_MISS_CONTROLLER: 'TABLE_MISS_CONTROLLER',
528         ofp.OFPTC_TABLE_MISS_CONTINUE: 'TABLE_MISS_CONTINUE',
529         ofp.OFPTC_TABLE_MISS_DROP: 'TABLE_MISS_DROP',
530         ofp.OFPTC_TABLE_MISS_MASK: 'TABLE_MISS_MASK'}
531
532     tables = []
533     for msg in msgs:
534         stats = msg.body
535         for stat in stats:
536             match = []
537             wildcards = []
538             write_setfields = []
539             apply_setfields = []
540             for k, v in oxm_type_convert.items():
541                 if (1 << k) & stat.match:
542                     match.append(v)
543                 if (1 << k) & stat.wildcards:
544                     wildcards.append(v)
545                 if (1 << k) & stat.write_setfields:
546                     write_setfields.append(v)
547                 if (1 << k) & stat.apply_setfields:
548                     apply_setfields.append(v)
549             write_actions = []
550             apply_actions = []
551             for k, v in act_convert.items():
552                 if (1 << k) & stat.write_actions:
553                     write_actions.append(v)
554                 if (1 << k) & stat.apply_actions:
555                     apply_actions.append(v)
556             instructions = []
557             for k, v in inst_convert.items():
558                 if (1 << k) & stat.instructions:
559                     instructions.append(v)
560             config = []
561             for k, v in table_conf_convert.items():
562                 if (1 << k) & stat.config:
563                     config.append(v)
564             s = {'table_id': UTIL.ofp_table_to_user(stat.table_id),
565                  'name': stat.name.decode('utf-8'),
566                  'match': match,
567                  'wildcards': wildcards,
568                  'write_actions': write_actions,
569                  'apply_actions': apply_actions,
570                  'write_setfields': write_setfields,
571                  'apply_setfields': apply_setfields,
572                  'metadata_match': stat.metadata_match,
573                  'metadata_write': stat.metadata_write,
574                  'instructions': instructions,
575                  'config': config,
576                  'max_entries': stat.max_entries,
577                  'active_count': stat.active_count,
578                  'lookup_count': stat.lookup_count,
579                  'matched_count': stat.matched_count}
580             tables.append(s)
581
582     return {str(dp.id): tables}
583
584
585 def get_port_stats(dp, waiters, port=None):
586     if port is None:
587         port = dp.ofproto.OFPP_ANY
588     else:
589         port = str_to_int(port)
590
591     stats = dp.ofproto_parser.OFPPortStatsRequest(
592         dp, port, 0)
593     msgs = []
594     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
595
596     ports = []
597     for msg in msgs:
598         for stats in msg.body:
599             s = {'port_no': UTIL.ofp_port_to_user(stats.port_no),
600                  'rx_packets': stats.rx_packets,
601                  'tx_packets': stats.tx_packets,
602                  'rx_bytes': stats.rx_bytes,
603                  'tx_bytes': stats.tx_bytes,
604                  'rx_dropped': stats.rx_dropped,
605                  'tx_dropped': stats.tx_dropped,
606                  'rx_errors': stats.rx_errors,
607                  'tx_errors': stats.tx_errors,
608                  'rx_frame_err': stats.rx_frame_err,
609                  'rx_over_err': stats.rx_over_err,
610                  'rx_crc_err': stats.rx_crc_err,
611                  'collisions': stats.collisions}
612             ports.append(s)
613
614     return {str(dp.id): ports}
615
616
617 def get_group_stats(dp, waiters, group_id=None):
618     if group_id is None:
619         group_id = dp.ofproto.OFPG_ALL
620     else:
621         group_id = str_to_int(group_id)
622
623     stats = dp.ofproto_parser.OFPGroupStatsRequest(
624         dp, group_id, 0)
625     msgs = []
626     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
627
628     groups = []
629     for msg in msgs:
630         for stats in msg.body:
631             bucket_counters = []
632             for bucket_counter in stats.bucket_counters:
633                 c = {'packet_count': bucket_counter.packet_count,
634                      'byte_count': bucket_counter.byte_count}
635                 bucket_counters.append(c)
636             g = {'length': stats.length,
637                  'group_id': UTIL.ofp_group_to_user(stats.group_id),
638                  'ref_count': stats.ref_count,
639                  'packet_count': stats.packet_count,
640                  'byte_count': stats.byte_count,
641                  'bucket_stats': bucket_counters}
642             groups.append(g)
643
644     return {str(dp.id): groups}
645
646
647 def get_group_features(dp, waiters):
648
649     ofp = dp.ofproto
650     type_convert = {ofp.OFPGT_ALL: 'ALL',
651                     ofp.OFPGT_SELECT: 'SELECT',
652                     ofp.OFPGT_INDIRECT: 'INDIRECT',
653                     ofp.OFPGT_FF: 'FF'}
654     cap_convert = {ofp.OFPGFC_SELECT_WEIGHT: 'SELECT_WEIGHT',
655                    ofp.OFPGFC_SELECT_LIVENESS: 'SELECT_LIVENESS',
656                    ofp.OFPGFC_CHAINING: 'CHAINING',
657                    ofp.OFPGFC_CHAINING_CHECKS: 'CHAINING_CHECKS'}
658     act_convert = {ofp.OFPAT_OUTPUT: 'OUTPUT',
659                    ofp.OFPAT_COPY_TTL_OUT: 'COPY_TTL_OUT',
660                    ofp.OFPAT_COPY_TTL_IN: 'COPY_TTL_IN',
661                    ofp.OFPAT_SET_MPLS_TTL: 'SET_MPLS_TTL',
662                    ofp.OFPAT_DEC_MPLS_TTL: 'DEC_MPLS_TTL',
663                    ofp.OFPAT_PUSH_VLAN: 'PUSH_VLAN',
664                    ofp.OFPAT_POP_VLAN: 'POP_VLAN',
665                    ofp.OFPAT_PUSH_MPLS: 'PUSH_MPLS',
666                    ofp.OFPAT_POP_MPLS: 'POP_MPLS',
667                    ofp.OFPAT_SET_QUEUE: 'SET_QUEUE',
668                    ofp.OFPAT_GROUP: 'GROUP',
669                    ofp.OFPAT_SET_NW_TTL: 'SET_NW_TTL',
670                    ofp.OFPAT_DEC_NW_TTL: 'DEC_NW_TTL',
671                    ofp.OFPAT_SET_FIELD: 'SET_FIELD'}
672
673     stats = dp.ofproto_parser.OFPGroupFeaturesStatsRequest(dp, 0)
674     msgs = []
675     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
676
677     features = []
678     for msg in msgs:
679         feature = msg.body
680         types = []
681         for k, v in type_convert.items():
682             if (1 << k) & feature.types:
683                 types.append(v)
684         capabilities = []
685         for k, v in cap_convert.items():
686             if k & feature.capabilities:
687                 capabilities.append(v)
688         max_groups = []
689         for k, v in type_convert.items():
690             max_groups.append({v: feature.max_groups[k]})
691         actions = []
692         for k1, v1 in type_convert.items():
693             acts = []
694             for k2, v2 in act_convert.items():
695                 if (1 << k2) & feature.actions[k1]:
696                     acts.append(v2)
697             actions.append({v1: acts})
698         f = {'types': types,
699              'capabilities': capabilities,
700              'max_groups': max_groups,
701              'actions': actions}
702         features.append(f)
703
704     return {str(dp.id): features}
705
706
707 def get_group_desc(dp, waiters):
708
709     type_convert = {dp.ofproto.OFPGT_ALL: 'ALL',
710                     dp.ofproto.OFPGT_SELECT: 'SELECT',
711                     dp.ofproto.OFPGT_INDIRECT: 'INDIRECT',
712                     dp.ofproto.OFPGT_FF: 'FF'}
713
714     stats = dp.ofproto_parser.OFPGroupDescStatsRequest(dp, 0)
715     msgs = []
716     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
717
718     descs = []
719     for msg in msgs:
720         for stats in msg.body:
721             buckets = []
722             for bucket in stats.buckets:
723                 actions = []
724                 for action in bucket.actions:
725                     actions.append(action_to_str(action))
726                 b = {'weight': bucket.weight,
727                      'watch_port': bucket.watch_port,
728                      'watch_group': bucket.watch_group,
729                      'actions': actions}
730                 buckets.append(b)
731             d = {'type': type_convert.get(stats.type),
732                  'group_id': UTIL.ofp_group_to_user(stats.group_id),
733                  'buckets': buckets}
734             descs.append(d)
735
736     return {str(dp.id): descs}
737
738
739 def get_port_desc(dp, waiters):
740
741     stats = dp.ofproto_parser.OFPFeaturesRequest(dp)
742     msgs = []
743     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
744
745     descs = []
746
747     for msg in msgs:
748         stats = msg.ports
749         for stat in stats.values():
750             d = {'port_no': UTIL.ofp_port_to_user(stat.port_no),
751                  'hw_addr': stat.hw_addr,
752                  'name': stat.name.decode('utf-8'),
753                  'config': stat.config,
754                  'state': stat.state,
755                  'curr': stat.curr,
756                  'advertised': stat.advertised,
757                  'supported': stat.supported,
758                  'peer': stat.peer,
759                  'curr_speed': stat.curr_speed,
760                  'max_speed': stat.max_speed}
761             descs.append(d)
762
763     return {str(dp.id): descs}
764
765
766 def get_role(dp, waiters, to_user=True):
767     return ofctl_utils.get_role(dp, waiters, to_user)
768
769
770 def mod_flow_entry(dp, flow, cmd):
771     cookie = str_to_int(flow.get('cookie', 0))
772     cookie_mask = str_to_int(flow.get('cookie_mask', 0))
773     table_id = UTIL.ofp_table_from_user(flow.get('table_id', 0))
774     idle_timeout = str_to_int(flow.get('idle_timeout', 0))
775     hard_timeout = str_to_int(flow.get('hard_timeout', 0))
776     priority = str_to_int(flow.get('priority', 0))
777     buffer_id = UTIL.ofp_buffer_from_user(
778         flow.get('buffer_id', dp.ofproto.OFP_NO_BUFFER))
779     out_port = UTIL.ofp_port_from_user(
780         flow.get('out_port', dp.ofproto.OFPP_ANY))
781     out_group = UTIL.ofp_group_from_user(
782         flow.get('out_group', dp.ofproto.OFPG_ANY))
783     flags = str_to_int(flow.get('flags', 0))
784     match = to_match(dp, flow.get('match', {}))
785     inst = to_actions(dp, flow.get('actions', []))
786
787     flow_mod = dp.ofproto_parser.OFPFlowMod(
788         dp, cookie, cookie_mask, table_id, cmd, idle_timeout,
789         hard_timeout, priority, buffer_id, out_port, out_group,
790         flags, match, inst)
791
792     ofctl_utils.send_msg(dp, flow_mod, LOG)
793
794
795 def mod_group_entry(dp, group, cmd):
796
797     type_convert = {'ALL': dp.ofproto.OFPGT_ALL,
798                     'SELECT': dp.ofproto.OFPGT_SELECT,
799                     'INDIRECT': dp.ofproto.OFPGT_INDIRECT,
800                     'FF': dp.ofproto.OFPGT_FF}
801
802     type_ = type_convert.get(group.get('type', 'ALL'))
803     if type_ is None:
804         LOG.error('Unknown group type: %s', group.get('type'))
805
806     group_id = UTIL.ofp_group_from_user(group.get('group_id', 0))
807
808     buckets = []
809     for bucket in group.get('buckets', []):
810         weight = str_to_int(bucket.get('weight', 0))
811         watch_port = str_to_int(
812             bucket.get('watch_port', dp.ofproto.OFPP_ANY))
813         watch_group = str_to_int(
814             bucket.get('watch_group', dp.ofproto.OFPG_ANY))
815         actions = []
816         for dic in bucket.get('actions', []):
817             action = to_action(dp, dic)
818             if action is not None:
819                 actions.append(action)
820         buckets.append(dp.ofproto_parser.OFPBucket(
821             weight, watch_port, watch_group, actions))
822
823     group_mod = dp.ofproto_parser.OFPGroupMod(
824         dp, cmd, type_, group_id, buckets)
825
826     ofctl_utils.send_msg(dp, group_mod, LOG)
827
828
829 def mod_port_behavior(dp, port_config):
830     port_no = UTIL.ofp_port_from_user(port_config.get('port_no', 0))
831     hw_addr = str(port_config.get('hw_addr'))
832     config = str_to_int(port_config.get('config', 0))
833     mask = str_to_int(port_config.get('mask', 0))
834     advertise = str_to_int(port_config.get('advertise'))
835
836     port_mod = dp.ofproto_parser.OFPPortMod(
837         dp, port_no, hw_addr, config, mask, advertise)
838
839     ofctl_utils.send_msg(dp, port_mod, LOG)
840
841
842 def set_role(dp, role):
843     r = UTIL.ofp_role_from_user(role.get('role', dp.ofproto.OFPCR_ROLE_EQUAL))
844     role_request = dp.ofproto_parser.OFPRoleRequest(dp, r, 0)
845     ofctl_utils.send_msg(dp, role_request, LOG)
846
847
848 # NOTE(jkoelker) Alias common funcitons
849 send_experimenter = ofctl_utils.send_experimenter