1 # Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
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
28 LOG = logging.getLogger('ryu.lib.ofctl_v1_3')
32 UTIL = ofctl_utils.OFCtlUtil(ofproto_v1_3)
33 str_to_int = ofctl_utils.str_to_int
36 def to_action(dp, dic):
38 parser = dp.ofproto_parser
39 action_type = dic.get('type')
40 return ofctl_utils.to_action(dic, ofp, parser, action_type, UTIL)
43 def to_actions(dp, acts):
47 parser = dp.ofproto_parser
50 action = to_action(dp, a)
52 if action is not None:
53 actions.append(action)
55 action_type = a.get('type')
56 if action_type == '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)
64 LOG.error('Unknown action type: %s', action_type)
67 parser.OFPInstructionActions(ofp.OFPIT_WRITE_ACTIONS,
69 elif action_type == 'CLEAR_ACTIONS':
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)
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))
87 LOG.error('Unknown action type: %s', action_type)
90 inst.append(parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
95 def action_to_str(act):
96 action_type = act.cls_action_type
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:
103 elif action_type == ofproto_v1_3.OFPAT_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:
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:
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:
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:
133 elif action_type == ofproto_v1_3.OFPAT_EXPERIMENTER:
134 if act.experimenter == ofproto_common.NX_EXPERIMENTER_ID:
136 return ofctl_nicira_ext.action_to_str(act, action_to_str)
138 LOG.debug('Error parsing NX_ACTION(%s)',
139 act.__class__.__name__, exc_info=True)
141 data_str = base64.b64encode(act.data)
142 buf = 'EXPERIMENTER: {experimenter:%s, data:%s}' % \
143 (act.experimenter, data_str.decode('utf-8'))
149 def actions_to_str(instructions):
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:
160 for a in instruction.actions:
161 write_actions.append(action_to_str(a))
163 actions.append({'WRITE_ACTIONS': write_actions})
164 elif instruction.type == ofproto_v1_3.OFPIT_CLEAR_ACTIONS:
165 actions.append('CLEAR_ACTIONS')
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)
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)
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)
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}
245 keys = {'dl_dst': 'eth_dst',
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'}
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']
258 if 'nw_dst' in attrs and 'arp_tpa' not in attrs:
259 attrs['arp_tpa'] = attrs['nw_dst']
263 for key, value in attrs.items():
268 value = convert[key](value)
269 if key == 'tp_src' or key == 'tp_dst':
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]
282 LOG.error('Unknown match field: %s', key)
284 return dp.ofproto_parser.OFPMatch(**kwargs)
287 def to_match_vid(value):
288 return ofctl_utils.to_match_vid(value, ofproto_v1_3.OFPVID_PRESENT)
291 def match_to_str(ofmatch):
293 keys = {'eth_src': 'dl_src',
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',
307 ofmatch = ofmatch.to_jsondict()['OFPMatch']
308 ofmatch = ofmatch['oxm_fields']
310 for match_field in ofmatch:
311 key = match_field['OXMTlv']['field']
314 mask = match_field['OXMTlv']['mask']
315 value = match_field['OXMTlv']['value']
317 value = match_vid_to_str(value, mask)
318 elif key == 'in_port':
319 value = UTIL.ofp_port_to_user(value)
322 value = str(value) + '/' + str(mask)
323 match.setdefault(key, value)
328 def match_vid_to_str(value, mask):
329 return ofctl_utils.match_vid_to_str(
330 value, mask, ofproto_v1_3.OFPVID_PRESENT)
333 def wrap_dpid_dict(dp, value, to_user=True):
335 return {str(dp.id): value}
337 return {dp.id: value}
340 def get_desc_stats(dp, waiters, to_user=True):
341 stats = dp.ofproto_parser.OFPDescStatsRequest(dp, 0)
343 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
348 s = stats.to_jsondict()[stats.__class__.__name__]
350 return wrap_dpid_dict(dp, s, to_user)
353 def get_queue_stats(dp, waiters, port=None, queue_id=None, to_user=True):
359 port = str_to_int(port)
362 queue_id = ofp.OFPQ_ALL
364 queue_id = str_to_int(queue_id)
366 stats = dp.ofproto_parser.OFPQueueStatsRequest(dp, 0, port,
369 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
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})
383 return wrap_dpid_dict(dp, s, to_user)
386 def get_queue_config(dp, waiters, port=None, to_user=True):
391 port = UTIL.ofp_port_from_user(str_to_int(port))
392 stats = dp.ofproto_parser.OFPQueueGetConfigRequest(dp, port)
394 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
396 prop_type = {dp.ofproto.OFPQT_MIN_RATE: 'MIN_RATE',
397 dp.ofproto.OFPQT_MAX_RATE: 'MAX_RATE',
398 dp.ofproto.OFPQT_EXPERIMENTER: 'EXPERIMENTER'}
403 for queue in config.queues:
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
415 q = {'properties': prop_list}
418 q['port'] = UTIL.ofp_port_to_user(queue.port)
419 q['queue_id'] = UTIL.ofp_queue_to_user(queue.queue_id)
422 q['port'] = queue.port
423 q['queue_id'] = queue.queue_id
427 c = {'queues': queue_list}
430 c['port'] = UTIL.ofp_port_to_user(config.port)
433 c['port'] = config.port
437 return wrap_dpid_dict(dp, configs, to_user)
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))
456 stats = dp.ofproto_parser.OFPFlowStatsRequest(
457 dp, flags, table_id, out_port, out_group, cookie, cookie_mask,
461 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
465 for stats in msg.body:
466 if 0 <= priority != stats.priority:
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}
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)
486 s['actions'] = stats.instructions
487 s['instructions'] = stats.instructions
488 s['match'] = stats.match
489 s['table_id'] = stats.table_id
493 return wrap_dpid_dict(dp, flows, to_user)
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', {}))
509 stats = dp.ofproto_parser.OFPAggregateStatsRequest(
510 dp, flags, table_id, out_port, out_group, cookie, cookie_mask,
514 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
519 s = {'packet_count': stats.packet_count,
520 'byte_count': stats.byte_count,
521 'flow_count': stats.flow_count}
524 return wrap_dpid_dict(dp, flows, to_user)
527 def get_table_stats(dp, waiters, to_user=True):
528 stats = dp.ofproto_parser.OFPTableStatsRequest(dp, 0)
530 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
536 s = {'active_count': stat.active_count,
537 'lookup_count': stat.lookup_count,
538 'matched_count': stat.matched_count}
541 s['table_id'] = UTIL.ofp_table_to_user(stat.table_id)
544 s['table_id'] = stat.table_id
548 return wrap_dpid_dict(dp, tables, to_user)
551 def get_table_features(dp, waiters, to_user=True):
552 stats = dp.ofproto_parser.OFPTableFeaturesStatsRequest(dp, 0, [])
555 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
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'}
575 prop_type = dict((k, k) for k in prop_type.keys())
577 p_type_instructions = [ofproto.OFPTFPT_INSTRUCTIONS,
578 ofproto.OFPTFPT_INSTRUCTIONS_MISS]
580 p_type_next_tables = [ofproto.OFPTFPT_NEXT_TABLES,
581 ofproto.OFPTFPT_NEXT_TABLES_MISS]
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]
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]
595 p_type_experimenter = [ofproto.OFPTFPT_EXPERIMENTER,
596 ofproto.OFPTFPT_EXPERIMENTER_MISS]
603 for prop in stat.properties:
604 p = {'type': prop_type.get(prop.type, 'UNKNOWN')}
605 if prop.type in p_type_instructions:
607 for i in prop.instruction_ids:
608 inst = {'len': i.len,
610 instruction_ids.append(inst)
611 p['instruction_ids'] = instruction_ids
612 elif prop.type in p_type_next_tables:
614 for i in prop.table_ids:
616 p['table_ids'] = table_ids
617 elif prop.type in p_type_actions:
619 for i in prop.action_ids:
622 action_ids.append(act)
623 p['action_ids'] = action_ids
624 elif prop.type in p_type_oxms:
626 for i in prop.oxm_ids:
627 oxm = {'hasmask': i.hasmask,
631 p['oxm_ids'] = oxm_ids
632 elif prop.type in p_type_experimenter:
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,
645 s['table_id'] = UTIL.ofp_table_to_user(stat.table_id)
648 s['table_id'] = stat.table_id
652 return wrap_dpid_dict(dp, tables, to_user)
655 def get_port_stats(dp, waiters, port=None, to_user=True):
657 port = dp.ofproto.OFPP_ANY
659 port = str_to_int(port)
661 stats = dp.ofproto_parser.OFPPortStatsRequest(
664 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
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}
685 s['port_no'] = UTIL.ofp_port_to_user(stats.port_no)
688 s['port_no'] = stats.port_no
692 return wrap_dpid_dict(dp, ports, to_user)
695 def get_meter_stats(dp, waiters, meter_id=None, to_user=True):
697 meter_id = dp.ofproto.OFPM_ALL
699 meter_id = str_to_int(meter_id)
701 stats = dp.ofproto_parser.OFPMeterStatsRequest(
704 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
708 for stats in msg.body:
710 for band in stats.band_stats:
711 b = {'packet_band_count': band.packet_band_count,
712 'byte_band_count': band.byte_band_count}
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,
723 s['meter_id'] = UTIL.ofp_meter_to_user(stats.meter_id)
726 s['meter_id'] = stats.meter_id
730 return wrap_dpid_dict(dp, meters, to_user)
733 def get_meter_features(dp, waiters, to_user=True):
736 type_convert = {ofp.OFPMBT_DROP: 'DROP',
737 ofp.OFPMBT_DSCP_REMARK: 'DSCP_REMARK'}
739 capa_convert = {ofp.OFPMF_KBPS: 'KBPS',
740 ofp.OFPMF_PKTPS: 'PKTPS',
741 ofp.OFPMF_BURST: 'BURST',
742 ofp.OFPMF_STATS: 'STATS'}
744 stats = dp.ofproto_parser.OFPMeterFeaturesStatsRequest(dp, 0)
746 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
750 for feature in msg.body:
752 for k, v in type_convert.items():
753 if (1 << k) & feature.band_types:
762 for k, v in sorted(capa_convert.items()):
763 if k & feature.capabilities:
766 capabilities.append(v)
769 capabilities.append(k)
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}
778 return wrap_dpid_dict(dp, features, to_user)
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'}
787 band_type = {dp.ofproto.OFPMBT_DROP: 'DROP',
788 dp.ofproto.OFPMBT_DSCP_REMARK: 'DSCP_REMARK',
789 dp.ofproto.OFPMBT_EXPERIMENTER: 'EXPERIMENTER'}
792 meter_id = dp.ofproto.OFPM_ALL
794 meter_id = str_to_int(meter_id)
796 stats = dp.ofproto_parser.OFPMeterConfigStatsRequest(
799 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
803 for config in msg.body:
805 for band in config.bands:
806 b = {'rate': band.rate,
807 'burst_size': band.burst_size}
810 b['type'] = band_type.get(band.type, '')
813 b['type'] = band.type
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
821 for k, v in sorted(flags.items()):
829 c = {'flags': c_flags,
833 c['meter_id'] = UTIL.ofp_meter_to_user(config.meter_id)
836 c['meter_id'] = config.meter_id
840 return wrap_dpid_dict(dp, configs, to_user)
843 def get_group_stats(dp, waiters, group_id=None, to_user=True):
845 group_id = dp.ofproto.OFPG_ALL
847 group_id = str_to_int(group_id)
849 stats = dp.ofproto_parser.OFPGroupStatsRequest(
852 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
856 for stats in msg.body:
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}
871 g['group_id'] = UTIL.ofp_group_to_user(stats.group_id)
874 g['group_id'] = stats.group_id
878 return wrap_dpid_dict(dp, groups, to_user)
881 def get_group_features(dp, waiters, to_user=True):
884 type_convert = {ofp.OFPGT_ALL: 'ALL',
885 ofp.OFPGT_SELECT: 'SELECT',
886 ofp.OFPGT_INDIRECT: 'INDIRECT',
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'}
909 stats = dp.ofproto_parser.OFPGroupFeaturesStatsRequest(dp, 0)
911 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
917 for k, v in type_convert.items():
918 if (1 << k) & feature.types:
926 for k, v in cap_convert.items():
927 if k & feature.capabilities:
929 capabilities.append(v)
932 capabilities.append(k)
936 for k, v in type_convert.items():
937 max_groups.append({v: feature.max_groups[k]})
940 max_groups = feature.max_groups
943 for k1, v1 in type_convert.items():
945 for k2, v2 in act_convert.items():
946 if (1 << k2) & feature.actions[k1]:
954 actions.append({v1: acts})
957 actions.append({k1: acts})
960 'capabilities': capabilities,
961 'max_groups': max_groups,
965 return wrap_dpid_dict(dp, features, to_user)
968 def get_group_desc(dp, waiters, to_user=True):
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'}
975 stats = dp.ofproto_parser.OFPGroupDescStatsRequest(dp, 0)
977 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
981 for stats in msg.body:
983 for bucket in stats.buckets:
985 for action in bucket.actions:
987 actions.append(action_to_str(action))
990 actions.append(action)
992 b = {'weight': bucket.weight,
993 'watch_port': bucket.watch_port,
994 'watch_group': bucket.watch_group,
998 d = {'buckets': buckets}
1000 d['group_id'] = UTIL.ofp_group_to_user(stats.group_id)
1001 d['type'] = type_convert.get(stats.type)
1004 d['group_id'] = stats.group_id
1005 d['type'] = stats.type
1009 return wrap_dpid_dict(dp, descs, to_user)
1012 def get_port_desc(dp, waiters, to_user=True):
1014 stats = dp.ofproto_parser.OFPPortDescStatsRequest(dp, 0)
1016 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
1023 d = {'hw_addr': stat.hw_addr,
1024 'name': stat.name.decode('utf-8', errors='replace'),
1025 'config': stat.config,
1026 'state': stat.state,
1028 'advertised': stat.advertised,
1029 'supported': stat.supported,
1031 'curr_speed': stat.curr_speed,
1032 'max_speed': stat.max_speed}
1035 d['port_no'] = UTIL.ofp_port_to_user(stat.port_no)
1038 d['port_no'] = stat.port_no
1042 return wrap_dpid_dict(dp, descs, to_user)
1045 def get_role(dp, waiters, to_user=True):
1046 return ofctl_utils.get_role(dp, waiters, to_user)
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', []))
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,
1071 ofctl_utils.send_msg(dp, flow_mod, LOG)
1074 def mod_meter_entry(dp, meter, cmd):
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}
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)
1090 flags |= flags_convert.get(flag)
1092 meter_id = UTIL.ofp_meter_from_user(meter.get('meter_id', 0))
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':
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))
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))
1110 dp.ofproto_parser.OFPMeterBandExperimenter(
1111 rate, burst_size, experimenter))
1113 LOG.error('Unknown band type: %s', band_type)
1115 meter_mod = dp.ofproto_parser.OFPMeterMod(
1116 dp, cmd, flags, meter_id, bands)
1118 ofctl_utils.send_msg(dp, meter_mod, LOG)
1121 def mod_group_entry(dp, group, cmd):
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}
1128 type_ = type_convert.get(group.get('type', 'ALL'))
1130 LOG.error('Unknown group type: %s', group.get('type'))
1132 group_id = UTIL.ofp_group_from_user(group.get('group_id', 0))
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))
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))
1149 group_mod = dp.ofproto_parser.OFPGroupMod(
1150 dp, cmd, type_, group_id, buckets)
1152 ofctl_utils.send_msg(dp, group_mod, LOG)
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'))
1162 port_mod = dp.ofproto_parser.OFPPortMod(
1163 dp, port_no, hw_addr, config, mask, advertise)
1165 ofctl_utils.send_msg(dp, port_mod, LOG)
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)
1174 # NOTE(jkoelker) Alias common funcitons
1175 send_experimenter = ofctl_utils.send_experimenter