summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOHMURA Kei <ohmura.kei@lab.ntt.co.jp>2012-09-03 18:46:40 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2012-10-30 11:39:52 +0900
commit3e74c789e992b4076dee8db2ad850a5429443cee (patch)
tree4bcafaaf752af451219f3fd2e9347edea4864cc2
parent51b3b9a2bd086d0bb8e21a0e0e3db015c7e55f7f (diff)
ryu/lib/ofctl_v1_0: introduce OF interface
This patch provides the raw OF interface. We can talk with a switch by using the OF interface via some protocols such as REST. Signed-off-by: OHMURA Kei <ohmura.kei@lab.ntt.co.jp> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--ryu/lib/ofctl_v1_0.py237
1 files changed, 237 insertions, 0 deletions
diff --git a/ryu/lib/ofctl_v1_0.py b/ryu/lib/ofctl_v1_0.py
new file mode 100644
index 00000000..2ec36c09
--- /dev/null
+++ b/ryu/lib/ofctl_v1_0.py
@@ -0,0 +1,237 @@
+# Copyright (C) 2012 Nippon Telegraph and Telephone Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+
+import gevent
+
+from ryu.ofproto import ofproto_v1_0
+from ryu.lib.mac import haddr_to_bin, haddr_to_str
+
+
+LOG = logging.getLogger('ryu.lib.ofctl_v1_0')
+
+DEFAULT_TIMEOUT = 1.0 # TODO:XXX
+
+
+def to_actions(dp, acts):
+ actions = []
+ for a in acts:
+ action_type = a.get('type')
+ if action_type == 'OUTPUT':
+ out_port = int(a.get('port', ofproto_v1_0.OFPP_NONE))
+ actions.append(dp.ofproto_parser.OFPActionOutput(out_port))
+ elif action_type == 'SET_VLAN_VID':
+ vlan_vid = int(a.get('vlan_vid', 0xffff))
+ actions.append(dp.ofproto_parser.OFPActionVlanVid(vlan_vid))
+ elif action_type == 'SET_VLAN_PCP':
+ vlan_pcp = int(a.get('vlan_pcp', 0))
+ actions.append(dp.ofproto_parser.OFPActionVlanPcp(vlan_pcp))
+ elif action_type == 'STRIP_VLAN':
+ actions.append(dp.ofproto_parser.OFPActionStripVlan())
+ elif action_type == 'SET_DL_SRC':
+ dl_src = haddr_to_bin(a.get('dl_src'))
+ actions.append(dp.ofproto_parser.OFPActionSetDlSrc(dl_src))
+ elif action_type == 'SET_DL_DST':
+ dl_dst = haddr_to_bin(a.get('dl_dst'))
+ actions.append(dp.ofproto_parser.OFPActionSetDlDst(dl_dst))
+ else:
+ LOG.debug('Unknown action type')
+
+ return actions
+
+
+def to_match(dp, attrs):
+ ofp = dp.ofproto
+
+ wildcards = ofp.OFPFW_ALL
+ in_port = 0
+ dl_src = 0
+ dl_dst = 0
+ dl_vlan = 0
+ dl_vlan_pcp = 0
+ dl_type = 0
+ nw_tos = 0
+ nw_proto = 0
+ nw_src = 0
+ nw_dst = 0
+ tp_src = 0
+ tp_dst = 0
+
+ for key, value in attrs.items():
+ if key == 'in_port':
+ in_port = int(value)
+ wildcards &= ~ofp.OFPFW_IN_PORT
+ elif key == 'dl_src':
+ dl_src = haddr_to_bin(value)
+ wildcards &= ~ofp.OFPFW_DL_DST
+ elif key == 'dl_dst':
+ dl_dst = haddr_to_bin(value)
+ wildcards &= ~ofp.OFPFW_DL_DST
+ elif key == 'dl_vlan':
+ dl_vlan = int(value)
+ wildcards &= ~ofp.OFPFW_DL_VLAN
+ elif key == 'dl_vlan_pcp':
+ dl_vlan_pcp = int(value)
+ wildcards &= ~ofp.OFPFW_DL_VLAN_PCP
+ elif key == 'dl_type':
+ dl_type = int(value)
+ wildcards &= ~ofp.OFPFW_DL_TYPE
+ elif key == 'nw_tos':
+ nw_tos = int(value)
+ wildcards &= ~ofp.OFPFW_NW_TOS
+ elif key == 'nw_proto':
+ nw_proto = int(value)
+ wildcards &= ~ofp.OFPFW_NW_PROTO
+ elif key == 'nw_src':
+ pass
+ elif key == 'nw_dst':
+ pass
+ elif key == 'tp_src':
+ tp_src = int(value)
+ wildcards &= ~ofp.OFPFW_TP_SRC
+ elif key == 'tp_dst':
+ tp_dst = int(value)
+ wildcards &= ~ofp.OFPFW_TP_DST
+ else:
+ print "unknown match name ", key, value, len(key)
+
+ match = dp.ofproto_parser.OFPMatch(
+ wildcards, in_port, dl_src, dl_dst, dl_vlan, dl_vlan_pcp,
+ dl_type, nw_tos, nw_proto, nw_src, nw_dst, tp_src, tp_dst)
+
+ return match
+
+
+def send_stats_request(dp, stats, waiters, msgs):
+ dp.set_xid(stats)
+ waiters = waiters.setdefault(dp.id, {})
+ lock = gevent.event.AsyncResult()
+ waiters[stats.xid] = (lock, msgs)
+ dp.send_msg(stats)
+
+ try:
+ lock.get(timeout=DEFAULT_TIMEOUT)
+ except gevent.Timeout:
+ del waiters[dp.id][stats.xid]
+
+
+def get_desc_stats(dp, waiters):
+ stats = dp.ofproto_parser.OFPDescStatsRequest(dp, 0)
+ msgs = []
+ send_stats_request(dp, stats, waiters, msgs)
+
+ for msg in msgs:
+ stats = msg.body
+ s = {'mfr_desc': stats.mfr_desc,
+ 'hw_desc': stats.hw_desc,
+ 'sw_desc': stats.sw_desc,
+ 'serial_num': stats.serial_num,
+ 'dp_desc': stats.dp_desc}
+ desc = {str(dp.id): s}
+ return desc
+
+
+def get_flow_stats(dp, waiters):
+ match = dp.ofproto_parser.OFPMatch(
+ dp.ofproto.OFPFW_ALL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+ stats = dp.ofproto_parser.OFPFlowStatsRequest(
+ dp, 0, match, 0xff, dp.ofproto.OFPP_NONE)
+ msgs = []
+ send_stats_request(dp, stats, waiters, msgs)
+
+ flows = []
+ for msg in msgs:
+ for stats in msg.body:
+ s = {'priority': stats.priority,
+ 'cookie': stats.cookie,
+ 'idle_timeout': stats.idle_timeout,
+ 'hard_timeout': stats.hard_timeout,
+ 'match': {'dl_dst': haddr_to_str(stats.match.dl_dst),
+ 'dl_src': haddr_to_str(stats.match.dl_src),
+ 'dl_type': stats.match.dl_type,
+ 'dl_vlan': stats.match.dl_vlan,
+ 'dl_vlan_pcp': stats.match.dl_vlan_pcp,
+ 'in_port': stats.match.in_port,
+ 'nw_dst': stats.match.nw_dst,
+ 'nw_proto': stats.match.nw_proto,
+ 'nw_src': stats.match.nw_src,
+ 'tp_src': stats.match.tp_src,
+ 'tp_dst': stats.match.tp_dst},
+ 'byte_count': stats.byte_count,
+ 'duration_sec': stats.duration_sec,
+ 'duration_nsec': stats.duration_nsec,
+ 'packet_count': stats.packet_count,
+ 'table_id': stats.table_id}
+ flows.append(s)
+ flows = {str(dp.id): flows}
+ return flows
+
+
+def get_port_stats(dp, waiters):
+ stats = dp.ofproto_parser.OFPPortStatsRequest(
+ dp, 0, dp.ofproto.OFPP_NONE)
+ msgs = []
+ send_stats_request(dp, stats, waiters, msgs)
+
+ ports = []
+ for msg in msgs:
+ for stats in msg.body:
+ s = {'port_no': stats.port_no,
+ 'rx_packets': stats.rx_packets,
+ 'tx_packets': stats.tx_packets,
+ 'rx_bytes': stats.rx_bytes,
+ 'tx_bytes': stats.tx_bytes,
+ 'rx_dropped': stats.rx_dropped,
+ 'tx_dropped': stats.tx_dropped,
+ 'rx_errors': stats.rx_errors,
+ 'tx_errors': stats.tx_errors,
+ 'rx_frame_err': stats.rx_frame_err,
+ 'rx_over_err': stats.rx_over_err,
+ 'rx_crc_err': stats.rx_crc_err,
+ 'collisions': stats.collisions}
+ ports.append(s)
+ ports = {str(dp.id): ports}
+ return ports
+
+
+def push_flow_entry(dp, flow):
+ cookie = int(flow.get('cookie', 0))
+ priority = int(flow.get('priority',
+ dp.ofproto.OFP_DEFAULT_PRIORITY))
+ flags = int(flow.get('flags', 0))
+ idle_timeout = int(flow.get('idle_timeout', 0))
+ hard_timeout = int(flow.get('hard_timeout', 0))
+ actions = to_actions(dp, flow.get('actions', {}))
+ match = to_match(dp, flow.get('match', {}))
+
+ flow_mod = dp.ofproto_parser.OFPFlowMod(
+ datapath=dp, match=match, cookie=cookie,
+ command=dp.ofproto.OFPFC_ADD, idle_timeout=idle_timeout,
+ hard_timeout=hard_timeout, priority=priority, flags=flags,
+ actions=actions)
+
+ dp.send_msg(flow_mod)
+
+
+def delete_flow_entry(dp):
+ match = dp.ofproto_parser.OFPMatch(
+ dp.ofproto.OFPFW_ALL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+
+ flow_mod = dp.ofproto_parser.OFPFlowMod(
+ datapath=dp, match=match, cookie=0,
+ command=dp.ofproto.OFPFC_DELETE)
+
+ dp.send_msg(flow_mod)