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_v1_2
22 from ryu.ofproto import ofproto_v1_2_parser
23 from ryu.lib import ofctl_utils
26 LOG = logging.getLogger('ryu.lib.ofctl_v1_2')
30 UTIL = ofctl_utils.OFCtlUtil(ofproto_v1_2)
31 str_to_int = ofctl_utils.str_to_int
34 def to_action(dp, dic):
36 parser = dp.ofproto_parser
37 action_type = dic.get('type')
38 return ofctl_utils.to_action(dic, ofp, parser, action_type, UTIL)
41 def to_actions(dp, acts):
45 parser = dp.ofproto_parser
48 action = to_action(dp, a)
49 if action is not None:
50 actions.append(action)
52 action_type = a.get('type')
53 if action_type == '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)
61 LOG.error('Unknown action type: %s', action_type)
64 parser.OFPInstructionActions(ofp.OFPIT_WRITE_ACTIONS,
66 elif action_type == 'CLEAR_ACTIONS':
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)
78 parser.OFPInstructionWriteMetadata(
79 metadata, metadata_mask))
81 LOG.error('Unknown action type: %s', action_type)
84 inst.append(parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
89 def action_to_str(act):
90 action_type = act.cls_action_type
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:
97 elif action_type == ofproto_v1_2.OFPAT_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:
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:
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:
121 elif action_type == ofproto_v1_2.OFPAT_SET_FIELD:
122 buf = 'SET_FIELD: {%s:%s}' % (act.key, act.value)
128 def actions_to_str(instructions):
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:
139 for a in instruction.actions:
140 write_actions.append(action_to_str(a))
142 actions.append({'WRITE_ACTIONS': write_actions})
143 elif instruction.type == ofproto_v1_2.OFPIT_CLEAR_ACTIONS:
144 actions.append('CLEAR_ACTIONS')
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)
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)
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}
214 keys = {'dl_dst': 'eth_dst',
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'}
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']
227 if 'nw_dst' in attrs and 'arp_tpa' not in attrs:
228 attrs['arp_tpa'] = attrs['nw_dst']
232 for key, value in attrs.items():
237 value = convert[key](value)
238 if key == 'tp_src' or key == 'tp_dst':
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]
251 LOG.error('Unknown match field: %s', key)
253 return dp.ofproto_parser.OFPMatch(**kwargs)
256 def to_match_vid(value):
257 return ofctl_utils.to_match_vid(value, ofproto_v1_2.OFPVID_PRESENT)
260 def match_to_str(ofmatch):
262 keys = {'eth_src': 'dl_src',
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',
276 ofmatch = ofmatch.to_jsondict()['OFPMatch']
277 ofmatch = ofmatch['oxm_fields']
278 for match_field in ofmatch:
279 key = match_field['OXMTlv']['field']
282 mask = match_field['OXMTlv']['mask']
283 value = match_field['OXMTlv']['value']
285 value = match_vid_to_str(value, mask)
286 elif key == 'in_port':
287 value = UTIL.ofp_port_to_user(value)
290 value = str(value) + '/' + str(mask)
291 match.setdefault(key, value)
296 def match_vid_to_str(value, mask):
297 return ofctl_utils.match_vid_to_str(
298 value, mask, ofproto_v1_2.OFPVID_PRESENT)
301 def get_desc_stats(dp, waiters):
302 stats = dp.ofproto_parser.OFPDescStatsRequest(dp)
304 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
309 s = stats.to_jsondict()[stats.__class__.__name__]
311 return {str(dp.id): s}
314 def get_queue_stats(dp, waiters, port=None, queue_id=None):
320 port = str_to_int(port)
323 queue_id = ofp.OFPQ_ALL
325 queue_id = str_to_int(queue_id)
327 stats = dp.ofproto_parser.OFPQueueStatsRequest(dp, port,
330 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
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})
342 return {str(dp.id): s}
345 def get_queue_config(dp, waiters, port=None):
350 port = UTIL.ofp_port_from_user(str_to_int(port))
351 stats = dp.ofproto_parser.OFPQueueGetConfigRequest(dp, port)
353 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
356 dp.ofproto.OFPQT_MIN_RATE: 'MIN_RATE',
357 dp.ofproto.OFPQT_MAX_RATE: 'MAX_RATE',
358 dp.ofproto.OFPQT_EXPERIMENTER: 'EXPERIMENTER',
364 for queue in config.queues:
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
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)}
379 c = {'port': UTIL.ofp_port_to_user(config.port),
380 'queues': queue_list}
383 return {str(dp.id): configs}
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))
401 stats = dp.ofproto_parser.OFPFlowStatsRequest(
402 dp, table_id, out_port, out_group, cookie, cookie_mask, match)
405 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
409 for stats in msg.body:
410 if 0 <= priority != stats.priority:
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,
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}
429 return {str(dp.id): flows}
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', {}))
444 stats = dp.ofproto_parser.OFPAggregateStatsRequest(
445 dp, table_id, out_port, out_group, cookie, cookie_mask, match)
448 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
453 s = {'packet_count': stats.packet_count,
454 'byte_count': stats.byte_count,
455 'flow_count': stats.flow_count}
458 return {str(dp.id): flows}
461 def get_table_stats(dp, waiters):
462 stats = dp.ofproto_parser.OFPTableStatsRequest(dp)
465 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
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'}
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'}
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'}
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'}
540 for k, v in oxm_type_convert.items():
541 if (1 << k) & stat.match:
543 if (1 << k) & stat.wildcards:
545 if (1 << k) & stat.write_setfields:
546 write_setfields.append(v)
547 if (1 << k) & stat.apply_setfields:
548 apply_setfields.append(v)
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)
557 for k, v in inst_convert.items():
558 if (1 << k) & stat.instructions:
559 instructions.append(v)
561 for k, v in table_conf_convert.items():
562 if (1 << k) & stat.config:
564 s = {'table_id': UTIL.ofp_table_to_user(stat.table_id),
565 'name': stat.name.decode('utf-8'),
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,
576 'max_entries': stat.max_entries,
577 'active_count': stat.active_count,
578 'lookup_count': stat.lookup_count,
579 'matched_count': stat.matched_count}
582 return {str(dp.id): tables}
585 def get_port_stats(dp, waiters, port=None):
587 port = dp.ofproto.OFPP_ANY
589 port = str_to_int(port)
591 stats = dp.ofproto_parser.OFPPortStatsRequest(
594 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
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}
614 return {str(dp.id): ports}
617 def get_group_stats(dp, waiters, group_id=None):
619 group_id = dp.ofproto.OFPG_ALL
621 group_id = str_to_int(group_id)
623 stats = dp.ofproto_parser.OFPGroupStatsRequest(
626 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
630 for stats in msg.body:
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}
644 return {str(dp.id): groups}
647 def get_group_features(dp, waiters):
650 type_convert = {ofp.OFPGT_ALL: 'ALL',
651 ofp.OFPGT_SELECT: 'SELECT',
652 ofp.OFPGT_INDIRECT: 'INDIRECT',
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'}
673 stats = dp.ofproto_parser.OFPGroupFeaturesStatsRequest(dp, 0)
675 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
681 for k, v in type_convert.items():
682 if (1 << k) & feature.types:
685 for k, v in cap_convert.items():
686 if k & feature.capabilities:
687 capabilities.append(v)
689 for k, v in type_convert.items():
690 max_groups.append({v: feature.max_groups[k]})
692 for k1, v1 in type_convert.items():
694 for k2, v2 in act_convert.items():
695 if (1 << k2) & feature.actions[k1]:
697 actions.append({v1: acts})
699 'capabilities': capabilities,
700 'max_groups': max_groups,
704 return {str(dp.id): features}
707 def get_group_desc(dp, waiters):
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'}
714 stats = dp.ofproto_parser.OFPGroupDescStatsRequest(dp, 0)
716 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
720 for stats in msg.body:
722 for bucket in stats.buckets:
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,
731 d = {'type': type_convert.get(stats.type),
732 'group_id': UTIL.ofp_group_to_user(stats.group_id),
736 return {str(dp.id): descs}
739 def get_port_desc(dp, waiters):
741 stats = dp.ofproto_parser.OFPFeaturesRequest(dp)
743 ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
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,
756 'advertised': stat.advertised,
757 'supported': stat.supported,
759 'curr_speed': stat.curr_speed,
760 'max_speed': stat.max_speed}
763 return {str(dp.id): descs}
766 def get_role(dp, waiters, to_user=True):
767 return ofctl_utils.get_role(dp, waiters, to_user)
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', []))
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,
792 ofctl_utils.send_msg(dp, flow_mod, LOG)
795 def mod_group_entry(dp, group, cmd):
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}
802 type_ = type_convert.get(group.get('type', 'ALL'))
804 LOG.error('Unknown group type: %s', group.get('type'))
806 group_id = UTIL.ofp_group_from_user(group.get('group_id', 0))
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))
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))
823 group_mod = dp.ofproto_parser.OFPGroupMod(
824 dp, cmd, type_, group_id, buckets)
826 ofctl_utils.send_msg(dp, group_mod, LOG)
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'))
836 port_mod = dp.ofproto_parser.OFPPortMod(
837 dp, port_no, hw_addr, config, mask, advertise)
839 ofctl_utils.send_msg(dp, port_mod, LOG)
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)
848 # NOTE(jkoelker) Alias common funcitons
849 send_experimenter = ofctl_utils.send_experimenter