def load_config(self): """ Parses the parameters received and instantiates the apps requested. """ # Get CLI params and call the pcapy loop self.cap, self.packet_number, \ self.load_apps, sanitizer, \ topo_file, is_to_save = get_params(sys.argv) self.sanitizer.process_filters(sanitizer) # Load TopologyReader self.topo_reader.readfile(topo_file) # Save to File self.save_to_file = save_to_file(is_to_save) # Start Apps self.ofp_proxy = OFProxy() if 'oess_fvd' in self.load_apps: self.oft = OessFvdTracer(self.load_apps['oess_fvd']) if 'statistics' in self.load_apps: self.stats = OFStats() if 'influx' in self.load_apps: self.influx = InfluxClient(trigger_event=self.trigger_event) if 'notifications' in self.load_apps: self.notifications = Notifications(self.load_apps['notifications'])
def _update_tcp_reconnects(self): """ Update the number of TCP Reconnects on InfluxDB """ OFStats().num_reconnects json_body = [{ "measurement": "OFP_messages", "tags": { "controllers": "tcp" }, "time": "{0}".format(datetime.datetime.utcnow().isoformat('T')), "fields": { "reconnects": OFStats().num_reconnects } }] self.logger.debug(json_body) self.db_client.write_points(json_body)
def _update_per_dpid(self): """ This method updates stats per dpid on InfluxDB TODO: currently, OFStats().per_dev_packet_type is empty """ dpids = OFStats().per_dev_packet_types.keys() self.logger.debug("dpids: {0}".format(dpids)) for dpid in dpids: json_body = [{ "measurement": "OFP_messages", "tags": { "dpid": dpid }, "time": "{0}".format(datetime.datetime.utcnow().isoformat('T')), "fields": OFStats().per_dev_packet_types[dpid] }] self.logger.debug(json_body) self.db_client.write_points(json_body)
def load_config(self): """ Parses the parameters received and instantiates the apps requested. """ # Get CLI params and call the pcapy loop self.cap, self.packet_number, \ self.load_apps, sanitizer, topo_file = get_params(sys.argv) self.sanitizer.process_filters(sanitizer) # Load TopologyReader self.topo_reader.readfile(topo_file) # Start Apps if 'oess_fvd' in self.load_apps: self.oft = OessFvdTracer() if 'statistics' in self.load_apps: self.stats = OFStats() # Load Proxy self.ofp_proxy = OFProxy()
def _update_packet_types(self): """Update OpenFlow version global stats on InfluxDB """ for v, fields in OFStats().packet_types.items(): json_body = [{ "measurement": "OFP_messages", "tags": { "OFP_version": v }, "time": "{0}".format(datetime.datetime.utcnow().isoformat('T')), "fields": fields }] self.logger.debug(json_body) self.db_client.write_points(json_body)
class RunSniffer(object): """ The RunSniffer class is the main class for the OpenFlow Sniffer. This class instantiate all auxiliary classes, captures the packets, instantiate new OpenFlow messages and triggers all applications. """ def __init__(self): self.printing_options = PrintingOptions() self.sanitizer = Sanitizer() self.oft = None self.stats = None self.influx = None self.notifications = None self.trigger_event = threading.Event() self.cap = None self.packet_number = None self.load_apps = dict() self.packet_count = 1 self.topo_reader = TopoReader() self.save_to_file = None self.ofp_proxy = None self.load_config() def load_config(self): """ Parses the parameters received and instantiates the apps requested. """ # Get CLI params and call the pcapy loop self.cap, self.packet_number, \ self.load_apps, sanitizer, \ topo_file, is_to_save = get_params(sys.argv) self.sanitizer.process_filters(sanitizer) # Load TopologyReader self.topo_reader.readfile(topo_file) # Save to File self.save_to_file = save_to_file(is_to_save) # Start Apps self.ofp_proxy = OFProxy() if 'oess_fvd' in self.load_apps: self.oft = OessFvdTracer(self.load_apps['oess_fvd']) if 'statistics' in self.load_apps: self.stats = OFStats() if 'influx' in self.load_apps: self.influx = InfluxClient(trigger_event=self.trigger_event) if 'notifications' in self.load_apps: self.notifications = Notifications(self.load_apps['notifications']) def run(self): """ cap.loop continuously capture packets w/ pcapy. For every captured packet, self.process_packet method is called. Exits: 0 - Normal, reached end of file 1 - Normal, user requested with CRTL + C 2 - Error 3 - Interface or file not found """ exit_code = 0 # DEBUG: # self.cap.loop(-1, self.process_packet) try: self.cap.loop(-1, self.process_packet) except EndOfPcapFile: exit_code = 3 except KeyboardInterrupt: exit_code = 1 except Exception as exception: print('Error on packet %s: %s ' % (self.packet_count, exception)) exit_code = 2 finally: if 'statistics' in self.load_apps: # If OFP_Stats is running, set a timer # before closing the app. Useful in cases # where the ofp_sniffer is reading from a # pcap file instead of a NIC. time.sleep(200) # pass print('Exiting with code: %s' % exit_code) # gracefully shut down if 'influx' in self.load_apps: self.influx.stop_event.set() sys.exit(exit_code) def process_packet(self, header, packet): """ Every packet captured by cap.loop is then processed here. If packets are bigger than 62 Bytes, we process them. If it is 0, means there are no more packets. If it is something in between, it is a fragment, we ignore for now. Args: header: header of the captured packet packet: packet captured from file or interface """ if len(packet) >= 54: # Verify if user asked for just one specific packet if self.was_packet_number_defined(): if not self.is_the_packet_number_specified(): self.packet_count += 1 return # DEBUG: # print("Packet Number: %s" % self.packet_count) pkt = Packet(packet, self.packet_count, header) if pkt.reconnect_error: if isinstance(self.stats, OFStats): # OFStats counts reconnects self.stats.process_packet(pkt) if isinstance(self.notifications, Notifications): # Send notifications via Slack self.notifications.send_msg(pkt) elif pkt.is_openflow_packet: valid_result = pkt.process_openflow_messages() if valid_result: # Apps go here: if isinstance(self.oft, OessFvdTracer): # FVD_Tracer does not print the packets self.oft.process_packet(pkt) if isinstance(self.ofp_proxy, OFProxy): # OFP_PROXY associates IP:PORT to DPID self.ofp_proxy.process_packet(pkt) if isinstance(self.stats, OFStats): # OFStats print the packets self.stats.process_packet(pkt) if isinstance(self.notifications, Notifications): # Send notifications via Slack self.notifications.send_msg(pkt) if not isinstance(self.oft, OessFvdTracer): # Print Packets pkt.print_packet() if self.influx: # tell influx to wake up and update immediately self.trigger_event.set() del pkt if self.is_the_packet_number_specified(): # If a specific packet was selected, end here. raise EndOfPcapFile elif len(packet) is 0: return 3 self.packet_count += 1 def was_packet_number_defined(self): """ In case user wants to see a specific packet inside a specific pcap file, provide file name with the specific packet number after ":" -r file.pcap:packet_number Returns: True if a packet number was specified False: if a packet number was not specified """ if self.packet_number != 0: return True return False def is_the_packet_number_specified(self): """ If user wants to see a specific packet inside a specific pcap file and the packet_count is that number, return True. Otherwise, return false Returns: True if packet_count matches False: if packet_count does not match """ return True if self.packet_count == self.packet_number else False
class RunSniffer(object): """ The RunSniffer class is the main class for the OpenFlow Sniffer. This class instantiate all auxiliary classes, captures the packets, instantiate new OpenFlow messages and triggers all applications. """ def __init__(self): self.printing_options = PrintingOptions() self.sanitizer = Sanitizer() self.oft = None self.stats = None self.cap = None self.packet_number = None self.load_apps = [] self.packet_count = 1 self.topo_reader = TopoReader() self.ofp_proxy = None self.load_config() def load_config(self): """ Parses the parameters received and instantiates the apps requested. """ # Get CLI params and call the pcapy loop self.cap, self.packet_number, \ self.load_apps, sanitizer, topo_file = get_params(sys.argv) self.sanitizer.process_filters(sanitizer) # Load TopologyReader self.topo_reader.readfile(topo_file) # Start Apps if 'oess_fvd' in self.load_apps: self.oft = OessFvdTracer() if 'statistics' in self.load_apps: self.stats = OFStats() # Load Proxy self.ofp_proxy = OFProxy() def run(self): """ cap.loop continuously capture packets w/ pcapy. For every captured packet, self.process_packet method is called. Exits: 0 - Normal, reached end of file 1 - Normal, user requested with CRTL + C 2 - Error 3 - Interface or file not found """ exit_code = 0 # Debug: # self.cap.loop(-1, self.process_packet) try: self.cap.loop(-1, self.process_packet) if 'statistics' in self.load_apps: # If OFP_Stats is running, set a timer # before closing the app. Useful in cases # where the ofp_sniffer is reading from a # pcap file instead of real time. time.sleep(200) except KeyboardInterrupt: exit_code = 1 except Exception as exception: print('Error on packet %s: %s ' % (self.packet_count, exception)) exit_code = 2 finally: print('Exiting...') sys.exit(exit_code) def process_packet(self, header, packet): """ Every packet captured by cap.loop is then processed here. If packets are bigger than 62 Bytes, we process them. If it is 0, means there are no more packets. If it is something in between, it is a fragment, we ignore for now. Args: header: header of the captured packet packet: packet captured from file or interface """ if len(packet) >= 62 and self.packet_number_defined(): # DEBUG: # print("Packet Number: %s" % self.packet_count) pkt = Packet(packet, self.packet_count, header) if pkt.is_openflow_packet: valid_result = pkt.process_openflow_messages() if valid_result: # Apps go here: if isinstance(self.oft, OessFvdTracer): # FVD_Tracer does not print the packets self.oft.process_packet(pkt) if isinstance(self.ofp_proxy, OFProxy): # OFP_PROXY associates IP:PORT to DPID self.ofp_proxy.process_packet(pkt) if isinstance(self.stats, OFStats): # OFStats print the packets self.stats.process_packet(pkt) if not isinstance(self.oft, OessFvdTracer): # Print Packets pkt.print_packet() del pkt elif len(packet) is 0: sys.exit(0) self.packet_count += 1 def packet_number_defined(self): """ In case user wants to see a specific packet inside a specific pcap file, provide file name with the specific packet number -r file.pcap:packet_number Returns: True if packet_count matches False: if packet_count does not match """ if self.packet_number > 0: return True if self.packet_count == self.packet_number else False return True