mirror of
https://github.com/faucetsdn/ryu.git
synced 2026-05-05 04:16:11 +02:00
ofctl_rest: support OFPTableStats Message
this patch makes ofctl_rest enable use of OFPTableStats message.
Get table stats:
usage)
URI: /stats/table/<dpid>
method: GET
e.g.)
$ curl -X GET http://localhost:8080/stats/table/1
More infomation about this feature is described in the following URL.
http://ryu.readthedocs.org/en/latest/app/ofctl_rest.html#get-table-stats
Signed-off-by: Minoru TAKAHASHI <takahashi.minoru7@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
parent
f4f24469da
commit
9a534b46a6
@ -65,6 +65,9 @@ supported_ofctl = {
|
||||
# get aggregate flows stats of the switch filtered by the fields
|
||||
# POST /stats/aggregateflow/<dpid>
|
||||
#
|
||||
# get table stats of the switch
|
||||
# GET /stats/table/<dpid>
|
||||
#
|
||||
# get ports stats of the switch
|
||||
# GET /stats/port/<dpid>
|
||||
#
|
||||
@ -243,6 +246,30 @@ class StatsController(ControllerBase):
|
||||
body = json.dumps(flows)
|
||||
return Response(content_type='application/json', body=body)
|
||||
|
||||
def get_table_stats(self, req, dpid, **_kwargs):
|
||||
|
||||
if type(dpid) == str and not dpid.isdigit():
|
||||
LOG.debug('invalid dpid %s', dpid)
|
||||
return Response(status=400)
|
||||
|
||||
dp = self.dpset.get(int(dpid))
|
||||
|
||||
if dp is None:
|
||||
return Response(status=404)
|
||||
|
||||
_ofp_version = dp.ofproto.OFP_VERSION
|
||||
|
||||
_ofctl = supported_ofctl.get(_ofp_version, None)
|
||||
if _ofctl is not None:
|
||||
ports = _ofctl.get_table_stats(dp, self.waiters)
|
||||
|
||||
else:
|
||||
LOG.debug('Unsupported OF protocol')
|
||||
return Response(status=501)
|
||||
|
||||
body = json.dumps(ports)
|
||||
return Response(content_type='application/json', body=body)
|
||||
|
||||
def get_port_stats(self, req, dpid, **_kwargs):
|
||||
|
||||
if type(dpid) == str and not dpid.isdigit():
|
||||
@ -741,6 +768,11 @@ class RestStatsApi(app_manager.RyuApp):
|
||||
action='get_aggregate_flow_stats',
|
||||
conditions=dict(method=['GET', 'POST']))
|
||||
|
||||
uri = path + '/table/{dpid}'
|
||||
mapper.connect('stats', uri,
|
||||
controller=StatsController, action='get_table_stats',
|
||||
conditions=dict(method=['GET']))
|
||||
|
||||
uri = path + '/port/{dpid}'
|
||||
mapper.connect('stats', uri,
|
||||
controller=StatsController, action='get_port_stats',
|
||||
@ -820,6 +852,7 @@ class RestStatsApi(app_manager.RyuApp):
|
||||
ofp_event.EventOFPDescStatsReply,
|
||||
ofp_event.EventOFPFlowStatsReply,
|
||||
ofp_event.EventOFPAggregateStatsReply,
|
||||
ofp_event.EventOFPTableStatsReply,
|
||||
ofp_event.EventOFPPortStatsReply,
|
||||
ofp_event.EventOFPQueueStatsReply,
|
||||
ofp_event.EventOFPMeterStatsReply,
|
||||
|
||||
@ -382,6 +382,57 @@ def get_aggregate_flow_stats(dp, waiters, flow={}):
|
||||
return flows
|
||||
|
||||
|
||||
def get_table_stats(dp, waiters):
|
||||
stats = dp.ofproto_parser.OFPTableStatsRequest(dp, 0)
|
||||
ofp = dp.ofproto
|
||||
msgs = []
|
||||
send_stats_request(dp, stats, waiters, msgs)
|
||||
|
||||
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)
|
||||
s = {'table_id': stat.table_id,
|
||||
'name': stat.name,
|
||||
'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)
|
||||
desc = {str(dp.id): tables}
|
||||
|
||||
return desc
|
||||
|
||||
|
||||
def get_port_stats(dp, waiters):
|
||||
stats = dp.ofproto_parser.OFPPortStatsRequest(
|
||||
dp, 0, dp.ofproto.OFPP_NONE)
|
||||
|
||||
@ -516,6 +516,131 @@ def get_aggregate_flow_stats(dp, waiters, flow={}):
|
||||
return flows
|
||||
|
||||
|
||||
def get_table_stats(dp, waiters):
|
||||
stats = dp.ofproto_parser.OFPTableStatsRequest(dp)
|
||||
ofp = dp.ofproto
|
||||
msgs = []
|
||||
send_stats_request(dp, stats, waiters, msgs)
|
||||
|
||||
oxm_type_convert = {ofp.OFPXMT_OFB_IN_PORT: 'IN_PORT',
|
||||
ofp.OFPXMT_OFB_IN_PHY_PORT: 'IN_PHY_PORT',
|
||||
ofp.OFPXMT_OFB_METADATA: 'METADATA',
|
||||
ofp.OFPXMT_OFB_ETH_DST: 'ETH_DST',
|
||||
ofp.OFPXMT_OFB_ETH_SRC: 'ETH_SRC',
|
||||
ofp.OFPXMT_OFB_ETH_TYPE: 'ETH_TYPE',
|
||||
ofp.OFPXMT_OFB_VLAN_VID: 'VLAN_VID',
|
||||
ofp.OFPXMT_OFB_VLAN_PCP: 'VLAN_PCP',
|
||||
ofp.OFPXMT_OFB_IP_DSCP: 'IP_DSCP',
|
||||
ofp.OFPXMT_OFB_IP_ECN: 'IP_ECN',
|
||||
ofp.OFPXMT_OFB_IP_PROTO: 'IP_PROTO',
|
||||
ofp.OFPXMT_OFB_IPV4_SRC: 'IPV4_SRC',
|
||||
ofp.OFPXMT_OFB_IPV4_DST: 'IPV4_DST',
|
||||
ofp.OFPXMT_OFB_TCP_SRC: 'TCP_SRC',
|
||||
ofp.OFPXMT_OFB_TCP_DST: 'TCP_DST',
|
||||
ofp.OFPXMT_OFB_UDP_SRC: 'UDP_SRC',
|
||||
ofp.OFPXMT_OFB_UDP_DST: 'UDP_DST',
|
||||
ofp.OFPXMT_OFB_SCTP_SRC: 'SCTP_SRC',
|
||||
ofp.OFPXMT_OFB_SCTP_DST: 'SCTP_DST',
|
||||
ofp.OFPXMT_OFB_ICMPV4_TYPE: 'ICMPV4_TYPE',
|
||||
ofp.OFPXMT_OFB_ICMPV4_CODE: 'ICMPV4_CODE',
|
||||
ofp.OFPXMT_OFB_ARP_OP: 'ARP_OP',
|
||||
ofp.OFPXMT_OFB_ARP_SPA: 'ARP_SPA',
|
||||
ofp.OFPXMT_OFB_ARP_TPA: 'ARP_TPA',
|
||||
ofp.OFPXMT_OFB_ARP_SHA: 'ARP_SHA',
|
||||
ofp.OFPXMT_OFB_ARP_THA: 'ARP_THA',
|
||||
ofp.OFPXMT_OFB_IPV6_SRC: 'IPV6_SRC',
|
||||
ofp.OFPXMT_OFB_IPV6_DST: 'IPV6_DST',
|
||||
ofp.OFPXMT_OFB_IPV6_FLABEL: 'IPV6_FLABEL',
|
||||
ofp.OFPXMT_OFB_ICMPV6_TYPE: 'ICMPV6_TYPE',
|
||||
ofp.OFPXMT_OFB_ICMPV6_CODE: 'ICMPV6_CODE',
|
||||
ofp.OFPXMT_OFB_IPV6_ND_TARGET: 'IPV6_ND_TARGET',
|
||||
ofp.OFPXMT_OFB_IPV6_ND_SLL: 'IPV6_ND_SLL',
|
||||
ofp.OFPXMT_OFB_IPV6_ND_TLL: 'IPV6_ND_TLL',
|
||||
ofp.OFPXMT_OFB_MPLS_LABEL: 'MPLS_LABEL',
|
||||
ofp.OFPXMT_OFB_MPLS_TC: 'MPLS_TC'}
|
||||
|
||||
act_convert = {ofp.OFPAT_OUTPUT: 'OUTPUT',
|
||||
ofp.OFPAT_COPY_TTL_OUT: 'COPY_TTL_OUT',
|
||||
ofp.OFPAT_COPY_TTL_IN: 'COPY_TTL_IN',
|
||||
ofp.OFPAT_SET_MPLS_TTL: 'SET_MPLS_TTL',
|
||||
ofp.OFPAT_DEC_MPLS_TTL: 'DEC_MPLS_TTL',
|
||||
ofp.OFPAT_PUSH_VLAN: 'PUSH_VLAN',
|
||||
ofp.OFPAT_POP_VLAN: 'POP_VLAN',
|
||||
ofp.OFPAT_PUSH_MPLS: 'PUSH_MPLS',
|
||||
ofp.OFPAT_POP_MPLS: 'POP_MPLS',
|
||||
ofp.OFPAT_SET_QUEUE: 'SET_QUEUE',
|
||||
ofp.OFPAT_GROUP: 'GROUP',
|
||||
ofp.OFPAT_SET_NW_TTL: 'SET_NW_TTL',
|
||||
ofp.OFPAT_DEC_NW_TTL: 'DEC_NW_TTL',
|
||||
ofp.OFPAT_SET_FIELD: 'SET_FIELD'}
|
||||
|
||||
inst_convert = {ofp.OFPIT_GOTO_TABLE: 'GOTO_TABLE',
|
||||
ofp.OFPIT_WRITE_METADATA: 'WRITE_METADATA',
|
||||
ofp.OFPIT_WRITE_ACTIONS: 'WRITE_ACTIONS',
|
||||
ofp.OFPIT_APPLY_ACTIONS: 'APPLY_ACTIONS',
|
||||
ofp.OFPIT_CLEAR_ACTIONS: 'CLEAR_ACTIONS',
|
||||
ofp.OFPIT_EXPERIMENTER: 'EXPERIMENTER'}
|
||||
|
||||
table_conf_convert = {
|
||||
ofp.OFPTC_TABLE_MISS_CONTROLLER: 'TABLE_MISS_CONTROLLER',
|
||||
ofp.OFPTC_TABLE_MISS_CONTINUE: 'TABLE_MISS_CONTINUE',
|
||||
ofp.OFPTC_TABLE_MISS_DROP: 'TABLE_MISS_DROP',
|
||||
ofp.OFPTC_TABLE_MISS_MASK: 'TABLE_MISS_MASK'}
|
||||
|
||||
tables = []
|
||||
for msg in msgs:
|
||||
stats = msg.body
|
||||
for stat in stats:
|
||||
match = []
|
||||
wildcards = []
|
||||
write_setfields = []
|
||||
apply_setfields = []
|
||||
for k, v in oxm_type_convert.items():
|
||||
if (1 << k) & stat.match:
|
||||
match.append(v)
|
||||
if (1 << k) & stat.wildcards:
|
||||
wildcards.append(v)
|
||||
if (1 << k) & stat.write_setfields:
|
||||
write_setfields.append(v)
|
||||
if (1 << k) & stat.apply_setfields:
|
||||
apply_setfields.append(v)
|
||||
write_actions = []
|
||||
apply_actions = []
|
||||
for k, v in act_convert.items():
|
||||
if (1 << k) & stat.write_actions:
|
||||
write_actions.append(v)
|
||||
if (1 << k) & stat.apply_actions:
|
||||
apply_actions.append(v)
|
||||
instructions = []
|
||||
for k, v in inst_convert.items():
|
||||
if (1 << k) & stat.instructions:
|
||||
instructions.append(v)
|
||||
config = []
|
||||
for k, v in table_conf_convert.items():
|
||||
if (1 << k) & stat.config:
|
||||
config.append(v)
|
||||
s = {'table_id': stat.table_id,
|
||||
'name': stat.name,
|
||||
'match': match,
|
||||
'wildcards': wildcards,
|
||||
'write_actions': write_actions,
|
||||
'apply_actions': apply_actions,
|
||||
'write_setfields': write_setfields,
|
||||
'apply_setfields': apply_setfields,
|
||||
'metadata_match': stat.metadata_match,
|
||||
'metadata_write': stat.metadata_write,
|
||||
'instructions': instructions,
|
||||
'config': config,
|
||||
'max_entries': stat.max_entries,
|
||||
'active_count': stat.active_count,
|
||||
'lookup_count': stat.lookup_count,
|
||||
'matched_count': stat.matched_count}
|
||||
tables.append(s)
|
||||
desc = {str(dp.id): tables}
|
||||
|
||||
return desc
|
||||
|
||||
|
||||
def get_port_stats(dp, waiters):
|
||||
stats = dp.ofproto_parser.OFPPortStatsRequest(
|
||||
dp, dp.ofproto.OFPP_ANY, 0)
|
||||
|
||||
@ -547,6 +547,25 @@ def get_aggregate_flow_stats(dp, waiters, flow={}):
|
||||
return flows
|
||||
|
||||
|
||||
def get_table_stats(dp, waiters):
|
||||
stats = dp.ofproto_parser.OFPTableStatsRequest(dp, 0)
|
||||
msgs = []
|
||||
send_stats_request(dp, stats, waiters, msgs)
|
||||
|
||||
tables = []
|
||||
for msg in msgs:
|
||||
stats = msg.body
|
||||
for stat in stats:
|
||||
s = {'table_id': stat.table_id,
|
||||
'active_count': stat.active_count,
|
||||
'lookup_count': stat.lookup_count,
|
||||
'matched_count': stat.matched_count}
|
||||
tables.append(s)
|
||||
desc = {str(dp.id): tables}
|
||||
|
||||
return desc
|
||||
|
||||
|
||||
def get_port_stats(dp, waiters):
|
||||
stats = dp.ofproto_parser.OFPPortStatsRequest(
|
||||
dp, 0, dp.ofproto.OFPP_ANY)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user