├── CollectStats.py ├── IDS_RyuApp.py ├── README.md └── Traffic_Monitor.py /CollectStats.py: -------------------------------------------------------------------------------- 1 | # Collect Statistic Model 2 | 3 | from operator import attrgetter 4 | from ryu.app import simple_switch_13 5 | from ryu.controller import ofp_event 6 | from ryu.controller.handler import MAIN_DISPATCHER, DEAD_DISPATCHER 7 | from ryu.controller.handler import set_ev_cls 8 | from ryu.lib import hub 9 | 10 | class CollectTrainingStatsApp(simple_switch_13.SimpleSwitch13): 11 | 12 | def __init__(self, *args, **kwargs): 13 | super(CollectTrainingStatsApp, self).__init__(*args, **kwargs) 14 | self.datapaths = {} 15 | self.monitor_thread = hub.spawn(self.monitor) 16 | 17 | file = open("FlowStatsfile.txt","a+") 18 | file.write('dp_id,in_port,eth_dst,packets,bytes') 19 | file.close() 20 | 21 | file = open("PortStatsfile.txt","a+") 22 | file.write('dp_id,port_no,rx_bytes,rx_pkts,tx_bytes,tx_pkts') 23 | file.close() 24 | 25 | 26 | file = open("FlowStatsfile_target.txt","a+") 27 | file.write('target') 28 | file.close() 29 | 30 | file = open("PortStatsfile_target.txt","a+") 31 | file.write('target') 32 | file.close() 33 | 34 | 35 | #Asynchronous message 36 | @set_ev_cls(ofp_event.EventOFPStateChange,[MAIN_DISPATCHER, DEAD_DISPATCHER]) 37 | def state_change_handler(self, ev): 38 | datapath = ev.datapath 39 | if ev.state == MAIN_DISPATCHER: 40 | if datapath.id not in self.datapaths: 41 | self.logger.debug('register datapath: %016x', datapath.id) 42 | self.datapaths[datapath.id] = datapath 43 | 44 | elif ev.state == DEAD_DISPATCHER: 45 | if datapath.id in self.datapaths: 46 | self.logger.debug('unregister datapath: %016x', datapath.id) 47 | del self.datapaths[datapath.id] 48 | 49 | 50 | def monitor(self): 51 | while True: 52 | for dp in self.datapaths.values(): 53 | self.request_stats(dp) 54 | hub.sleep(10) 55 | 56 | 57 | def request_stats(self, datapath): 58 | self.logger.debug('send stats request: %016x', datapath.id) 59 | ofproto = datapath.ofproto 60 | parser = datapath.ofproto_parser 61 | 62 | # To collect dp_id, pkt_count, byte_count 63 | req = parser.OFPFlowStatsRequest(datapath) 64 | datapath.send_msg(req) 65 | 66 | # To collect dp_id, port_no, rx_bytes, rx_pkts, tx_bytes, tx_pkts 67 | req = parser.OFPPortStatsRequest(datapath, 0, ofproto.OFPP_ANY) 68 | datapath.send_msg(req) 69 | 70 | 71 | @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER) 72 | def _flow_stats_reply_handler(self, ev): 73 | body = ev.msg.body 74 | 75 | file = open("FlowStatsfile.txt","a+") 76 | file1=open("FlowStatsfile_target.txt","a+") 77 | self.logger.info('datapath in-port eth-dst out-port packets bytes') 78 | self.logger.info('---------------- -------- ----------------- -------- -------- --------') 79 | for stat in sorted([flow for flow in body if (flow.priority == 1) ], key=lambda flow: 80 | (flow.match['in_port'],flow.match['eth_dst'])): 81 | self.logger.info('%016x %8x %17s %8x %8d %8d',ev.msg.datapath.id,stat.match['in_port'], 82 | stat.match['eth_dst'],stat.instructions[0].actions[0].port,stat.packet_count, stat.byte_count) 83 | file.write("\n"+str(ev.msg.datapath.id) + ","+ str(stat.match['in_port'])+ "," + 84 | str(stat.match['eth_dst'])+ "," + str(stat.packet_count) + "," + str(stat.byte_count)) 85 | file1.write("\n0") 86 | file.close() 87 | file1.close() 88 | 89 | 90 | 91 | @set_ev_cls(ofp_event.EventOFPPortStatsReply, MAIN_DISPATCHER) 92 | def _port_stats_reply_handler(self, ev): 93 | body = ev.msg.body 94 | 95 | file = open("PortStatsfile.txt","a+") 96 | file1 = open("PortStatsfile_target.txt","a+") 97 | self.logger.info('datapath port rx-pkts rx-bytes rx-error tx-pkts tx-bytes tx-error') 98 | self.logger.info('---------------- -------- -------- -------- -------- -------- -------- --------') 99 | for stat in sorted(body, key=attrgetter('port_no')): 100 | if stat.port_no <= 10: 101 | self.logger.info('%016x %8x %8d %8d %8d %8d %8d %8d', 102 | ev.msg.datapath.id, stat.port_no, 103 | stat.rx_packets, stat.rx_bytes, stat.rx_errors, 104 | stat.tx_packets, stat.tx_bytes, stat.tx_errors) 105 | 106 | file.write("\n{},{},{},{},{},{}".format(ev.msg.datapath.id, stat.port_no, stat.rx_bytes, 107 | stat.rx_packets, stat.tx_bytes, stat.tx_packets)) 108 | file1.write("\n0") 109 | 110 | file.close() 111 | file1.close() 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /IDS_RyuApp.py: -------------------------------------------------------------------------------- 1 | # IDS using ML RyuApp 2 | 3 | import pandas as pd 4 | from sklearn.ensemble import RandomForestClassifier 5 | from operator import attrgetter 6 | from ryu.app import simple_switch_13 7 | from ryu.controller import ofp_event 8 | from ryu.controller.handler import MAIN_DISPATCHER, DEAD_DISPATCHER 9 | from ryu.controller.handler import set_ev_cls 10 | from ryu.lib import hub 11 | 12 | # instantiating the Random Forest Classifier 13 | rf_flow = RandomForestClassifier(n_estimators = 10) 14 | rf_port = RandomForestClassifier(n_estimators = 10) 15 | rf_group = RandomForestClassifier(n_estimators = 10) 16 | 17 | flag_flow = True 18 | flag_port = True 19 | flag_group = True 20 | 21 | class IDS_Application(simple_switch_13.SimpleSwitch13): 22 | 23 | def __init__(self, *args, **kwargs): 24 | super(IDS_Application, self).__init__(*args, **kwargs) 25 | self.datapaths = {} 26 | 27 | # Create a CSV file to store the Test data 28 | file = open("/home/arsheen/Downloads/MalPredictFlowStatsfile.txt","a+") 29 | file.write('dp_id,in_port,eth_dst,packets,bytes\n') 30 | file.write('516,1,1,10002203,238000000\n') 31 | file.write('516,1,1,40022000,2380000000\n') 32 | file.close() 33 | 34 | file = open("/home/arsheen/Downloads/MalPredictPortStatsfile.txt","a+") 35 | file.write('dp_id,port_no,rx_bytes,rx_pkts,tx_bytes,tx_pkts\n') 36 | file.write('1,2,10,10,10,10\n') 37 | file.close() 38 | 39 | self.monitor_thread = hub.spawn(self.main) 40 | 41 | 42 | # Asynchronous message to inform controller of the status of links in the network 43 | @set_ev_cls(ofp_event.EventOFPStateChange,[MAIN_DISPATCHER, DEAD_DISPATCHER]) 44 | def state_change_handler(self, ev): 45 | datapath = ev.datapath 46 | if ev.state == MAIN_DISPATCHER: 47 | if datapath.id not in self.datapaths: 48 | self.datapaths[datapath.id] = datapath 49 | 50 | elif ev.state == DEAD_DISPATCHER: 51 | if datapath.id in self.datapaths: 52 | del self.datapaths[datapath.id] 53 | 54 | 55 | def main(self): 56 | training_flag = True 57 | while True: 58 | # Train the model once 59 | if training_flag: 60 | self.IDS_training() 61 | training_flag = False 62 | 63 | for dp in self.datapaths.values(): 64 | # Give 30 second wait time to create topology 65 | if training_flag: 66 | hub.sleep(30) 67 | self.request_stats(dp) 68 | 69 | # Implement IDS application every 30 seconds 70 | self.IDS_impl() 71 | hub.sleep(30) 72 | 73 | # Remove unnecessary columns and calculate and store only current number of packets and bytes that have arrived instead of cummulative count 74 | # For each flow entry 75 | def data_cleaning_flow(self, input_path,output_path): 76 | file = open(input_path,"r") 77 | file1 = open(output_path,"a+") 78 | b = [0,0,0,0,0] 79 | a = [] 80 | c = [0,0,0,0,0] 81 | dict = {} 82 | first_line_flag_flow = True 83 | for line in file: 84 | a = line.split(",") 85 | if first_line_flag_flow: 86 | file1.write(str(a[3])+","+str(a[4])) 87 | first_line_flag_flow = False 88 | else: 89 | key = str(a[0])+"_"+str(a[1])+"_"+str(a[2]) 90 | if key in dict: 91 | ab = dict[key].split(",") 92 | for i in range(len(ab)): 93 | if i == 2: 94 | continue 95 | else: 96 | c[i] = int(a[i]) - int(ab[i]) 97 | file1.write(str(c[3])+","+ str(c[4])+"\n") 98 | dict[key] =( str(a[0])+ "," +str(a[1]) + "," + str(a[2])+ "," + str(a[3])+"," + str(a[4])) 99 | else: 100 | dict[key] = (str(a[0])+ "," +str(a[1]) + "," + str(a[2])+ "," + str(a[3])+"," + str(a[4])) 101 | file1.write(str(a[3])+","+str(a[4])+"\n") 102 | file.close() 103 | file1.close() 104 | 105 | ''' Remove unnecessary columns and calculate and store only current number of packets and bytes that have 106 | arrived instead of cummulative count''' 107 | # for each port entry 108 | def data_cleaning_port(self, input_path, output_path): 109 | file = open(input_path,"r") 110 | file1 = open(output_path,"a+") 111 | b = [0,0,0,0,0,0] 112 | a = [] 113 | c = [0,0,0,0,0,0] 114 | dict = {} 115 | first_line_flag_port = True 116 | for line in file: 117 | a = line.split(",") 118 | if first_line_flag_port: 119 | file1.write(str(a[2])+ "," + str(a[3])+","+str(a[4])+ "," + str(a[5])) 120 | first_line_flag_port = False 121 | else: 122 | key = str(a[0])+ "_" +str(a[1]) 123 | if key in dict: 124 | ab = dict[key].split(",") 125 | for i in range(len(ab)): 126 | c[i] = int(a[i]) - int(ab[i]) 127 | file1.write(str(c[2])+ "," + str(c[3])+","+str(c[4])+ "," + str(c[5])+"\n") 128 | dict[key] =( str(a[0])+ "," +str(a[1]) + "," + str(a[2])+ "," + str(a[3])+"," + str(a[4])+ "," + str(a[5])) 129 | else: 130 | dict[key] = (str(a[0])+ "," +str(a[1]) + "," + str(a[2])+ "," + str(a[3])+"," + str(a[4])+ "," + str(a[5])) 131 | file1.write(str(a[2])+ "," + str(a[3])+","+str(a[4])+ "," + str(a[5])+"\n") 132 | file.close() 133 | file1.close() 134 | 135 | 136 | # Model training 137 | def IDS_training(self): 138 | # Read cleaned flow statistics data 139 | self.data_cleaning_flow('/home/arsheen/Downloads/FlowStatsfile.txt','/home/arsheen/Downloads/FlowStatsfile_cleaned.txt') 140 | flow_without_key = pd.read_csv('/home/arsheen/Downloads/MalFlowStatsfile_cleaned.txt') 141 | flow_stat_input_target = pd.read_csv('/home/arsheen/Downloads/MalFlowStatsfile_target.txt') 142 | 143 | # Read cleaned port statistics data 144 | self.data_cleaning_port('/home/arsheen/Downloads/PortStatsfile.txt','/home/arsheen/Downloads/PortStatsfile_cleaned.txt') 145 | port_without_key = pd.read_csv('/home/arsheen/Downloads/MalPortStatsfile_cleaned.txt') 146 | port_stat_input_target = pd.read_csv('/home/arsheen/Downloads/MalPortStatsfile_target.txt') 147 | 148 | # Convert flow statistics data from string to int and fit it on the machine learning model 149 | flow_without_key = flow_without_key.apply(pd.to_numeric) 150 | flow_stat_input_target = flow_stat_input_target.apply(pd.to_numeric, errors='ignore') 151 | rf_flow.fit(flow_without_key,flow_stat_input_target.values.ravel()) 152 | 153 | # Convert port statistics data from string to int and fit it on the machine learning model 154 | port_without_key = port_without_key.apply(pd.to_numeric) 155 | port_stat_input_target = port_stat_input_target.apply(pd.to_numeric) 156 | rf_port.fit(port_without_key,port_stat_input_target.values.ravel()) 157 | 158 | 159 | # Check for the accuracy of the model 160 | def check_accuracy(self,model,input_data, input_target): 161 | cross_val_score_stat = cross_val_score(model, input_data, input_target, scoring = 'accuracy', cv = 10) 162 | mean_cross_val_score = cross_val_score_stat.mean() 163 | print(mean_cross_val_score) 164 | 165 | 166 | # IDS Implementation: monitoring real time traffic and predicting whether it is malicious. 167 | def IDS_impl(self): 168 | self.data_cleaning_flow('/home/arsheen/Downloads/PredictFlowStatsfile.txt','/home/arsheen/Downloads/PredictFlowStatsfile_cleaned.txt') 169 | self.data_cleaning_port('/home/arsheen/Downloads/PredictPortStatsfile.txt','/home/arsheen/Downloads/PredictPortStatsfile_cleaned.txt') 170 | 171 | #Read cleaned file 172 | flow_predict_without_key = pd.read_csv('/home/arsheen/Downloads/PredictFlowStatsfile_cleaned.txt') 173 | port_predict_without_key = pd.read_csv('/home/arsheen/Downloads/PredictPortStatsfile_cleaned.txt') 174 | 175 | #convert to numeric form 176 | flow_predict_without_key = flow_predict_without_key.apply(pd.to_numeric) 177 | port_predict_without_key = port_predict_without_key.apply(pd.to_numeric) 178 | 179 | #convert to list form for iteration 180 | flow_predict_list=list(flow_predict_without_key.values.tolist()) 181 | 182 | #Use test data to check for intrusion 183 | for i in flow_predict_list: 184 | if i==['packets','bytes']: 185 | continue 186 | else: 187 | temp = list(i) 188 | test = [] 189 | test.append(temp) 190 | # Binary classification 191 | flag_flow = rf_flow.predict(test) 192 | if flag_flow == 1: 193 | self.anomaly_specific_actions(True,True) 194 | else: 195 | self.anomaly_specific_actions(False,True) 196 | 197 | 198 | port_predict_list=list(port_predict_without_key.values.tolist()) 199 | for j in port_predict_list: 200 | if j==['rx_bytes','rx_pkts','tx_bytes','tx_pkts']: 201 | continue 202 | else: 203 | temp = list(j) 204 | test = [] 205 | test.append(temp) 206 | # Binary classification 207 | flag_port = rf_port.predict(test) 208 | if flag_port == 1: 209 | self.anomaly_specific_actions(True,True) 210 | else: 211 | self.anomaly_specific_actions(True,False) 212 | 213 | # Controller to Switch request for stats 214 | def request_stats(self, datapath): 215 | ofproto = datapath.ofproto 216 | parser = datapath.ofproto_parser 217 | 218 | # to collect dp_id, pkt_count, byte_count 219 | req = parser.OFPFlowStatsRequest(datapath) 220 | datapath.send_msg(req) 221 | 222 | # to collect dp_id, port_no, rx_bytes, rx_pkts, tx_bytes, tx_pkts 223 | req = parser.OFPPortStatsRequest(datapath, 0, ofproto.OFPP_ANY) 224 | datapath.send_msg(req) 225 | 226 | 227 | # Switch to Controller reply with statistics 228 | @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER) 229 | def flow_stats_reply_handler(self, ev): 230 | body = ev.msg.body 231 | file = open("MalPredictFlowStatsfile.txt","a+") 232 | for stat in sorted([flow for flow in body if flow.priority == 1], key=lambda flow: (flow.match['in_port'],flow.match['eth_dst'])): 233 | file.write("\n"+str(ev.msg.datapath.id) + ","+ str(stat.match['in_port'])+ "," + str(stat.match['eth_dst'])+ "," + 234 | str(stat.packet_count) + "," + str(stat.byte_count)) 235 | file.close() 236 | 237 | @set_ev_cls(ofp_event.EventOFPPortStatsReply, MAIN_DISPATCHER) 238 | def port_stats_reply_handler(self, ev): 239 | body = ev.msg.body 240 | file = open("MalPredictPortStatsfile.txt","a+") 241 | for stat in sorted(body, key=attrgetter('port_no')): 242 | file.write("\n"+str(ev.msg.datapath.id) + "," + str(stat.port_no) + "," + 243 | str(stat.rx_bytes)+ "," + str(stat.rx_packets) + "," + str(stat.tx_bytes) + "," + str(stat.tx_packets)) 244 | file.close() 245 | 246 | 247 | #Anomaly specific actions 248 | def anomaly_specific_actions(self,flag_flow, flag_port): 249 | if (not flag_flow) or (not flag_port): 250 | self.logger.debug("Intrusion Detected") 251 | print("Intrusion Detected") 252 | else: 253 | self.logger.debug("Everything is awesome") 254 | print("Everything is awesome") 255 | 256 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | Implemented a network intrusion detection system for a software defined network using Random Forest method for classification of port and flow statistics. 4 | 5 | 6 | Project Execution: 7 | 8 | 9 | Create a mininet topology. 10 | 11 | ssh to the mininet virtual machine. 12 | 13 | Run the collectStats.py file on the ryu controller. (Data from collectStat.py file is used for training the algorithm.) 14 | 15 | Now, run IDS_RyuApp.py to check whether current traffic is clean or malacious using machine learning algorithm. 16 | -------------------------------------------------------------------------------- /Traffic_Monitor.py: -------------------------------------------------------------------------------- 1 | from operator import attrgetter 2 | from ryu.app import simple_switch_13 3 | from ryu.controller import ofp_event 4 | from ryu.controller.handler import MAIN_DISPATCHER, DEAD_DISPATCHER 5 | from ryu.controller.handler import set_ev_cls 6 | from ryu.lib import hub 7 | 8 | class SimpleTrafficMonitor(simple_switch_13.SimpleSwitch13): 9 | 10 | def __init__(self, *args, **kwargs): 11 | super(SimpleTrafficMonitor, self).__init__(*args, **kwargs) 12 | self.datapaths = {} 13 | self.monitor_thread = hub.spawn(self._monitor) 14 | 15 | # Handling Asynchronous messages 16 | @set_ev_cls(ofp_event.EventOFPStateChange,[MAIN_DISPATCHER, DEAD_DISPATCHER]) 17 | def _state_change_handler(self, ev): 18 | datapath = ev.datapath 19 | tmFile = open("tmFile.txt","a+") 20 | if ev.state == MAIN_DISPATCHER: 21 | if datapath.id not in self.datapaths: 22 | self.logger.debug('register datapath: %016x', datapath.id) 23 | tmFile.write('register datapath: ' + str(datapath.id)) 24 | self.datapaths[datapath.id] = datapath 25 | elif ev.state == DEAD_DISPATCHER: 26 | if datapath.id in self.datapaths: 27 | self.logger.debug('unregister datapath: %016x', datapath.id) 28 | tmFile.write('unregister datapath: '+ str(datapath.id)) 29 | del self.datapaths[datapath.id] 30 | tmFile.close() 31 | 32 | # Monitoring and collecting statistic information 33 | def _monitor(self): 34 | while True: 35 | for dp in self.datapaths.values(): 36 | self._request_stats(dp) 37 | hub.sleep(10) 38 | 39 | def _request_stats(self, datapath): 40 | self.logger.debug('send stats request: %016x', datapath.id) 41 | ofproto = datapath.ofproto 42 | parser = datapath.ofproto_parser 43 | 44 | req = parser.OFPFlowStatsRequest(datapath) 45 | datapath.send_msg(req) 46 | 47 | req = parser.OFPPortStatsRequest(datapath, 0, ofproto.OFPP_ANY) 48 | datapath.send_msg(req) 49 | 50 | req = parser.OFPGroupStatsRequest(datapath, 0, ofp.OFPG_ALL) 51 | datapath.send_msg(req) 52 | 53 | req = ofp_parser.OFPMeterStatsRequest(datapath, 0, ofp.OFPM_ALL) 54 | datapath.send_msg(req) 55 | 56 | 57 | @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER) 58 | def _flow_stats_reply_handler(self, ev): 59 | '''body = ev.msg.body 60 | 61 | tmFile = open("tmFile.txt","a+") 62 | self.logger.info('datapath in-port eth-dst out-port packets bytes') 63 | self.logger.info('---------------- -------- ----------------- -------- -------- --------') 64 | tmFile.write('datapath in-port eth-dst out-port packets bytes') 65 | tmFile.write('---------------- -------- ----------------- -------- -------- --------') 66 | for stat in sorted([flow for flow in body if flow.priority == 1], 67 | key=lambda flow: (flow.match['in_port'], 68 | flow.match['eth_dst'])): 69 | self.logger.info('%016x %8x %17s %8x %8d %8d', 70 | ev.msg.datapath.id, 71 | stat.match['in_port'], stat.match['eth_dst'], 72 | stat.instructions[0].actions[0].port, 73 | stat.packet_count, stat.byte_count) 74 | tmFile.write( 75 | str(ev.msg.datapath.id)+" "+ 76 | str(stat.match['in_port'])+" "+ str(stat.match['eth_dst'])+ " "+ 77 | str(stat.instructions[0].actions[0].port)+ " "+ 78 | str(stat.packet_count)+ " "+ str(stat.byte_count)) 79 | tmFile.close()''' 80 | tmFile = open("tmFile.txt","a+") 81 | flows = [] 82 | for stat in ev.msg.body: 83 | flows.append('table_id=%s ' 84 | 'duration_sec=%d duration_nsec=%d ' 85 | 'priority=%d ' 86 | 'idle_timeout=%d hard_timeout=%d flags=0x%04x ' 87 | 'cookie=%d packet_count=%d byte_count=%d ' 88 | 'match=%s instructions=%s' % 89 | (stat.table_id, 90 | stat.duration_sec, stat.duration_nsec, 91 | stat.priority, 92 | stat.idle_timeout, stat.hard_timeout, stat.flags, 93 | stat.cookie, stat.packet_count, stat.byte_count, 94 | stat.match, stat.instructions)) 95 | self.logger.debug('FlowStats: %s', flows) 96 | tmFile.write(str(flows)) 97 | tmFile.close() 98 | 99 | @set_ev_cls(ofp_event.EventOFPPortStatsReply, MAIN_DISPATCHER) 100 | def _port_stats_reply_handler(self, ev): 101 | body = ev.msg.body 102 | tmFile = open("tmFile.txt","a+") 103 | self.logger.info('datapath port rx-pkts rx-bytes rx-error tx-pkts tx-bytes tx-error') 104 | self.logger.info('---------------- -------- -------- -------- -------- -------- -------- --------') 105 | tmFile.write('datapath port rx-pkts rx-bytes rx-error tx-pkts tx-bytes tx-error') 106 | tmFile.write('---------------- -------- -------- -------- -------- -------- -------- --------') 107 | for stat in sorted(body, key=attrgetter('port_no')): 108 | self.logger.info('%016x %8x %8d %8d %8d %8d %8d %8d', 109 | ev.msg.datapath.id, stat.port_no, 110 | stat.rx_packets, stat.rx_bytes, stat.rx_errors, 111 | stat.tx_packets, stat.tx_bytes, stat.tx_errors) 112 | tmFile.write( 113 | str(ev.msg.datapath.id)+" "+ str(stat.port_no) + " "+ 114 | str(stat.rx_packets)+" "+ str(stat.rx_bytes)+" "+ str(stat.rx_errors)+ " "+ 115 | str(stat.tx_packets)+ " "+ str(stat.tx_bytes)+" "+ str(stat.tx_errors)) 116 | tmFile.close() 117 | 118 | @set_ev_cls(ofp_event.EventOFPGroupStatsReply, MAIN_DISPATCHER) 119 | def group_stats_reply_handler(self, ev): 120 | tmFile = open("tmFile.txt","a+") 121 | groups = [] 122 | for stat in ev.msg.body: 123 | groups.append('length=%d group_id=%d ' 124 | 'ref_count=%d packet_count=%d byte_count=%d ' 125 | 'duration_sec=%d duration_nsec=%d' % 126 | (stat.length, stat.group_id, 127 | stat.ref_count, stat.packet_count, 128 | stat.byte_count, stat.duration_sec, 129 | stat.duration_nsec)) 130 | self.logger.debug('GroupStats: %s', groups) 131 | tmFile.write(str(groups)) 132 | tmFile.close() 133 | 134 | @set_ev_cls(ofp_event.EventOFPMeterStatsReply, MAIN_DISPATCHER) 135 | def meter_stats_reply_handler(self, ev): 136 | tmFile = open("tmFile.txt","a+") 137 | meters = [] 138 | for stat in ev.msg.body: 139 | meters.append('meter_id=0x%08x len=%d flow_count=%d ' 140 | 'packet_in_count=%d byte_in_count=%d ' 141 | 'duration_sec=%d duration_nsec=%d ' 142 | 'band_stats=%s' % 143 | (stat.meter_id, stat.len, stat.flow_count, 144 | stat.packet_in_count, stat.byte_in_count, 145 | stat.duration_sec, stat.duration_nsec, 146 | stat.band_stats)) 147 | self.logger.debug('MeterStats: %s', meters) 148 | tmFile.write(str(meters)) 149 | tmFile.close() --------------------------------------------------------------------------------