Stats Improvement
diff --git a/cli/cli/c_actions.py b/cli/cli/c_actions.py
index e06819b..127c843 100755
--- a/cli/cli/c_actions.py
+++ b/cli/cli/c_actions.py
@@ -37,6 +37,7 @@
from midw import *
from vnsw import *
+from html5lib.constants import DataLossWarning
onos=1
#
@@ -1948,8 +1949,9 @@
entries = json.loads(result)
+ #if 'realtimestats' in data and data['realtimestats'] == 'group':
+
entries2 = None
-
if 'realtimestats' in data and data['realtimestats'] == 'group':
url2 = "http://%s/rest/v1/" % sdnsh.controller + ("realtimestats/groupdesc/%(dpid)s/" % data)
result2 = sdnsh.store.rest_simple_request(url2)
@@ -1973,6 +1975,80 @@
data,
entries2)
+ if 'realtimestats' in data and 'tabletype' in data and data['realtimestats'] == 'table':
+ combResult = []
+ if data['tabletype'] == 'ip':
+ for ipTableEntry in entries:
+ match = ipTableEntry['match']
+ if match :
+ networkDestination = match[0].get('networkDestination') if match[0].get('networkDestination') else '*'
+ #raise error.ArgumentValidationError('\n\n\n %s' %match)
+ #else:
+ # networkSource = None
+ # networkDestination = None
+ combResult.append({
+ 'switch' : ipTableEntry['switch'],
+ 'byteCount' : ipTableEntry['byteCount'],
+ 'packetCount' : ipTableEntry['packetCount'],
+ 'cookie' : ipTableEntry['cookie'],
+ 'durationSeconds' : ipTableEntry['durationSec'],
+ 'networkDestination' : networkDestination,
+ })
+ elif data['tabletype'] == 'mpls':
+ for ipTableEntry in entries:
+ match = ipTableEntry['match']
+ if match :
+ mplsTc = match[0].get('mplsTc')
+ mplsLabel = match[0].get('mplsLabel')
+ #raise error.ArgumentValidationError('\n\n\n %s' %match)
+ #else:
+ # networkSource = None
+ # networkDestination = None
+ combResult.append({
+ 'switch' : ipTableEntry['switch'],
+ 'byteCount' : ipTableEntry['byteCount'],
+ 'packetCount' : ipTableEntry['packetCount'],
+ 'cookie' : ipTableEntry['cookie'],
+ 'mplsTc' : mplsTc,
+ 'mplsLabel' : mplsLabel,
+ 'durationSeconds' : ipTableEntry['durationSec']
+ })
+ elif data['tabletype'] == 'acl':
+ for ipTableEntry in entries:
+ match = ipTableEntry['match']
+ if match :
+ networkDestination = match[0].get('networkDestination')\
+ if match[0].get('networkDestination') else '*'
+ networkProtocol = match[0].get('networkProtocol') if match[0].get('networkProtocol') else '*'
+ networkSource = match[0].get('networkSource') if match[0].get('networkSource') else '*'
+ mplsTc = match[0].get('mplsTc') if match[0].get('mplsTc') else '*'
+ mplsLabel = match[0].get('mplsLabel')if match[0].get('mplsLabel') else '*'
+ transportDestination = match[0].get('transportDestination') if match[0].get('transportDestination') else '*'
+ transportSource = match[0].get('transportSource') if match[0].get('transportSource') else '*'
+ inputPort = match[0].get('inputPort') if match[0].get('inputPort') else '*'
+ dataLayerSource = match[0].get('dataLayerSource') if match[0].get('dataLayerSource') else '*'
+ dataLayerDestination = match[0].get('dataLayerDestination') if match[0].get('dataLayerDestination') else '*'
+ dataLayerType= match[0].get('dataLayerType') if match[0].get('dataLayerType') else '*'
+ combResult.append({
+ 'switch' : ipTableEntry['switch'],
+ 'byteCount' : ipTableEntry['byteCount'],
+ 'packetCount' : ipTableEntry['packetCount'],
+ 'cookie' : ipTableEntry['cookie'],
+ 'inputPort' : inputPort,
+ 'durationSeconds' : ipTableEntry['durationSec'],
+ 'networkSource' : networkSource,
+ 'networkDestination' : networkDestination,
+ 'networkProtocol' : networkProtocol,
+ 'dataLayerType' : dataLayerType,
+ 'dataLayerSource' : dataLayerSource,
+ 'dataLayerDestination' : dataLayerDestination,
+ 'mplsTc' : mplsTc,
+ 'mplsLabel' : mplsLabel,
+ 'transportDestination' : transportDestination,
+ 'transportSource' : transportSource
+ })
+ entries = combResult
+
if 'realtimestats' in data and data['realtimestats'] == 'group':
combResult = []
for groupStatEntry in entries:
diff --git a/cli/cli/desc/version200/core.py b/cli/cli/desc/version200/core.py
index cca3240..8c56945 100755
--- a/cli/cli/desc/version200/core.py
+++ b/cli/cli/desc/version200/core.py
@@ -1700,7 +1700,7 @@
'Idx', 'switch', 'cookie',
'byteCount', 'packetCount',
'actions', 'dataLayerSource', 'dataLayerDestination',
- 'flow-brief',
+ 'flow-brief',
],
'scoped' : [
'Idx', 'cookie',
@@ -1817,6 +1817,386 @@
},
}
+REALTIME_TABLE_IP_FLOW_FORMAT = {
+ 'realtime_table_ip_flow' : {
+ 'field-orderings' : {
+ 'default' : [
+ 'Idx', 'switch', 'cookie',
+ 'byteCount', 'packetCount',
+ 'actions', 'networkDestination',
+ 'flow-brief',
+ ],
+ 'scoped' : [
+ 'Idx', 'switch', 'byteCount', 'packetCount', 'durationSeconds',
+ 'cookie',
+ 'networkDestination',
+ ],
+ 'brief' : [ 'Idx', 'switch', 'byteCount', 'packetCount', 'durationSeconds',
+ 'cookie',
+ 'networkDestination'
+ ],
+ 'default' : [ 'Idx', 'switch', 'byteCount', 'packetCount', 'durationSeconds',
+ 'cookie',
+ 'networkDestination'
+ ],
+ 'scoped' : [ 'Idx', 'switch', 'byteCount', 'packetCount', 'durationSeconds',
+ 'cookie',
+ 'networkDestination'
+ ],
+ 'details' : [ 'Idx', 'switch', 'byteCount', 'packetCount', 'durationSeconds',
+ 'cookie',
+ 'networkDestination'
+ ],
+ #'vns_flow': [ 'Idx', 'dataLayerSource', 'dataLayerDestination', 'dataLayerVirtualLan', 'dataLayerType'],
+ #'summary' : [ 'Idx', 'vnsName', 'vnsFlowCnt', 'flowEntryCnt'],
+ },
+ 'fields': {
+ 'switch' : { 'verbose-name' : 'Switch',
+ 'formatter' : fmtcnv.replace_switch_with_alias
+ },
+ 'flow-brief' : {
+ 'verbose-name' : 'Match',
+ 'formatter' : fmtcnv.realtime_flow_brief,
+ },
+ 'flow-timeout' : {
+ 'verbose-name' : 'H/I',
+ 'formatter' : realtime_flow_timeout,
+ },
+ 'byteCount' : { 'verbose-name': 'Bytes',
+ 'primary_key':True
+ },
+ 'packetCount' : { 'verbose-name' : 'Packets'
+ },
+ 'cookie' : { 'verbose-name' : 'Cookie'#,
+ #'formatter' : fmtcnv.decode_flow_cookie,
+ },
+ 'durationSeconds' : { 'verbose-name' : 'Dur(s)'
+ },
+ 'durationNanoseconds' : { 'verbose-name' : 'Dur(ns)'
+ },
+ 'hardTimeout' : { 'verbose-name' : 'Hard Timeout',
+ 'formatter' : fmtcnv.convert_signed_short_to_unsigned
+ },
+ 'idleTimeout' : { 'verbose-name' : 'Idle Timeout',
+ 'formatter' : fmtcnv.convert_signed_short_to_unsigned
+ },
+ 'length' : { 'verbose-name' : 'Length'
+ },
+ 'priority' : { 'verbose-name' : 'Priority',
+ 'formatter' : fmtcnv.convert_signed_short_to_unsigned
+ },
+ 'tableId' : { 'verbose-name' : 'Table' },
+ 'wildcards' : { 'verbose-name' : 'Wildcards',
+ 'formatter' : fmtcnv.convert_integer_to_bitmask
+ },
+ 'dataLayerSource' : { 'verbose-name' : 'Src MAC',
+ 'formatter' : fmtcnv.replace_host_with_alias
+ },
+ 'dataLayerDestination' : { 'verbose-name' : 'Dst MAC',
+ 'formatter' : fmtcnv.replace_host_with_alias
+ },
+ 'dataLayerType' : { 'verbose-name' : 'Ether Type',
+ 'formatter' : fmtcnv.decode_ether_type
+ },
+ 'dataLayerVirtualLan' : { 'verbose-name' : 'VLAN ID',
+ 'formatter' : fmtcnv.convert_signed_short_to_unsigned
+ },
+ 'dataLayerVirtualLanPriorityCodePoint' : { 'verbose-name' : 'VLAN PCP'
+ },
+ 'inputPort' : { 'verbose-name' : 'In Port',
+ 'formatter' : fmtcnv.decode_openflow_port
+ },
+ 'networkSource' : { 'verbose-name' : 'Src IP'
+ },
+ 'networkDestination' : { 'verbose-name' : 'Dst IP'
+ },
+ 'networkSourceMaskLen' : { 'verbose-name' : 'Src IP Bits'
+ },
+ 'networkDestinationMaskLen' : { 'verbose-name' : 'Dst IP Bits'
+ },
+ 'networkProtocol' : { 'verbose-name' : 'Protocol',
+ 'formatter' : fmtcnv.decode_network_protocol
+ },
+ 'networkTypeOfService' : { 'verbose-name' : 'TOS Bits'
+ },
+ 'transportSource' : { 'verbose-name' : 'Src Port',
+ 'formatter' : fmtcnv.decode_src_port
+ },
+ 'transportDestination' : { 'verbose-name' : 'Dst Port',
+ 'formatter' : fmtcnv.decode_dst_port
+ },
+ 'actions' : { 'verbose-name' : 'Actions',
+ 'formatter' : fmtcnv.decode_actions
+ },
+ 'vnsName' : { 'verbose-name' : 'VNS'
+ },
+ 'vnsFlowCnt' : { 'verbose-name' : 'Flows'
+ },
+ 'flowEntryCnt' : { 'verbose-name' : 'Flow-Entries'
+ },
+ }
+ },
+}
+
+
+
+REALTIME_TABLE_MPLS_FLOW_FORMAT = {
+ 'realtime_table_mpls_flow' : {
+ 'field-orderings' : {
+ 'default' : [
+ 'Idx', 'switch', 'cookie',
+ 'byteCount', 'packetCount',
+ 'actions', 'mplsTc', 'mplsLabel',
+ 'flow-brief',
+ ],
+ 'scoped' : [
+ 'Idx', 'switch', 'byteCount', 'packetCount', 'durationSeconds',
+ 'cookie',
+ 'mplsTc', 'mplsLabel'
+ ],
+ 'brief' : [ 'Idx', 'switch', 'byteCount', 'packetCount', 'durationSeconds',
+ 'cookie',
+ 'mplsTc', 'mplsLabel'
+ ],
+ 'default' : [ 'Idx', 'switch', 'byteCount', 'packetCount', 'durationSeconds',
+ 'cookie',
+ 'mplsTc', 'mplsLabel'
+ ],
+ 'scoped' : [ 'Idx', 'switch', 'byteCount', 'packetCount', 'durationSeconds',
+ 'cookie',
+ 'mplsTc', 'mplsLabel'
+ ],
+ 'details' : [ 'Idx', 'switch', 'byteCount', 'packetCount', 'durationSeconds',
+ 'cookie',
+ 'mplsTc', 'mplsLabel'
+ ],
+ #'vns_flow': [ 'Idx', 'dataLayerSource', 'dataLayerDestination', 'dataLayerVirtualLan', 'dataLayerType'],
+ #'summary' : [ 'Idx', 'vnsName', 'vnsFlowCnt', 'flowEntryCnt'],
+ },
+ 'fields': {
+ 'switch' : { 'verbose-name' : 'Switch',
+ 'formatter' : fmtcnv.replace_switch_with_alias
+ },
+ 'flow-brief' : {
+ 'verbose-name' : 'Match',
+ 'formatter' : fmtcnv.realtime_flow_brief,
+ },
+ 'flow-timeout' : {
+ 'verbose-name' : 'H/I',
+ 'formatter' : realtime_flow_timeout,
+ },
+ 'byteCount' : { 'verbose-name': 'Bytes',
+ 'primary_key':True
+ },
+ 'packetCount' : { 'verbose-name' : 'Packets'
+ },
+ 'cookie' : { 'verbose-name' : 'Cookie',
+ #'formatter' : fmtcnv.decode_flow_cookie,
+ },
+ 'durationSeconds' : { 'verbose-name' : 'Dur(s)'
+ },
+ 'durationNanoseconds' : { 'verbose-name' : 'Dur(ns)'
+ },
+ 'hardTimeout' : { 'verbose-name' : 'Hard Timeout',
+ 'formatter' : fmtcnv.convert_signed_short_to_unsigned
+ },
+ 'idleTimeout' : { 'verbose-name' : 'Idle Timeout',
+ 'formatter' : fmtcnv.convert_signed_short_to_unsigned
+ },
+ 'length' : { 'verbose-name' : 'Length'
+ },
+ 'priority' : { 'verbose-name' : 'Priority',
+ 'formatter' : fmtcnv.convert_signed_short_to_unsigned
+ },
+ 'tableId' : { 'verbose-name' : 'Table' },
+ 'wildcards' : { 'verbose-name' : 'Wildcards',
+ 'formatter' : fmtcnv.convert_integer_to_bitmask
+ },
+ 'dataLayerSource' : { 'verbose-name' : 'Src MAC',
+ 'formatter' : fmtcnv.replace_host_with_alias
+ },
+ 'dataLayerDestination' : { 'verbose-name' : 'Dst MAC',
+ 'formatter' : fmtcnv.replace_host_with_alias
+ },
+ 'dataLayerType' : { 'verbose-name' : 'Ether Type',
+ 'formatter' : fmtcnv.decode_ether_type
+ },
+ 'dataLayerVirtualLan' : { 'verbose-name' : 'VLAN ID',
+ 'formatter' : fmtcnv.convert_signed_short_to_unsigned
+ },
+ 'dataLayerVirtualLanPriorityCodePoint' : { 'verbose-name' : 'VLAN PCP'
+ },
+ 'inputPort' : { 'verbose-name' : 'In Port',
+ 'formatter' : fmtcnv.decode_openflow_port
+ },
+ 'networkSource' : { 'verbose-name' : 'Src IP'
+ },
+ 'networkDestination' : { 'verbose-name' : 'Dst IP'
+ },
+ 'networkSourceMaskLen' : { 'verbose-name' : 'Src IP Bits'
+ },
+ 'networkDestinationMaskLen' : { 'verbose-name' : 'Dst IP Bits'
+ },
+ 'networkProtocol' : { 'verbose-name' : 'Protocol',
+ 'formatter' : fmtcnv.decode_network_protocol
+ },
+ 'networkTypeOfService' : { 'verbose-name' : 'TOS Bits'
+ },
+ 'transportSource' : { 'verbose-name' : 'Src Port',
+ 'formatter' : fmtcnv.decode_src_port
+ },
+ 'transportDestination' : { 'verbose-name' : 'Dst Port',
+ 'formatter' : fmtcnv.decode_dst_port
+ },
+ 'actions' : { 'verbose-name' : 'Actions',
+ 'formatter' : fmtcnv.decode_actions
+ },
+ 'vnsName' : { 'verbose-name' : 'VNS'
+ },
+ 'vnsFlowCnt' : { 'verbose-name' : 'Flows'
+ },
+ 'flowEntryCnt' : { 'verbose-name' : 'Flow-Entries'
+ },
+ 'mplsTc' : { 'verbose-name' : 'MPLS_TC'
+ },
+ 'mplsLabel' : { 'verbose-name' : 'MPLS_Label'
+ },
+
+ }
+ },
+}
+
+
+
+
+REALTIME_TABLE_ACL_FLOW_FORMAT = {
+ 'realtime_table_acl_flow' : {
+ 'field-orderings' : {
+ 'default' : [
+ 'Idx', 'switch', 'cookie',
+ 'byteCount', 'packetCount',
+ 'actions', 'dataLayerSource', 'dataLayerDestination',
+ 'flow-brief','mplsTc','mplsLabel'
+ ],
+ 'scoped' : [
+ 'Idx', 'cookie',
+ 'byteCount', 'packetCount',
+ 'actions', 'dataLayerSource', 'dataLayerDestination','mplsTc','mplsLabel',
+ 'flow-brief',
+
+ ],
+ 'brief' : [ 'Idx', 'switch', 'cookie', 'dataLayerSource', 'dataLayerDestination',
+ 'networkSource', 'networkDestination', 'networkProtocol',
+ 'transportSource', 'transportDestination','mplsTc','mplsLabel'],
+ 'default' : [ 'Idx', 'switch', 'byteCount', 'packetCount', 'durationSeconds',
+ 'cookie', 'inputPort', 'dataLayerSource', 'dataLayerDestination',
+ 'dataLayerType', 'networkSource', 'networkDestination', 'networkProtocol',
+ 'transportSource', 'transportDestination','mplsTc','mplsLabel'],
+ 'scoped' : [ 'Idx', 'switch', 'byteCount', 'packetCount', 'durationSeconds',
+ 'cookie', 'inputPort', 'dataLayerSource', 'dataLayerDestination',
+ 'dataLayerType', 'networkSource', 'networkDestination', 'networkProtocol',
+ 'transportSource', 'transportDestination','mplsTc','mplsLabel'],
+ 'details' : [ 'Idx', 'switch', 'byteCount', 'packetCount', 'durationSeconds',
+ 'cookie', 'hardTimeout', 'idleTimeout', 'priority', 'tableId', 'inputPort',
+ 'dataLayerSource', 'dataLayerDestination', 'dataLayerType', 'dataLayerVirtualLan',
+ 'dataLayerVirtualLanPriorityCodePoint', 'networkSource', 'networkDestination',
+ 'networkProtocol', 'transportSource', 'transportDestination',
+ 'networkTypeOfService', 'actions','mplsTc','mplsLabel'],
+ #'vns_flow': [ 'Idx', 'dataLayerSource', 'dataLayerDestination', 'dataLayerVirtualLan', 'dataLayerType'],
+ #'summary' : [ 'Idx', 'vnsName', 'vnsFlowCnt', 'flowEntryCnt'],
+ },
+ 'fields': {
+ 'switch' : { 'verbose-name' : 'Switch',
+ 'formatter' : fmtcnv.replace_switch_with_alias
+ },
+ 'flow-brief' : {
+ 'verbose-name' : 'Match',
+ 'formatter' : fmtcnv.realtime_flow_brief,
+ },
+ 'flow-timeout' : {
+ 'verbose-name' : 'H/I',
+ 'formatter' : realtime_flow_timeout,
+ },
+ 'byteCount' : { 'verbose-name': 'Bytes',
+ 'primary_key':True
+ },
+ 'packetCount' : { 'verbose-name' : 'Packets'
+ },
+ 'cookie' : { 'verbose-name' : 'Cookie',
+ #'formatter' : fmtcnv.decode_flow_cookie,
+ },
+ 'durationSeconds' : { 'verbose-name' : 'Dur(s)'
+ },
+ 'durationNanoseconds' : { 'verbose-name' : 'Dur(ns)'
+ },
+ 'hardTimeout' : { 'verbose-name' : 'Hard Timeout',
+ 'formatter' : fmtcnv.convert_signed_short_to_unsigned
+ },
+ 'idleTimeout' : { 'verbose-name' : 'Idle Timeout',
+ 'formatter' : fmtcnv.convert_signed_short_to_unsigned
+ },
+ 'length' : { 'verbose-name' : 'Length'
+ },
+ 'priority' : { 'verbose-name' : 'Priority',
+ 'formatter' : fmtcnv.convert_signed_short_to_unsigned
+ },
+ 'tableId' : { 'verbose-name' : 'Table' },
+ 'wildcards' : { 'verbose-name' : 'Wildcards',
+ 'formatter' : fmtcnv.convert_integer_to_bitmask
+ },
+ 'dataLayerSource' : { 'verbose-name' : 'Src MAC',
+ 'formatter' : fmtcnv.replace_host_with_alias
+ },
+ 'dataLayerDestination' : { 'verbose-name' : 'Dst MAC',
+ 'formatter' : fmtcnv.replace_host_with_alias
+ },
+ 'dataLayerType' : { 'verbose-name' : 'Ether Type',
+ 'formatter' : fmtcnv.decode_ether_type
+ },
+ 'dataLayerVirtualLan' : { 'verbose-name' : 'VLAN ID',
+ 'formatter' : fmtcnv.convert_signed_short_to_unsigned
+ },
+ 'dataLayerVirtualLanPriorityCodePoint' : { 'verbose-name' : 'VLAN PCP'
+ },
+ 'inputPort' : { 'verbose-name' : 'In Port',
+ 'formatter' : fmtcnv.decode_openflow_port
+ },
+ 'networkSource' : { 'verbose-name' : 'Src IP'
+ },
+ 'networkDestination' : { 'verbose-name' : 'Dst IP'
+ },
+ 'networkSourceMaskLen' : { 'verbose-name' : 'Src IP Bits'
+ },
+ 'networkDestinationMaskLen' : { 'verbose-name' : 'Dst IP Bits'
+ },
+ 'networkProtocol' : { 'verbose-name' : 'Protocol',
+ 'formatter' : fmtcnv.decode_network_protocol
+ },
+ 'networkTypeOfService' : { 'verbose-name' : 'TOS Bits'
+ },
+ 'transportSource' : { 'verbose-name' : 'Src Port',
+ 'formatter' : fmtcnv.decode_src_port
+ },
+ 'transportDestination' : { 'verbose-name' : 'Dst Port',
+ 'formatter' : fmtcnv.decode_dst_port
+ },
+ 'actions' : { 'verbose-name' : 'Actions',
+ 'formatter' : fmtcnv.decode_actions
+ },
+ 'vnsName' : { 'verbose-name' : 'VNS'
+ },
+ 'vnsFlowCnt' : { 'verbose-name' : 'Flows'
+ },
+ 'flowEntryCnt' : { 'verbose-name' : 'Flow-Entries'
+ },
+ 'mplsTc' : { 'verbose-name' : 'MPLS_TC'
+ },
+ 'mplsLabel' : { 'verbose-name' : 'MPLS_LABEL'
+ },
+ }
+ },
+}
+
REALTIME_AGGREGATE_FORMAT = {
'realtime_aggregate' : {
diff --git a/cli/cli/desc/version200/switch.py b/cli/cli/desc/version200/switch.py
index dd4ccab..082b7d1 100755
--- a/cli/cli/desc/version200/switch.py
+++ b/cli/cli/desc/version200/switch.py
@@ -189,9 +189,7 @@
'field' : 'realtimestats',
'type' : 'enum',
'values' : ('aggregate',
- 'flow',
'port',
- 'table',
'desc',
'queue',
'group'
@@ -236,6 +234,44 @@
'doc' : 'format|+',
},
),
+ (
+ {
+ 'field' : 'realtimestats',
+ 'type' : 'enum',
+ 'values' : 'table',
+ #'args':(
+ # {
+ # 'field' : 'tabletype',
+ # 'type' : 'enum',
+ # 'values' : ('ip',
+ # 'acl',
+ # 'mpls'
+ # ),
+ # },
+ # )
+ },
+ {
+ 'field' : 'tabletype',
+ 'type' : 'enum',
+ 'values' : ('ip',
+ 'acl',
+ 'mpls'
+ ),
+ 'doc' : 'format|+',
+ },
+ {
+ 'field' : 'tableflow',
+ 'type' : 'enum',
+ 'values' : ('flow',
+ ),
+ 'action' : 'display-rest',
+ 'url' : 'realtimestats/%(realtimestats)s/%(tabletype)s/%(tableflow)s/%(dpid)s/',
+ 'rest-type' : 'dict-of-list-of-switch',
+ 'format' : 'realtime_%(realtimestats)s_%(tabletype)s_flow',
+ 'short-help' : 'Show requested item by querying switch',
+ 'doc' : 'switch|realtime-+',
+ },
+ ),
)
}
)
diff --git a/cli/sdncon/rest/views.py b/cli/sdncon/rest/views.py
index c8ff42e..545fe98 100755
--- a/cli/sdncon/rest/views.py
+++ b/cli/sdncon/rest/views.py
@@ -413,6 +413,19 @@
if stattype == 'groupdesc':
stattype = 'groupDesc'
url = "http://localhost:8080/wm/floodlight/core/switch/%s/%s/json" % (dpid, stattype)
+ return get_sdnplatform_response(url)
+
+@safe_rest_view
+def do_tablerealtimestats(request, tabletype, dpid):
+ """
+ This returns realtime statistics per table (flows (only)
+ current implementation) for a dpid by calling the localhost sdnplatform
+ """
+ #raise RestInvalidMethodException()
+ if request.method != 'GET':
+ raise RestInvalidMethodException()
+ #url = controller_url('core', 'switch', dpid, stattype, 'json')
+ url = "http://localhost:8080/wm/floodlight/core/switch/%s/table/%s/flow/json" % (dpid,tabletype)
#url ="http://localhost:8080/wm/floodlight/core/switch/00:00:00:00:00:00:00:01/flow/json"
return get_sdnplatform_response(url)
diff --git a/cli/sdncon/urls.py b/cli/sdncon/urls.py
index d112dc6..5d522de 100755
--- a/cli/sdncon/urls.py
+++ b/cli/sdncon/urls.py
@@ -61,9 +61,11 @@
(r'^rest/v1/realtimestats/counter/categories/(?P<dpid>[A-Za-z0-9_:.\-]+)/(?P<stattype>[A-Za-z0-9_:.\-]+)/(?P<layer>[0-9])/?$', 'sdncon.rest.views.do_sdnplatform_counter_categories'),
(r'^rest/v1/realtimestats/counter/(?P<stattype>[A-Za-z0-9_:.\-]+)/?$', 'sdncon.rest.views.do_sdnplatform_realtimestats'),
(r'^rest/v1/realtimestats/counter/(?P<dpid>[A-Za-z0-9_:.\-]+)/(?P<stattype>[A-Za-z]+)/?$', 'sdncon.rest.views.do_sdnplatform_realtimestats'),
+ (r'^rest/v1/realtimestats/table/(?P<tabletype>[A-Za-z]+)/flow/(?P<dpid>[A-Za-z0-9_:./\-]+)/?$', 'sdncon.rest.views.do_tablerealtimestats'),
(r'^rest/v1/realtimestats/(?P<stattype>[A-Za-z]+)/(?P<dpid>[A-Za-z0-9_:./\-]+)/?$', 'sdncon.rest.views.do_realtimestats'),
(r'^rest/v1/controller/stats/(?P<stattype>[A-Za-z]+)/?$', 'sdncon.rest.views.do_controller_stats'),
(r'^rest/v1/controller/storage/tables/?$', 'sdncon.rest.views.do_controller_storage_table_list'),
+
# REST API VNS/device information
(r'^rest/v1/device', 'sdncon.rest.views.do_device'),
diff --git a/src/main/java/net/floodlightcontroller/core/IOF13Switch.java b/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
index 6cb5b15..53f90f3 100644
--- a/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
+++ b/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
@@ -5,6 +5,8 @@
import java.util.HashSet;
import java.util.Set;
+import org.projectfloodlight.openflow.types.TableId;
+
import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
import net.onrc.onos.core.util.Dpid;
import net.onrc.onos.core.util.PortNumber;
@@ -131,5 +133,12 @@
public void removePortFromGroups(PortNumber port);
public void addPortToGroups(PortNumber port);
+ /**
+ * give string tableType (ip, mpls, acl)
+ * @param tableType String equal to only one of (ip, mpls, acl)
+ * @return TableId
+ */
+
+ public TableId getTableId(String tableType);
}
diff --git a/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java b/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java
index 74cccfb..8608b20 100644
--- a/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java
+++ b/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java
@@ -43,6 +43,7 @@
router.attach("/switch/{switchId}/role/json", SwitchRoleResource.class);
router.attach("/switch/all/{statType}/json", AllSwitchStatisticsResource.class);
router.attach("/switch/{switchId}/{statType}/json", SwitchStatisticsResource.class);
+ router.attach("/switch/{switchId}/table/{tableType}/{statType}/json", SwitchStatisticsResource.class);
router.attach("/controller/switches/json", ControllerSwitchesResource.class);
router.attach("/memory/json", ControllerMemoryResource.class);
router.attach("/health/json", HealthCheckResource.class);
diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java b/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java
index 8e4208c..e6abf2d 100644
--- a/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java
+++ b/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java
@@ -25,6 +25,7 @@
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.annotations.LogMessageDoc;
+import net.onrc.onos.core.drivermanager.OFSwitchImplCPqD13;
import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
@@ -102,7 +103,6 @@
try {
future = sw.getStatistics(req);
values = future.get(10, TimeUnit.SECONDS);
- System.out.println("value\n\n\n"+ values);
for (OFFlowStatsEntry entry : ((OFFlowStatsReply)values.get(0)).getEntries()) {
OFFlowStatsEntryMod entryMod = new OFFlowStatsEntryMod(entry);
flowStats.add(entryMod);
@@ -212,6 +212,54 @@
protected Object getSwitchStatistics(String switchId, OFStatsType statType) {
return getSwitchStatistics(HexString.toLong(switchId), statType);
}
+ //TODO: Java doc
+ protected List<?> getSwitchStatisticsForTable(long switchId,
+ OFStatsType statType, String tableType) {
+ IFloodlightProviderService floodlightProvider =
+ (IFloodlightProviderService) getContext().getAttributes().
+ get(IFloodlightProviderService.class.getCanonicalName());
+ IOFSwitch sw = floodlightProvider.getSwitches().get(switchId);
+ Future<List<OFStatsReply>> future;
+ List<OFStatsReply> values = null;
+ //getting tableId from CPqD driver
+ TableId tableId;
+ if (sw != null) {
+ if((tableId = ((OFSwitchImplCPqD13) sw).getTableId(tableType)) == null){
+ log.error("Invalid tableType {} " + tableType);
+ return null;
+ }
+ OFStatsRequest<?> req = null;
+ if (statType == OFStatsType.FLOW) {
+ log.debug("Switch Flow Stats req for table {} sent to switch {}",
+ tableType,sw.getStringId());
+ OFMatchV3 match = sw.getFactory().buildMatchV3()
+ .setOxmList(OFOxmList.EMPTY).build();
+ req = sw.getFactory()
+ .buildFlowStatsRequest()
+ .setMatch(match)
+ .setOutPort(OFPort.ANY)
+ .setTableId(tableId)
+ .setXid(sw.getNextTransactionId()).build();
+ List<OFFlowStatsEntryMod> flowStats = new ArrayList<OFFlowStatsEntryMod>();
+ try {
+ future = sw.getStatistics(req);
+ values = future.get(10, TimeUnit.SECONDS);
+ for (OFFlowStatsEntry entry : ((OFFlowStatsReply)values.get(0)).getEntries()) {
+ OFFlowStatsEntryMod entryMod = new OFFlowStatsEntryMod(entry);
+ flowStats.add(entryMod);
+ }
+ log.debug("Switch flow Stats Entries for table {} from switch {} are {}",
+ tableType, sw.getStringId(), flowStats);
+ } catch (Exception e) {
+ log.error("Failure retrieving per table statistics from switch " + sw, e);
+ }
+ return flowStats;
+ }
+ }
+ //should never get to this point
+ log.error("Failure retrieving {} table statistics from switch {}",tableType, sw);
+ return null;
+ }
protected OFFeaturesReply getSwitchFeaturesReply(long switchId) {
IFloodlightProviderService floodlightProvider =
diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java
index 4f45463..ce2221e 100644
--- a/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java
+++ b/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java
@@ -20,6 +20,7 @@
import java.util.HashMap;
import org.projectfloodlight.openflow.protocol.OFStatsType;
+import org.projectfloodlight.openflow.util.HexString;
import org.restlet.resource.Get;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,14 +42,24 @@
String switchId = (String) getRequestAttributes().get("switchId");
String statType = (String) getRequestAttributes().get("statType");
+ String tableType = null;
+ if(getRequestAttributes().containsKey("tableType")){
+ tableType = (String) getRequestAttributes().get("tableType");
+ }
if (statType.equals("port")) {
values = getSwitchStatistics(switchId, OFStatsType.PORT);
} else if (statType.equals("queue")) {
values = getSwitchStatistics(switchId, OFStatsType.QUEUE);
} else if (statType.equals("flow")) {
- values = getSwitchStatistics(switchId, OFStatsType.FLOW);
- } else if (statType.equals("aggregate")) {
+ if (tableType != null){
+ values = getSwitchStatisticsForTable(HexString.toLong(switchId), OFStatsType.FLOW, tableType);
+ }
+ else{
+ values = getSwitchStatistics(switchId, OFStatsType.FLOW);
+ }
+ }
+ else if (statType.equals("aggregate")) {
values = getSwitchStatistics(switchId, OFStatsType.AGGREGATE);
} else if (statType.equals("desc")) {
values = getSwitchStatistics(switchId, OFStatsType.DESC);
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/OFFlowStatsEntryModSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/OFFlowStatsEntryModSerializer.java
index e04487d..4f71dc9 100644
--- a/src/main/java/net/floodlightcontroller/core/web/serializers/OFFlowStatsEntryModSerializer.java
+++ b/src/main/java/net/floodlightcontroller/core/web/serializers/OFFlowStatsEntryModSerializer.java
@@ -8,6 +8,7 @@
import net.floodlightcontroller.core.web.OFFlowStatsEntryMod;
import org.projectfloodlight.openflow.protocol.action.*;
+import org.apache.commons.codec.binary.Hex;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.SerializerProvider;
@@ -73,7 +74,7 @@
jGen.writeStringField("dataLayerSource", matchGeneric.getValue().toString());
}
else if (matchGeneric.getMatchField().id == MatchFields.ETH_TYPE){
- jGen.writeStringField("dataLayerType", "0x"+matchGeneric.getValue().toString());
+ jGen.writeNumberField("dataLayerType", Integer.decode("0x"+matchGeneric.getValue().toString()));
}
else if (matchGeneric.getMatchField().id == MatchFields.IN_PORT){
jGen.writeNumberField("inputPort", Integer.parseInt(matchGeneric.getValue().toString()));
diff --git a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
index 3630e2b..640d7eb 100644
--- a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
+++ b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
@@ -1427,4 +1427,22 @@
log.info("Sw: {} Group Features {}", getStringId(), gfsr);
}
+ @Override
+ public TableId getTableId(String tableType) {
+ tableType = tableType.toLowerCase();
+ if(tableType.contentEquals("ip")){
+ return TableId.of(OFSwitchImplCPqD13.TABLE_IPv4_UNICAST);
+ }
+ else if (tableType.contentEquals("mpls")){
+ return TableId.of(OFSwitchImplCPqD13.TABLE_MPLS);
+ }
+ else if (tableType.contentEquals("acl")){
+ return TableId.of(OFSwitchImplCPqD13.TABLE_ACL);
+ }
+ else{
+ log.warn("Invalid tableType: {}", tableType);
+ return null;
+ }
+ }
+
}