blob: 50393ea8f27c4239edcefa7564ef3d355c578935 [file] [log] [blame]
stevenvanrossemc5a536a2016-02-16 14:52:39 +01001__author__ = 'Administrator'
2
3import urllib2
4import logging
5from mininet.node import OVSSwitch
6import ast
stevenvanrossem9315da42016-04-11 12:10:06 +02007import time
stevenvanrossemc5a536a2016-02-16 14:52:39 +01008logging.basicConfig(level=logging.INFO)
9
10"""
11class to read openflow stats from the Ryu controller of the DCNEtwork
12"""
13
14class DCNetworkMonitor():
15 def __init__(self, net):
16 self.net = net
17 # link to REST_API
18 self.ip = '0.0.0.0'
19 self.port = '8080'
20 self.REST_api = 'http://{0}:{1}'.format(self.ip,self.port)
21
stevenvanrossem9315da42016-04-11 12:10:06 +020022 self.previous_measurement = 0
23 self.previous_monitor_time = 0
stevenvanrossemed711fd2016-04-11 16:59:29 +020024 self.switch_dpid = 0
25 self.metric_key = None
26 self.mon_port = None
stevenvanrossemc5a536a2016-02-16 14:52:39 +010027
stevenvanrossemed711fd2016-04-11 16:59:29 +020028 # first set some parameters, before measurement can start
29 def setup_rate_measurement(self, vnf_name, vnf_interface=None, direction='tx', metric='packets'):
stevenvanrossem9315da42016-04-11 12:10:06 +020030 # check if port is specified (vnf:port)
stevenvanrossemed711fd2016-04-11 16:59:29 +020031 if vnf_interface is None:
stevenvanrossem9315da42016-04-11 12:10:06 +020032 # take first interface by default
33 connected_sw = self.net.DCNetwork_graph.neighbors(vnf_name)[0]
34 link_dict = self.net.DCNetwork_graph[vnf_name][connected_sw]
35 vnf_interface = link_dict[0]['src_port_id']
stevenvanrossem9315da42016-04-11 12:10:06 +020036
37 for connected_sw in self.net.DCNetwork_graph.neighbors(vnf_name):
38 link_dict = self.net.DCNetwork_graph[vnf_name][connected_sw]
39 for link in link_dict:
stevenvanrossemed711fd2016-04-11 16:59:29 +020040 # logging.info("{0},{1}".format(link_dict[link],vnf_interface))
stevenvanrossem9315da42016-04-11 12:10:06 +020041 if link_dict[link]['src_port_id'] == vnf_interface:
42 # found the right link and connected switch
43 # logging.info("{0},{1}".format(link_dict[link]['src_port_id'], vnf_source_interface))
stevenvanrossemed711fd2016-04-11 16:59:29 +020044 self.mon_port = link_dict[link]['dst_port']
stevenvanrossem9315da42016-04-11 12:10:06 +020045 break
46
47 try:
48 # default port direction to monitor
49 if direction is None:
50 direction = 'tx'
stevenvanrossemed711fd2016-04-11 16:59:29 +020051 if metric is None:
52 metric = 'packets'
stevenvanrossem9315da42016-04-11 12:10:06 +020053
stevenvanrossemc5a536a2016-02-16 14:52:39 +010054 vnf_switch = self.net.DCNetwork_graph.neighbors(str(vnf_name))
55
56 if len(vnf_switch) > 1:
57 logging.info("vnf: {0} has multiple ports".format(vnf_name))
58 return
59 elif len(vnf_switch) == 0:
60 logging.info("vnf: {0} is not connected".format(vnf_name))
61 return
62 else:
63 vnf_switch = vnf_switch[0]
64 next_node = self.net.getNodeByName(vnf_switch)
65
stevenvanrossemed711fd2016-04-11 16:59:29 +020066 if not isinstance(next_node, OVSSwitch):
stevenvanrossemc5a536a2016-02-16 14:52:39 +010067 logging.info("vnf: {0} is not connected to switch".format(vnf_name))
68 return
69
stevenvanrossemed711fd2016-04-11 16:59:29 +020070 self.previous_measurement = 0
71 self.previous_monitor_time = 0
stevenvanrossem9315da42016-04-11 12:10:06 +020072
stevenvanrossemed711fd2016-04-11 16:59:29 +020073 #self.switch_dpid = x = int(str(next_node.dpid), 16)
74 self.switch_dpid = int(str(next_node.dpid), 16)
75 self.metric_key = '{0}_{1}'.format(direction, metric)
stevenvanrossemc5a536a2016-02-16 14:52:39 +010076
stevenvanrossemed711fd2016-04-11 16:59:29 +020077 except Exception as ex:
78 logging.exception("get_txrate error.")
79 return ex.message
stevenvanrossem9315da42016-04-11 12:10:06 +020080
81
stevenvanrossemed711fd2016-04-11 16:59:29 +020082 # call this function repeatedly for streaming measurements
83 def get_rate(self, vnf_name, vnf_interface=None, direction='tx', metric='packets'):
84
85 key = self.metric_key
86
87 ret = self.REST_cmd('stats/port', self.switch_dpid)
stevenvanrossemc5a536a2016-02-16 14:52:39 +010088 port_stat_dict = ast.literal_eval(ret)
stevenvanrossemed711fd2016-04-11 16:59:29 +020089 for port_stat in port_stat_dict[str(self.switch_dpid)]:
90 if port_stat['port_no'] == self.mon_port:
stevenvanrossem9315da42016-04-11 12:10:06 +020091 port_uptime = port_stat['duration_sec'] + port_stat['duration_nsec'] * 10 ** (-9)
92 this_measurement = port_stat[key]
93
94 if self.previous_monitor_time <= 0 or self.previous_monitor_time >= port_uptime:
95 self.previous_measurement = port_stat[key]
96 self.previous_monitor_time = port_uptime
97 # do first measurement
98 time.sleep(1)
stevenvanrossemed711fd2016-04-11 16:59:29 +020099 byte_rate = self.get_rate(vnf_name, vnf_interface, direction, metric)
stevenvanrossem9315da42016-04-11 12:10:06 +0200100 return byte_rate
101 else:
102 time_delta = (port_uptime - self.previous_monitor_time)
103 byte_rate = (this_measurement - self.previous_measurement) / float(time_delta)
104 #logging.info('uptime:{2} delta:{0} rate:{1}'.format(time_delta,byte_rate,port_uptime))
stevenvanrossem9315da42016-04-11 12:10:06 +0200105
106 self.previous_measurement = this_measurement
107 self.previous_monitor_time = port_uptime
108 return byte_rate
stevenvanrossemc5a536a2016-02-16 14:52:39 +0100109
110 return ret
111
stevenvanrossemc5a536a2016-02-16 14:52:39 +0100112 def REST_cmd(self, prefix, dpid):
113 url = self.REST_api + '/' + str(prefix) + '/' + str(dpid)
114 req = urllib2.Request(url)
115 ret = urllib2.urlopen(req).read()
116 return ret