2012-09-03 18:46:40 +09:00
|
|
|
# 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.
|
|
|
|
|
2012-11-25 22:38:28 +09:00
|
|
|
import struct
|
|
|
|
import socket
|
2012-09-03 18:46:40 +09:00
|
|
|
import logging
|
|
|
|
|
|
|
|
from ryu.ofproto import ofproto_v1_0
|
2016-01-19 13:46:10 +09:00
|
|
|
from ryu.lib import ofctl_utils
|
2012-09-03 18:46:40 +09:00
|
|
|
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
|
|
|
|
|
2016-01-19 13:46:10 +09:00
|
|
|
UTIL = ofctl_utils.OFCtlUtil(ofproto_v1_0)
|
|
|
|
|
2012-09-03 18:46:40 +09:00
|
|
|
|
|
|
|
def to_actions(dp, acts):
|
|
|
|
actions = []
|
|
|
|
for a in acts:
|
|
|
|
action_type = a.get('type')
|
|
|
|
if action_type == 'OUTPUT':
|
2016-01-19 13:46:10 +09:00
|
|
|
port = UTIL.ofp_port_from_user(
|
|
|
|
a.get('port', ofproto_v1_0.OFPP_NONE))
|
2014-11-07 12:00:14 +09:00
|
|
|
# NOTE: The reason of this magic number (0xffe5)
|
|
|
|
# is because there is no good constant in of1.0.
|
|
|
|
# The same value as OFPCML_MAX of of1.2 and of1.3 is used.
|
|
|
|
max_len = int(a.get('max_len', 0xffe5))
|
|
|
|
actions.append(dp.ofproto_parser.OFPActionOutput(port, max_len))
|
2012-09-03 18:46:40 +09:00
|
|
|
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))
|
2014-11-07 12:00:14 +09:00
|
|
|
elif action_type == 'SET_NW_SRC':
|
|
|
|
nw_src = ipv4_to_int(a.get('nw_src'))
|
|
|
|
actions.append(dp.ofproto_parser.OFPActionSetNwSrc(nw_src))
|
|
|
|
elif action_type == 'SET_NW_DST':
|
|
|
|
nw_dst = ipv4_to_int(a.get('nw_dst'))
|
|
|
|
actions.append(dp.ofproto_parser.OFPActionSetNwDst(nw_dst))
|
|
|
|
elif action_type == 'SET_NW_TOS':
|
|
|
|
nw_tos = int(a.get('nw_tos', 0))
|
|
|
|
actions.append(dp.ofproto_parser.OFPActionSetNwTos(nw_tos))
|
|
|
|
elif action_type == 'SET_TP_SRC':
|
|
|
|
tp_src = int(a.get('tp_src', 0))
|
|
|
|
actions.append(dp.ofproto_parser.OFPActionSetTpSrc(tp_src))
|
|
|
|
elif action_type == 'SET_TP_DST':
|
|
|
|
tp_dst = int(a.get('tp_dst', 0))
|
|
|
|
actions.append(dp.ofproto_parser.OFPActionSetTpDst(tp_dst))
|
|
|
|
elif action_type == 'ENQUEUE':
|
2016-01-19 13:46:10 +09:00
|
|
|
port = UTIL.ofp_port_from_user(
|
|
|
|
a.get('port', ofproto_v1_0.OFPP_NONE))
|
|
|
|
queue_id = UTIL.ofp_queue_from_user(a.get('queue_id', 0))
|
2014-11-07 12:00:14 +09:00
|
|
|
actions.append(dp.ofproto_parser.OFPActionEnqueue(port, queue_id))
|
2012-09-03 18:46:40 +09:00
|
|
|
else:
|
2015-01-08 13:45:31 +09:00
|
|
|
LOG.error('Unknown action type')
|
2012-09-03 18:46:40 +09:00
|
|
|
|
|
|
|
return actions
|
|
|
|
|
|
|
|
|
2012-11-25 22:38:28 +09:00
|
|
|
def actions_to_str(acts):
|
|
|
|
actions = []
|
|
|
|
for a in acts:
|
|
|
|
action_type = a.cls_action_type
|
|
|
|
|
|
|
|
if action_type == ofproto_v1_0.OFPAT_OUTPUT:
|
2016-01-19 13:46:10 +09:00
|
|
|
port = UTIL.ofp_port_to_user(a.port)
|
|
|
|
buf = 'OUTPUT:' + str(port)
|
2012-11-25 22:38:28 +09:00
|
|
|
elif action_type == ofproto_v1_0.OFPAT_SET_VLAN_VID:
|
|
|
|
buf = 'SET_VLAN_VID:' + str(a.vlan_vid)
|
|
|
|
elif action_type == ofproto_v1_0.OFPAT_SET_VLAN_PCP:
|
|
|
|
buf = 'SET_VLAN_PCP:' + str(a.vlan_pcp)
|
|
|
|
elif action_type == ofproto_v1_0.OFPAT_STRIP_VLAN:
|
|
|
|
buf = 'STRIP_VLAN'
|
|
|
|
elif action_type == ofproto_v1_0.OFPAT_SET_DL_SRC:
|
|
|
|
buf = 'SET_DL_SRC:' + haddr_to_str(a.dl_addr)
|
|
|
|
elif action_type == ofproto_v1_0.OFPAT_SET_DL_DST:
|
|
|
|
buf = 'SET_DL_DST:' + haddr_to_str(a.dl_addr)
|
2014-11-07 12:00:14 +09:00
|
|
|
elif action_type == ofproto_v1_0.OFPAT_SET_NW_SRC:
|
|
|
|
buf = 'SET_NW_SRC:' + \
|
|
|
|
socket.inet_ntoa(struct.pack('!I', a.nw_addr))
|
|
|
|
elif action_type == ofproto_v1_0.OFPAT_SET_NW_DST:
|
|
|
|
buf = 'SET_NW_DST:' + \
|
|
|
|
socket.inet_ntoa(struct.pack('!I', a.nw_addr))
|
|
|
|
elif action_type == ofproto_v1_0.OFPAT_SET_NW_TOS:
|
|
|
|
buf = 'SET_NW_TOS:' + str(a.tos)
|
|
|
|
elif action_type == ofproto_v1_0.OFPAT_SET_TP_SRC:
|
|
|
|
buf = 'SET_TP_SRC:' + str(a.tp)
|
|
|
|
elif action_type == ofproto_v1_0.OFPAT_SET_TP_DST:
|
|
|
|
buf = 'SET_TP_DST:' + str(a.tp)
|
|
|
|
elif action_type == ofproto_v1_0.OFPAT_ENQUEUE:
|
2016-01-19 13:46:10 +09:00
|
|
|
port = UTIL.ofp_port_to_user(a.port)
|
|
|
|
queue = UTIL.ofp_queue_to_user(a.queue_id)
|
|
|
|
buf = 'ENQUEUE:' + str(port) + ":" + str(queue)
|
2014-11-07 12:00:14 +09:00
|
|
|
elif action_type == ofproto_v1_0.OFPAT_VENDOR:
|
|
|
|
buf = 'VENDOR'
|
2012-11-25 22:38:28 +09:00
|
|
|
else:
|
|
|
|
buf = 'UNKNOWN'
|
|
|
|
actions.append(buf)
|
2012-11-04 23:13:02 +09:00
|
|
|
|
2012-11-25 22:38:28 +09:00
|
|
|
return actions
|
2012-11-04 23:13:02 +09:00
|
|
|
|
|
|
|
|
2014-11-07 12:00:14 +09:00
|
|
|
def ipv4_to_int(addr):
|
|
|
|
ip = addr.split('.')
|
|
|
|
assert len(ip) == 4
|
|
|
|
i = 0
|
|
|
|
for b in ip:
|
|
|
|
b = int(b)
|
|
|
|
i = (i << 8) | b
|
|
|
|
return i
|
|
|
|
|
|
|
|
|
2012-09-03 18:46:40 +09:00
|
|
|
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':
|
2016-01-19 13:46:10 +09:00
|
|
|
in_port = UTIL.ofp_port_from_user(value)
|
2012-09-03 18:46:40 +09:00
|
|
|
wildcards &= ~ofp.OFPFW_IN_PORT
|
|
|
|
elif key == 'dl_src':
|
|
|
|
dl_src = haddr_to_bin(value)
|
2013-03-21 18:02:19 +09:00
|
|
|
wildcards &= ~ofp.OFPFW_DL_SRC
|
2012-09-03 18:46:40 +09:00
|
|
|
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':
|
2012-11-25 22:38:28 +09:00
|
|
|
ip = value.split('/')
|
|
|
|
nw_src = struct.unpack('!I', socket.inet_aton(ip[0]))[0]
|
|
|
|
mask = 32
|
|
|
|
if len(ip) == 2:
|
|
|
|
mask = int(ip[1])
|
|
|
|
assert 0 < mask <= 32
|
|
|
|
v = (32 - mask) << ofp.OFPFW_NW_SRC_SHIFT | \
|
|
|
|
~ofp.OFPFW_NW_SRC_MASK
|
|
|
|
wildcards &= v
|
2012-09-03 18:46:40 +09:00
|
|
|
elif key == 'nw_dst':
|
2012-11-25 22:38:28 +09:00
|
|
|
ip = value.split('/')
|
|
|
|
nw_dst = struct.unpack('!I', socket.inet_aton(ip[0]))[0]
|
|
|
|
mask = 32
|
|
|
|
if len(ip) == 2:
|
|
|
|
mask = int(ip[1])
|
|
|
|
assert 0 < mask <= 32
|
|
|
|
v = (32 - mask) << ofp.OFPFW_NW_DST_SHIFT | \
|
|
|
|
~ofp.OFPFW_NW_DST_MASK
|
|
|
|
wildcards &= v
|
2012-09-03 18:46:40 +09:00
|
|
|
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:
|
2015-01-08 13:45:31 +09:00
|
|
|
LOG.error("unknown match name %s, %s, %d", key, value, len(key))
|
2012-09-03 18:46:40 +09:00
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
2012-11-25 22:38:28 +09:00
|
|
|
def match_to_str(m):
|
ofctl_v1_0: fix output of get_flow_stats
After applying this patch,
ofctl_v1_0:get_flow_stats outputs only match fields that no wildcard is set.
Execution example is as follows.
before applying this patch:
$curl http://127.0.0.1:8080/stats/flow/1
{
"1": [
{
"actions": [
"OUTPUT:1"
],
"byte_count": 238,
"cookie": 0,
"duration_nsec": 585000000,
"duration_sec": 154,
"hard_timeout": 0,
"idle_timeout": 0,
"match": {
"dl_dst": "00:00:00:00:00:01",
"dl_src": "00:00:00:00:00:00",
"dl_type": 0,
"dl_vlan": 0,
"dl_vlan_pcp": 0,
"in_port": 2,
"nw_dst": "0.0.0.0",
"nw_proto": 0,
"nw_src": "0.0.0.0",
"nw_tos": 0,
"tp_dst": 0,
"tp_src": 0
},
"packet_count": 3,
"priority": 32768,
"table_id": 0
}
]
}
after applying this patch:
$curl http://127.0.0.1:8080/stats/flow/1
{
"1": [
{
"actions": [
"OUTPUT:1"
],
"byte_count": 238,
"cookie": 0,
"duration_nsec": 593000000,
"duration_sec": 12,
"hard_timeout": 0,
"idle_timeout": 0,
"match": {
"dl_dst": "00:00:00:00:00:01",
"in_port": 2
},
"packet_count": 3,
"priority": 32768,
"table_id": 0
}
]
}
Reported-by:Liu, Weijie <wliu43@illinois.edu>
Signed-off-by: Minoru TAKAHASHI <takahashi.minoru7@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
2015-06-09 09:55:07 +09:00
|
|
|
|
|
|
|
match = {}
|
|
|
|
|
|
|
|
if ~m.wildcards & ofproto_v1_0.OFPFW_IN_PORT:
|
2016-01-19 13:46:10 +09:00
|
|
|
match['in_port'] = UTIL.ofp_port_to_user(m.in_port)
|
ofctl_v1_0: fix output of get_flow_stats
After applying this patch,
ofctl_v1_0:get_flow_stats outputs only match fields that no wildcard is set.
Execution example is as follows.
before applying this patch:
$curl http://127.0.0.1:8080/stats/flow/1
{
"1": [
{
"actions": [
"OUTPUT:1"
],
"byte_count": 238,
"cookie": 0,
"duration_nsec": 585000000,
"duration_sec": 154,
"hard_timeout": 0,
"idle_timeout": 0,
"match": {
"dl_dst": "00:00:00:00:00:01",
"dl_src": "00:00:00:00:00:00",
"dl_type": 0,
"dl_vlan": 0,
"dl_vlan_pcp": 0,
"in_port": 2,
"nw_dst": "0.0.0.0",
"nw_proto": 0,
"nw_src": "0.0.0.0",
"nw_tos": 0,
"tp_dst": 0,
"tp_src": 0
},
"packet_count": 3,
"priority": 32768,
"table_id": 0
}
]
}
after applying this patch:
$curl http://127.0.0.1:8080/stats/flow/1
{
"1": [
{
"actions": [
"OUTPUT:1"
],
"byte_count": 238,
"cookie": 0,
"duration_nsec": 593000000,
"duration_sec": 12,
"hard_timeout": 0,
"idle_timeout": 0,
"match": {
"dl_dst": "00:00:00:00:00:01",
"in_port": 2
},
"packet_count": 3,
"priority": 32768,
"table_id": 0
}
]
}
Reported-by:Liu, Weijie <wliu43@illinois.edu>
Signed-off-by: Minoru TAKAHASHI <takahashi.minoru7@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
2015-06-09 09:55:07 +09:00
|
|
|
|
|
|
|
if ~m.wildcards & ofproto_v1_0.OFPFW_DL_SRC:
|
|
|
|
match['dl_src'] = haddr_to_str(m.dl_src)
|
|
|
|
|
|
|
|
if ~m.wildcards & ofproto_v1_0.OFPFW_DL_DST:
|
|
|
|
match['dl_dst'] = haddr_to_str(m.dl_dst)
|
|
|
|
|
|
|
|
if ~m.wildcards & ofproto_v1_0.OFPFW_DL_VLAN:
|
|
|
|
match['dl_vlan'] = m.dl_vlan
|
|
|
|
|
|
|
|
if ~m.wildcards & ofproto_v1_0.OFPFW_DL_VLAN_PCP:
|
|
|
|
match['dl_vlan_pcp'] = m.dl_vlan_pcp
|
|
|
|
|
|
|
|
if ~m.wildcards & ofproto_v1_0.OFPFW_DL_TYPE:
|
|
|
|
match['dl_type'] = m.dl_type
|
|
|
|
|
|
|
|
if ~m.wildcards & ofproto_v1_0.OFPFW_NW_TOS:
|
|
|
|
match['nw_tos'] = m.nw_tos
|
|
|
|
|
|
|
|
if ~m.wildcards & ofproto_v1_0.OFPFW_NW_PROTO:
|
|
|
|
match['nw_proto'] = m.nw_proto
|
|
|
|
|
|
|
|
if ~m.wildcards & ofproto_v1_0.OFPFW_NW_SRC_ALL:
|
|
|
|
match['nw_src'] = nw_src_to_str(m.wildcards, m.nw_src)
|
|
|
|
|
|
|
|
if ~m.wildcards & ofproto_v1_0.OFPFW_NW_DST_ALL:
|
|
|
|
match['nw_dst'] = nw_dst_to_str(m.wildcards, m.nw_dst)
|
|
|
|
|
|
|
|
if ~m.wildcards & ofproto_v1_0.OFPFW_TP_SRC:
|
|
|
|
match['tp_src'] = m.tp_src
|
|
|
|
|
|
|
|
if ~m.wildcards & ofproto_v1_0.OFPFW_TP_DST:
|
|
|
|
match['tp_dst'] = m.tp_dst
|
|
|
|
|
|
|
|
return match
|
2012-11-25 22:38:28 +09:00
|
|
|
|
|
|
|
|
2013-03-21 18:02:19 +09:00
|
|
|
def nw_src_to_str(wildcards, addr):
|
|
|
|
ip = socket.inet_ntoa(struct.pack('!I', addr))
|
2016-03-29 19:18:24 +00:00
|
|
|
mask = 32 - ((wildcards & ofproto_v1_0.OFPFW_NW_SRC_MASK) >>
|
|
|
|
ofproto_v1_0.OFPFW_NW_SRC_SHIFT)
|
2013-03-21 18:02:19 +09:00
|
|
|
if mask == 32:
|
|
|
|
mask = 0
|
|
|
|
if mask:
|
|
|
|
ip += '/%d' % mask
|
|
|
|
return ip
|
|
|
|
|
|
|
|
|
|
|
|
def nw_dst_to_str(wildcards, addr):
|
|
|
|
ip = socket.inet_ntoa(struct.pack('!I', addr))
|
2016-03-29 19:18:24 +00:00
|
|
|
mask = 32 - ((wildcards & ofproto_v1_0.OFPFW_NW_DST_MASK) >>
|
|
|
|
ofproto_v1_0.OFPFW_NW_DST_SHIFT)
|
2013-03-21 18:02:19 +09:00
|
|
|
if mask == 32:
|
|
|
|
mask = 0
|
|
|
|
if mask:
|
|
|
|
ip += '/%d' % mask
|
|
|
|
return ip
|
|
|
|
|
|
|
|
|
2012-09-03 18:46:40 +09:00
|
|
|
def get_desc_stats(dp, waiters):
|
|
|
|
stats = dp.ofproto_parser.OFPDescStatsRequest(dp, 0)
|
|
|
|
msgs = []
|
2016-03-29 19:18:35 +00:00
|
|
|
ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
|
2016-03-25 16:58:24 +09:00
|
|
|
s = {}
|
2012-09-03 18:46:40 +09:00
|
|
|
|
|
|
|
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}
|
2016-08-08 16:49:40 +09:00
|
|
|
|
|
|
|
return {str(dp.id): s}
|
2012-09-03 18:46:40 +09:00
|
|
|
|
|
|
|
|
2016-03-22 09:51:45 +09:00
|
|
|
def get_queue_stats(dp, waiters, port=None, queue_id=None):
|
|
|
|
if port is None:
|
|
|
|
port = dp.ofproto.OFPP_ALL
|
|
|
|
else:
|
|
|
|
port = int(str(port), 0)
|
|
|
|
|
|
|
|
if queue_id is None:
|
|
|
|
queue_id = dp.ofproto.OFPQ_ALL
|
|
|
|
else:
|
|
|
|
queue_id = int(str(queue_id), 0)
|
|
|
|
|
|
|
|
stats = dp.ofproto_parser.OFPQueueStatsRequest(dp, 0, port,
|
|
|
|
queue_id)
|
ofctl_rest: support OFPQueueStats message
this patch makes ofctl_rest enable use of OFPQueueStats message.
usage)
URI: /stats/queue/<dpid>
method: GET
e.g.)
$ curl -X GET http://localhost:8080/stats/queue/1
{
"1": [
{
"port_no": 1,
"queue_id": 0,
"tx_bytes": 0,
"tx_packets": 0,
"tx_errors": 0,
"duration_sec": 4294963425,
"duration_nsec": 3912967296
},
{
"port_no": 1,
"queue_id": 1,
"tx_bytes": 0,
"tx_packets": 0,
"tx_errors": 0,
"duration_sec": 4294963425,
"duration_nsec": 3912967296
}
]
}
NOTE: The "duration_sec" and "duration_nsec" fields are for OF1.3(or later).
Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
2015-01-19 10:45:10 +09:00
|
|
|
msgs = []
|
2016-03-29 19:18:35 +00:00
|
|
|
ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
|
ofctl_rest: support OFPQueueStats message
this patch makes ofctl_rest enable use of OFPQueueStats message.
usage)
URI: /stats/queue/<dpid>
method: GET
e.g.)
$ curl -X GET http://localhost:8080/stats/queue/1
{
"1": [
{
"port_no": 1,
"queue_id": 0,
"tx_bytes": 0,
"tx_packets": 0,
"tx_errors": 0,
"duration_sec": 4294963425,
"duration_nsec": 3912967296
},
{
"port_no": 1,
"queue_id": 1,
"tx_bytes": 0,
"tx_packets": 0,
"tx_errors": 0,
"duration_sec": 4294963425,
"duration_nsec": 3912967296
}
]
}
NOTE: The "duration_sec" and "duration_nsec" fields are for OF1.3(or later).
Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
2015-01-19 10:45:10 +09:00
|
|
|
|
|
|
|
s = []
|
|
|
|
for msg in msgs:
|
|
|
|
stats = msg.body
|
|
|
|
for stat in stats:
|
|
|
|
s.append({'port_no': stat.port_no,
|
|
|
|
'queue_id': stat.queue_id,
|
|
|
|
'tx_bytes': stat.tx_bytes,
|
|
|
|
'tx_errors': stat.tx_errors,
|
|
|
|
'tx_packets': stat.tx_packets})
|
2016-08-08 16:49:40 +09:00
|
|
|
|
|
|
|
return {str(dp.id): s}
|
ofctl_rest: support OFPQueueStats message
this patch makes ofctl_rest enable use of OFPQueueStats message.
usage)
URI: /stats/queue/<dpid>
method: GET
e.g.)
$ curl -X GET http://localhost:8080/stats/queue/1
{
"1": [
{
"port_no": 1,
"queue_id": 0,
"tx_bytes": 0,
"tx_packets": 0,
"tx_errors": 0,
"duration_sec": 4294963425,
"duration_nsec": 3912967296
},
{
"port_no": 1,
"queue_id": 1,
"tx_bytes": 0,
"tx_packets": 0,
"tx_errors": 0,
"duration_sec": 4294963425,
"duration_nsec": 3912967296
}
]
}
NOTE: The "duration_sec" and "duration_nsec" fields are for OF1.3(or later).
Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
2015-01-19 10:45:10 +09:00
|
|
|
|
|
|
|
|
2015-12-24 16:48:07 +09:00
|
|
|
def get_flow_stats(dp, waiters, flow=None):
|
|
|
|
flow = flow if flow else {}
|
2014-08-20 14:27:19 +09:00
|
|
|
match = to_match(dp, flow.get('match', {}))
|
2016-01-19 13:46:10 +09:00
|
|
|
table_id = UTIL.ofp_table_from_user(
|
|
|
|
flow.get('table_id', 0xff))
|
|
|
|
out_port = UTIL.ofp_port_from_user(
|
|
|
|
flow.get('out_port', dp.ofproto.OFPP_NONE))
|
2016-12-08 16:49:00 +09:00
|
|
|
# Note: OpenFlow does not allow to filter flow entries by priority,
|
|
|
|
# but for efficiency, ofctl provides the way to do it.
|
|
|
|
priority = int(flow.get('priority', -1))
|
2014-08-20 14:27:19 +09:00
|
|
|
|
2012-09-03 18:46:40 +09:00
|
|
|
stats = dp.ofproto_parser.OFPFlowStatsRequest(
|
2014-08-20 14:27:19 +09:00
|
|
|
dp, 0, match, table_id, out_port)
|
|
|
|
|
2012-09-03 18:46:40 +09:00
|
|
|
msgs = []
|
2016-03-29 19:18:35 +00:00
|
|
|
ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
|
2012-09-03 18:46:40 +09:00
|
|
|
|
|
|
|
flows = []
|
|
|
|
for msg in msgs:
|
|
|
|
for stats in msg.body:
|
2016-12-08 16:49:00 +09:00
|
|
|
if 0 <= priority != stats.priority:
|
|
|
|
continue
|
|
|
|
|
2012-11-25 22:38:28 +09:00
|
|
|
actions = actions_to_str(stats.actions)
|
|
|
|
match = match_to_str(stats.match)
|
2012-11-04 23:13:02 +09:00
|
|
|
|
2012-09-03 18:46:40 +09:00
|
|
|
s = {'priority': stats.priority,
|
|
|
|
'cookie': stats.cookie,
|
|
|
|
'idle_timeout': stats.idle_timeout,
|
|
|
|
'hard_timeout': stats.hard_timeout,
|
2012-11-04 23:13:02 +09:00
|
|
|
'actions': actions,
|
2012-11-25 22:38:28 +09:00
|
|
|
'match': match,
|
2012-09-03 18:46:40 +09:00
|
|
|
'byte_count': stats.byte_count,
|
|
|
|
'duration_sec': stats.duration_sec,
|
|
|
|
'duration_nsec': stats.duration_nsec,
|
|
|
|
'packet_count': stats.packet_count,
|
2016-01-19 13:46:10 +09:00
|
|
|
'table_id': UTIL.ofp_table_to_user(stats.table_id)}
|
2012-09-03 18:46:40 +09:00
|
|
|
flows.append(s)
|
2016-08-08 16:49:40 +09:00
|
|
|
|
|
|
|
return {str(dp.id): flows}
|
2012-09-03 18:46:40 +09:00
|
|
|
|
|
|
|
|
2015-12-24 16:48:07 +09:00
|
|
|
def get_aggregate_flow_stats(dp, waiters, flow=None):
|
|
|
|
flow = flow if flow else {}
|
2015-01-19 10:56:23 +09:00
|
|
|
match = to_match(dp, flow.get('match', {}))
|
2016-01-19 13:46:10 +09:00
|
|
|
table_id = UTIL.ofp_table_from_user(
|
|
|
|
flow.get('table_id', 0xff))
|
|
|
|
out_port = UTIL.ofp_port_from_user(
|
|
|
|
flow.get('out_port', dp.ofproto.OFPP_NONE))
|
2015-01-19 10:56:23 +09:00
|
|
|
|
|
|
|
stats = dp.ofproto_parser.OFPAggregateStatsRequest(
|
|
|
|
dp, 0, match, table_id, out_port)
|
|
|
|
|
|
|
|
msgs = []
|
2016-03-29 19:18:35 +00:00
|
|
|
ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
|
2015-01-19 10:56:23 +09:00
|
|
|
|
|
|
|
flows = []
|
|
|
|
for msg in msgs:
|
|
|
|
stats = msg.body
|
|
|
|
for st in stats:
|
|
|
|
s = {'packet_count': st.packet_count,
|
|
|
|
'byte_count': st.byte_count,
|
|
|
|
'flow_count': st.flow_count}
|
2016-03-25 16:58:24 +09:00
|
|
|
flows.append(s)
|
2015-01-19 10:56:23 +09:00
|
|
|
|
2016-08-08 16:49:40 +09:00
|
|
|
return {str(dp.id): flows}
|
2015-01-19 10:56:23 +09:00
|
|
|
|
|
|
|
|
2015-10-22 17:31:33 +09:00
|
|
|
def get_table_stats(dp, waiters):
|
|
|
|
stats = dp.ofproto_parser.OFPTableStatsRequest(dp, 0)
|
|
|
|
ofp = dp.ofproto
|
|
|
|
msgs = []
|
2016-03-29 19:18:35 +00:00
|
|
|
ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
|
2015-10-22 17:31:33 +09:00
|
|
|
|
|
|
|
match_convert = {ofp.OFPFW_IN_PORT: 'IN_PORT',
|
|
|
|
ofp.OFPFW_DL_VLAN: 'DL_VLAN',
|
|
|
|
ofp.OFPFW_DL_SRC: 'DL_SRC',
|
|
|
|
ofp.OFPFW_DL_DST: 'DL_DST',
|
|
|
|
ofp.OFPFW_DL_TYPE: 'DL_TYPE',
|
|
|
|
ofp.OFPFW_NW_PROTO: 'NW_PROTO',
|
|
|
|
ofp.OFPFW_TP_SRC: 'TP_SRC',
|
|
|
|
ofp.OFPFW_TP_DST: 'TP_DST',
|
|
|
|
ofp.OFPFW_NW_SRC_SHIFT: 'NW_SRC_SHIFT',
|
|
|
|
ofp.OFPFW_NW_SRC_BITS: 'NW_SRC_BITS',
|
|
|
|
ofp.OFPFW_NW_SRC_MASK: 'NW_SRC_MASK',
|
|
|
|
ofp.OFPFW_NW_SRC: 'NW_SRC',
|
|
|
|
ofp.OFPFW_NW_SRC_ALL: 'NW_SRC_ALL',
|
|
|
|
ofp.OFPFW_NW_DST_SHIFT: 'NW_DST_SHIFT',
|
|
|
|
ofp.OFPFW_NW_DST_BITS: 'NW_DST_BITS',
|
|
|
|
ofp.OFPFW_NW_DST_MASK: 'NW_DST_MASK',
|
|
|
|
ofp.OFPFW_NW_DST: 'NW_DST',
|
|
|
|
ofp.OFPFW_NW_DST_ALL: 'NW_DST_ALL',
|
|
|
|
ofp.OFPFW_DL_VLAN_PCP: 'DL_VLAN_PCP',
|
|
|
|
ofp.OFPFW_NW_TOS: 'NW_TOS',
|
|
|
|
ofp.OFPFW_ALL: 'ALL',
|
|
|
|
ofp.OFPFW_ICMP_TYPE: 'ICMP_TYPE',
|
|
|
|
ofp.OFPFW_ICMP_CODE: 'ICMP_CODE'}
|
|
|
|
|
|
|
|
tables = []
|
|
|
|
for msg in msgs:
|
|
|
|
stats = msg.body
|
|
|
|
for stat in stats:
|
|
|
|
wildcards = []
|
|
|
|
for k, v in match_convert.items():
|
|
|
|
if (1 << k) & stat.wildcards:
|
|
|
|
wildcards.append(v)
|
2016-01-19 13:46:10 +09:00
|
|
|
s = {'table_id': UTIL.ofp_table_to_user(stat.table_id),
|
2015-12-22 11:49:18 +09:00
|
|
|
'name': stat.name.decode('utf-8'),
|
2015-10-22 17:31:33 +09:00
|
|
|
'wildcards': wildcards,
|
|
|
|
'max_entries': stat.max_entries,
|
|
|
|
'active_count': stat.active_count,
|
|
|
|
'lookup_count': stat.lookup_count,
|
|
|
|
'matched_count': stat.matched_count}
|
|
|
|
tables.append(s)
|
|
|
|
|
2016-08-08 16:49:40 +09:00
|
|
|
return {str(dp.id): tables}
|
2015-10-22 17:31:33 +09:00
|
|
|
|
|
|
|
|
2016-03-22 09:51:41 +09:00
|
|
|
def get_port_stats(dp, waiters, port=None):
|
|
|
|
if port is None:
|
|
|
|
port = dp.ofproto.OFPP_NONE
|
|
|
|
else:
|
|
|
|
port = int(str(port), 0)
|
|
|
|
|
2012-09-03 18:46:40 +09:00
|
|
|
stats = dp.ofproto_parser.OFPPortStatsRequest(
|
2016-03-22 09:51:41 +09:00
|
|
|
dp, 0, port)
|
2012-09-03 18:46:40 +09:00
|
|
|
msgs = []
|
2016-03-29 19:18:35 +00:00
|
|
|
ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
|
2012-09-03 18:46:40 +09:00
|
|
|
|
|
|
|
ports = []
|
|
|
|
for msg in msgs:
|
|
|
|
for stats in msg.body:
|
2016-01-19 13:46:10 +09:00
|
|
|
s = {'port_no': UTIL.ofp_port_to_user(stats.port_no),
|
2012-09-03 18:46:40 +09:00
|
|
|
'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)
|
2016-08-08 16:49:40 +09:00
|
|
|
|
|
|
|
return {str(dp.id): ports}
|
2012-09-03 18:46:40 +09:00
|
|
|
|
|
|
|
|
ofctl_rest: enable getting Description of a port
this patch makes ofctl_rest enable getting Description of a port.
usage)
URI: /stats/portdesc/<dpid>
method: GET
e.g. )
curl http://localhost:8080/stats/portdesc/1
{"1": [{"hw_addr": "c6:d8:19:4a:e1:4f", "curr": 0, "supported": 0,
"max_speed": 0, "advertised": 0, "peer": 0,
"port_no": 4294967294, "curr_speed": 0, "name": "s1",
"state": 1, "config": 1},
{"hw_addr": "8e:96:a1:14:d8:a1", "curr": 2112, "supported": 0,
"max_speed": 0, "advertised": 0, "peer": 0,
"port_no": 1, "curr_speed": 10000000, "name": "s1-eth1",
"state": 0, "config": 0}]}
Signed-off-by: TAKAHASHI Minoru <takahashi.minoru7@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
2014-07-08 15:02:34 +09:00
|
|
|
def get_port_desc(dp, waiters):
|
|
|
|
|
|
|
|
stats = dp.ofproto_parser.OFPFeaturesRequest(dp)
|
|
|
|
msgs = []
|
2016-03-29 19:18:35 +00:00
|
|
|
ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
|
ofctl_rest: enable getting Description of a port
this patch makes ofctl_rest enable getting Description of a port.
usage)
URI: /stats/portdesc/<dpid>
method: GET
e.g. )
curl http://localhost:8080/stats/portdesc/1
{"1": [{"hw_addr": "c6:d8:19:4a:e1:4f", "curr": 0, "supported": 0,
"max_speed": 0, "advertised": 0, "peer": 0,
"port_no": 4294967294, "curr_speed": 0, "name": "s1",
"state": 1, "config": 1},
{"hw_addr": "8e:96:a1:14:d8:a1", "curr": 2112, "supported": 0,
"max_speed": 0, "advertised": 0, "peer": 0,
"port_no": 1, "curr_speed": 10000000, "name": "s1-eth1",
"state": 0, "config": 0}]}
Signed-off-by: TAKAHASHI Minoru <takahashi.minoru7@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
2014-07-08 15:02:34 +09:00
|
|
|
|
|
|
|
descs = []
|
|
|
|
for msg in msgs:
|
|
|
|
stats = msg.ports
|
|
|
|
for stat in stats.values():
|
2016-01-19 13:46:10 +09:00
|
|
|
d = {'port_no': UTIL.ofp_port_to_user(stat.port_no),
|
ofctl_rest: enable getting Description of a port
this patch makes ofctl_rest enable getting Description of a port.
usage)
URI: /stats/portdesc/<dpid>
method: GET
e.g. )
curl http://localhost:8080/stats/portdesc/1
{"1": [{"hw_addr": "c6:d8:19:4a:e1:4f", "curr": 0, "supported": 0,
"max_speed": 0, "advertised": 0, "peer": 0,
"port_no": 4294967294, "curr_speed": 0, "name": "s1",
"state": 1, "config": 1},
{"hw_addr": "8e:96:a1:14:d8:a1", "curr": 2112, "supported": 0,
"max_speed": 0, "advertised": 0, "peer": 0,
"port_no": 1, "curr_speed": 10000000, "name": "s1-eth1",
"state": 0, "config": 0}]}
Signed-off-by: TAKAHASHI Minoru <takahashi.minoru7@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
2014-07-08 15:02:34 +09:00
|
|
|
'hw_addr': stat.hw_addr,
|
2015-12-22 11:49:18 +09:00
|
|
|
'name': stat.name.decode('utf-8'),
|
ofctl_rest: enable getting Description of a port
this patch makes ofctl_rest enable getting Description of a port.
usage)
URI: /stats/portdesc/<dpid>
method: GET
e.g. )
curl http://localhost:8080/stats/portdesc/1
{"1": [{"hw_addr": "c6:d8:19:4a:e1:4f", "curr": 0, "supported": 0,
"max_speed": 0, "advertised": 0, "peer": 0,
"port_no": 4294967294, "curr_speed": 0, "name": "s1",
"state": 1, "config": 1},
{"hw_addr": "8e:96:a1:14:d8:a1", "curr": 2112, "supported": 0,
"max_speed": 0, "advertised": 0, "peer": 0,
"port_no": 1, "curr_speed": 10000000, "name": "s1-eth1",
"state": 0, "config": 0}]}
Signed-off-by: TAKAHASHI Minoru <takahashi.minoru7@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
2014-07-08 15:02:34 +09:00
|
|
|
'config': stat.config,
|
|
|
|
'state': stat.state,
|
|
|
|
'curr': stat.curr,
|
|
|
|
'advertised': stat.advertised,
|
|
|
|
'supported': stat.supported,
|
|
|
|
'peer': stat.peer}
|
|
|
|
descs.append(d)
|
2016-08-08 16:49:40 +09:00
|
|
|
|
|
|
|
return {str(dp.id): descs}
|
ofctl_rest: enable getting Description of a port
this patch makes ofctl_rest enable getting Description of a port.
usage)
URI: /stats/portdesc/<dpid>
method: GET
e.g. )
curl http://localhost:8080/stats/portdesc/1
{"1": [{"hw_addr": "c6:d8:19:4a:e1:4f", "curr": 0, "supported": 0,
"max_speed": 0, "advertised": 0, "peer": 0,
"port_no": 4294967294, "curr_speed": 0, "name": "s1",
"state": 1, "config": 1},
{"hw_addr": "8e:96:a1:14:d8:a1", "curr": 2112, "supported": 0,
"max_speed": 0, "advertised": 0, "peer": 0,
"port_no": 1, "curr_speed": 10000000, "name": "s1-eth1",
"state": 0, "config": 0}]}
Signed-off-by: TAKAHASHI Minoru <takahashi.minoru7@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
2014-07-08 15:02:34 +09:00
|
|
|
|
|
|
|
|
2012-12-11 06:13:37 +09:00
|
|
|
def mod_flow_entry(dp, flow, cmd):
|
2012-09-03 18:46:40 +09:00
|
|
|
cookie = int(flow.get('cookie', 0))
|
|
|
|
priority = int(flow.get('priority',
|
|
|
|
dp.ofproto.OFP_DEFAULT_PRIORITY))
|
2016-01-19 13:46:10 +09:00
|
|
|
buffer_id = UTIL.ofp_buffer_from_user(
|
|
|
|
flow.get('buffer_id', dp.ofproto.OFP_NO_BUFFER))
|
|
|
|
out_port = UTIL.ofp_port_from_user(
|
|
|
|
flow.get('out_port', dp.ofproto.OFPP_NONE))
|
2012-09-03 18:46:40 +09:00
|
|
|
flags = int(flow.get('flags', 0))
|
|
|
|
idle_timeout = int(flow.get('idle_timeout', 0))
|
|
|
|
hard_timeout = int(flow.get('hard_timeout', 0))
|
2013-08-08 17:51:54 +09:00
|
|
|
actions = to_actions(dp, flow.get('actions', []))
|
2012-09-03 18:46:40 +09:00
|
|
|
match = to_match(dp, flow.get('match', {}))
|
|
|
|
|
|
|
|
flow_mod = dp.ofproto_parser.OFPFlowMod(
|
|
|
|
datapath=dp, match=match, cookie=cookie,
|
2012-12-11 06:13:37 +09:00
|
|
|
command=cmd, idle_timeout=idle_timeout,
|
2014-09-11 14:49:19 +09:00
|
|
|
hard_timeout=hard_timeout, priority=priority,
|
|
|
|
buffer_id=buffer_id, out_port=out_port,
|
|
|
|
flags=flags,
|
2012-09-03 18:46:40 +09:00
|
|
|
actions=actions)
|
|
|
|
|
2016-03-29 19:18:34 +00:00
|
|
|
ofctl_utils.send_msg(dp, flow_mod, LOG)
|
2012-09-03 18:46:40 +09:00
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
2016-03-29 19:18:34 +00:00
|
|
|
ofctl_utils.send_msg(dp, flow_mod, LOG)
|
2014-07-08 15:00:51 +09:00
|
|
|
|
|
|
|
|
|
|
|
def mod_port_behavior(dp, port_config):
|
2016-01-19 13:46:10 +09:00
|
|
|
port_no = UTIL.ofp_port_from_user(port_config.get('port_no', 0))
|
2016-01-18 10:53:09 +09:00
|
|
|
hw_addr = str(port_config.get('hw_addr'))
|
2014-07-08 15:00:51 +09:00
|
|
|
config = int(port_config.get('config', 0))
|
|
|
|
mask = int(port_config.get('mask', 0))
|
|
|
|
advertise = int(port_config.get('advertise'))
|
|
|
|
|
|
|
|
port_mod = dp.ofproto_parser.OFPPortMod(
|
|
|
|
dp, port_no, hw_addr, config, mask, advertise)
|
|
|
|
|
2016-03-29 19:18:34 +00:00
|
|
|
ofctl_utils.send_msg(dp, port_mod, LOG)
|