def __init__(self, *args, **kwargs): super(Dashboard, self).__init__(*args, **kwargs) self.config_file = os.getenv('GAUGE_CONFIG', '/etc/ryu/faucet/gauge.conf') self.logger = self.create_logger() self.dps = {} with open(self.config_file, 'r') as config_file: for dp_conf_file in config_file: # config_file should be a list of faucet config filenames # separated by linebreaks dp = DP.parser(dp_conf_file.strip(), self.logname) try: dp.sanity_check() self.valve = valve_factory(dp) except AssertionError: self.logger.exception( "Error in config file {0}".format(dp_conf_file)) else: self.dps[dp.dp_id] = dp # Create dpset object for querying Ryu's DPSet application self.dpset = kwargs['dpset'] # dict of polling threads: # polling threads are indexed by dp_id and then by name # eg: self.pollers[0x1]['port_stats'] self.pollers = {} # dict of async event handlers self.handlers = {} self.redis_flush_thread = hub.spawn(self.redis_flush_request)
def parse_config(self, config_file, log_name): new_dp = DP.parser(config_file, log_name) if new_dp: try: new_dp.sanity_check() return new_dp except AssertionError: self.logger.exception("Error in config file:") return None
def __init__(self, *args, **kwargs): super(Gauge, self).__init__(*args, **kwargs) self.config_file = os.getenv( 'GAUGE_CONFIG', '/etc/sdx/gauge.conf') self.config_dir = os.path.dirname(self.config_file) self.exc_logfile = os.getenv( 'GAUGE_EXCEPTION_LOG', '/var/log/sdx/gauge_exception.log') self.logfile = os.getenv('GAUGE_LOG', '/var/log/sdx/gauge.log') # Setup logging self.logger = logging.getLogger(__name__) logger_handler = TimedRotatingFileHandler( self.logfile, when='midnight') log_fmt = '%(asctime)s %(name)-6s %(levelname)-8s %(message)s' date_fmt = '%b %d %H:%M:%S' default_formatter = logging.Formatter(log_fmt, date_fmt) logger_handler.setFormatter(default_formatter) self.logger.addHandler(logger_handler) self.logger.propagate = 0 # Set up separate logging for exceptions exc_logger = logging.getLogger(self.exc_logname) exc_logger_handler = logging.FileHandler(self.exc_logfile) exc_logger_handler.setFormatter( logging.Formatter(log_fmt, date_fmt)) exc_logger.addHandler(exc_logger_handler) exc_logger.propagate = 1 exc_logger.setLevel(logging.ERROR) # Prevent printing of the 'Starting new HTTP requests' messages logging.getLogger("urllib3").setLevel(logging.WARNING) self.dps = {} with open(self.config_file, 'r') as config_file: for dp_conf_file in config_file: # config_file should be a list of faucet config filenames # separated by linebreaks dp = DP.parser(os.path.join(self.config_dir, dp_conf_file.strip()), self.logname) try: dp.sanity_check() except AssertionError: self.logger.exception( "Error in config file {0}".format(dp_conf_file)) else: self.dps[dp.dp_id] = dp # Create dpset object for querying Ryu's DPSet application self.dpset = kwargs['dpset'] # dict of polling threads: # polling threads are indexed by dp_id and then by name # eg: self.pollers[0x1]['port_stats'] self.pollers = {} # dict of async event handlers self.handlers = {}
def __init__(self, *args, **kwargs): super(Faucet, self).__init__(*args, **kwargs) # There doesnt seem to be a sensible method of getting command line # options into ryu apps. Instead I am using the environment variable # FAUCET_CONFIG to allow this to be set, if it is not set it will # default to valve.yaml self.config_file = os.getenv( 'FAUCET_CONFIG', '/etc/opt/faucet/valve.yaml') self.logfile = os.getenv( 'FAUCET_LOG', '/var/log/faucet/faucet.log') self.exc_logfile = os.getenv( 'FAUCET_EXCEPTION_LOG', '/var/log/faucet/faucet_exception.log') # Set the signal handler for reloading config file signal.signal(signal.SIGHUP, self.signal_handler) # Create dpset object for querying Ryu's DPSet application self.dpset = kwargs['dpset'] # Setup logging self.logger = logging.getLogger(self.logname) logger_handler = TimedRotatingFileHandler( self.logfile, when='midnight') log_fmt = '%(asctime)s %(name)-6s %(levelname)-8s %(message)s' logger_handler.setFormatter( logging.Formatter(log_fmt, '%b %d %H:%M:%S')) self.logger.addHandler(logger_handler) self.logger.propagate = 0 self.logger.setLevel(logging.DEBUG) # Set up separate logging for exceptions exc_logger = logging.getLogger(self.exc_logname) exc_logger_handler = logging.FileHandler(self.exc_logfile) exc_logger_handler.setFormatter( logging.Formatter(log_fmt, '%b %d %H:%M:%S')) exc_logger.addHandler(exc_logger_handler) exc_logger.propagate = 1 exc_logger.setLevel(logging.CRITICAL) # Parse config file dp = DP.parser(self.config_file, self.logname) if dp: try: dp.sanity_check() except AssertionError: self.logger.exception("Error in config file:") # Load Valve self.valve = valve_factory(dp) if self.valve is None: self.logger.error("Hardware type not supported")
def test_reload_drop(self): """Test that after a config reload packets with invalid vlan tags are dropped. """ match = { 'in_port': 3, 'vlan_vid': 11|ofp.OFPVID_PRESENT} new_dp = DP.parser("tests/config/valve-test-reload.yaml") ofmsgs = self.valve.reload_config(new_dp) self.table.apply_ofmsgs(ofmsgs) self.assertFalse( self.table.is_output(match), msg='Output action when packet should be dropped after reload')
def test_reload_unknown_eth_dst_rule(self): """Test that packets with unkown eth dst addrs get flooded correctly after a config reload. They must be output to each currently running port on the associated vlan, with the correct vlan tagging.""" matches = [ {'in_port': 4}, {'in_port': 3, 'vlan_vid': 10|ofp.OFPVID_PRESENT}, { 'in_port': 3, 'vlan_vid': 10|ofp.OFPVID_PRESENT, 'eth_src': "00:00:00:00:00:01"}, {'in_port': 2, 'vlan_vid': 11|ofp.OFPVID_PRESENT}, { 'in_port': 2, 'vlan_vid': 11|ofp.OFPVID_PRESENT, 'eth_dst': "00:00:00:00:00:01"}, {'in_port': 2, 'vlan_vid': 10|ofp.OFPVID_PRESENT}, {'in_port': 1, 'eth_src': "00:00:00:00:00:03"}, {'in_port': 1}] dp = DP.parser("tests/config/valve-test-reload.yaml") ofmsgs = self.valve.reload_config(dp) self.table.apply_ofmsgs(ofmsgs) for match in matches: in_port = match['in_port'] if 'vlan_vid' in match: vlan = dp.vlans[match['vlan_vid'] & ~ofp.OFPVID_PRESENT] else: # if a tagged port arrives on an untagged interface, we can # ignore the label vlan = dp.get_native_vlan(in_port) # the ports that have not yet had packets output to them remaining_ports = set(range(1, 7)) for p in vlan.get_ports(): remaining_ports.discard(p.number) if p.number != in_port and p.running(): if vlan.port_is_tagged(p.number): vid = vlan.vid|ofp.OFPVID_PRESENT else: vid = 0 self.assertTrue( self.table.is_output(match, port=p.number, vlan=vid), msg="packet ({0}) not output correctly to port {1} on " "vlan {2} when flooding after reload".format(match, p.number, vid)) for p in remaining_ports: self.assertFalse( self.table.is_output(match, p), msg="packet output to port not on vlan after reload")
def setUp(self): dp = DP.parser("tests/config/valve-test.yaml") self.valve = OVSStatelessValve(dp) self.table = FakeOFTable() self.table.apply_ofmsgs(self.valve.datapath_connect(1, [1,2,3,4,5,6])) rcv_packet_ofmsgs = self.valve.rcv_packet( dp_id=1, in_port=1, vlan_vid=10, eth_src="00:00:00:00:00:01", eth_dst="00:00:00:00:00:02") self.table.apply_ofmsgs(rcv_packet_ofmsgs) rcv_packet_ofmsgs = self.valve.rcv_packet( dp_id=1, in_port=3, vlan_vid=11, eth_src="00:00:00:00:00:03", eth_dst="00:00:00:00:00:04") self.table.apply_ofmsgs(rcv_packet_ofmsgs)
def signal_handler(self, sigid, frame): if sigid == signal.SIGHUP: self.logger.info("Caught SIGHUP, reloading configuration") new_config_file = os.getenv('FAUCET_CONFIG', self.config_file) new_dp = DP.parser(new_config_file, self.logname) if new_dp: try: new_dp.sanity_check() except AssertionError: self.logger.exception("Error in config file:") flowmods = self.valve.reload_config(new_dp) ryudp = self.dpset.get(new_dp.dp_id) for f in flowmods: # OpenFlow Message objects in ryu require a ryu datapath # object f.datapath = ryudp ryudp.send_msg(f)
def test_reload_port_disable(self): """Test that when a port is disabled in a reload packets are not output to it. """ matches = [ {'in_port': 4}, { 'in_port': 2, 'vlan_vid': 11|ofp.OFPVID_PRESENT, 'eth_dst': "00:00:00:00:00:05"}] rcv_packet_ofmsgs = self.valve.rcv_packet( dp_id=1, in_port=5, vlan_vid=11, eth_src="00:00:00:00:00:05", eth_dst="00:00:00:00:00:06") self.table.apply_ofmsgs(rcv_packet_ofmsgs) dp = DP.parser("tests/config/valve-test-reload.yaml") ofmsgs = self.valve.reload_config(dp) self.table.apply_ofmsgs(ofmsgs) for match in matches: self.assertFalse( self.table.is_output(match, port=5), msg="packet output to disabled port")
def setUp(self): self.dp = DP.parser('config/testconfig.yaml')