示例#1
0
def _watcher_parser_v2(conf, logname, prom_client):
    logger = config_parser_util.get_logger(logname)
    result = []

    if conf is None:
        conf = {}

    dps = {}
    if 'faucet_configs' in conf:
        for faucet_file in conf['faucet_configs']:
            _, dp_list = dp_parser(faucet_file, logname)
            if dp_list:
                for dp in dp_list:
                    dps[dp.name] = dp

    if 'faucet' in conf:
        faucet_conf = conf['faucet']
        acls = faucet_conf.get('acls', {})
        fct_dps = faucet_conf.get('dps', {})
        meters = faucet_conf.get('meters', {})
        routers = faucet_conf.get('routers', {})
        vlans = faucet_conf.get('vlans', {})
        for dp in _dp_parser_v2(acls, fct_dps, meters, routers, vlans):
            dps[dp.name] = dp

    if not dps:
        raise InvalidConfigError(
            'Gauge configured without any FAUCET configuration')

    dbs = conf.pop('dbs')

    # pylint: disable=fixme
    for watcher_name, watcher_conf in list(conf['watchers'].items()):
        if watcher_conf.get('all_dps', False):
            watcher_dps = list(dps.keys())
        else:
            watcher_dps = watcher_conf['dps']
        # Watcher config has a list of DPs, but actually a WatcherConf is
        # created for each DP.
        # TODO: refactor watcher_conf as a container.
        for dp_name in watcher_dps:
            if dp_name not in dps:
                logger.error('DP %s in Gauge but not configured in FAUCET',
                             dp_name)
                continue
            dp = dps[dp_name]
            if 'dbs' in watcher_conf:
                watcher_dbs = watcher_conf['dbs']
            elif 'db' in watcher_conf:
                watcher_dbs = [watcher_conf['db']]
            else:
                raise InvalidConfigError('Watcher configured without DB')
            for db in watcher_dbs:
                watcher = WatcherConf(watcher_name, dp.dp_id, watcher_conf,
                                      prom_client)
                watcher.add_db(dbs[db])
                watcher.add_dp(dp)
                result.append(watcher)

    return result
示例#2
0
文件: acl.py 项目: girishprb/faucet
    def build(self, meters, vid, port_num):
        """Check that ACL can be built from config."""
        class NullRyuDatapath:
            """Placeholder Ryu Datapath."""
            ofproto = valve_of.ofp

        self.matches = {}
        self.set_fields = set()
        self.meter = False
        if self.rules:
            try:
                ofmsgs = valve_acl.build_acl_ofmsgs(
                    [self],
                    wildcard_table,
                    valve_of.goto_table(wildcard_table),
                    valve_of.goto_table(wildcard_table),
                    2**16 - 1,
                    meters,
                    self.exact_match,
                    vlan_vid=vid,
                    port_num=port_num)
            except (netaddr.core.AddrFormatError, KeyError, ValueError) as err:
                raise InvalidConfigError(err)
            test_config_condition(not ofmsgs, 'OF messages is empty')
            for ofmsg in ofmsgs:
                ofmsg.datapath = NullRyuDatapath()
                ofmsg.set_xid(0)
                try:
                    ofmsg.serialize()
                except (KeyError, ValueError) as err:
                    raise InvalidConfigError(err)
                except Exception as err:
                    print(ofmsg)
                    raise err
                if valve_of.is_flowmod(ofmsg):
                    apply_actions = []
                    for inst in ofmsg.instructions:
                        if valve_of.is_apply_actions(inst):
                            apply_actions.extend(inst.actions)
                        elif valve_of.is_meter(inst):
                            self.meter = True
                    for action in apply_actions:
                        if valve_of.is_set_field(action):
                            self.set_fields.add(action.key)
                    for match, value in list(ofmsg.match.items()):
                        has_mask = isinstance(value, (tuple, list))
                        if has_mask or match not in self.matches:
                            self.matches[match] = has_mask
        return (self.matches, self.set_fields, self.meter)
示例#3
0
def watcher_factory(conf):
    """Return a Gauge object based on type.

    Args:
        conf (GaugeConf): object with the configuration for this valve.
    """

    watcher_types = {
        'port_state': {
            'text': GaugePortStateLogger,
            'influx': GaugePortStateInfluxDBLogger,
            'prometheus': GaugePortStatePrometheusPoller,
        },
        'port_stats': {
            'text': GaugePortStatsLogger,
            'influx': GaugePortStatsInfluxDBLogger,
            'prometheus': GaugePortStatsPrometheusPoller,
        },
        'flow_table': {
            'text': GaugeFlowTableLogger,
            'influx': GaugeFlowTableInfluxDBLogger,
            'prometheus': GaugeFlowTablePrometheusPoller,
        },
        'meter_stats': {
            'text': GaugeMeterStatsLogger,
            'prometheus': GaugeMeterStatsPrometheusPoller,
        },
    }

    w_type = conf.type
    db_type = conf.db_type
    try:
        return watcher_types[w_type][db_type]
    except KeyError as key_error:
        raise InvalidConfigError('invalid water config') from key_error
示例#4
0
 def build_acl(acl, vid=None):
     """Check that ACL can be built from config and mark mirror destinations."""
     if acl.rules:
         null_dp = namedtuple('null_dp', 'ofproto')
         null_dp.ofproto = valve_of.ofp
         try:
             ofmsgs = valve_acl.build_acl_ofmsgs(
                 [acl],
                 self.wildcard_table,
                 valve_of.goto_table(self.wildcard_table),
                 valve_of.goto_table(self.wildcard_table),
                 2**16 - 1,
                 self.meters,
                 acl.exact_match,
                 vlan_vid=vid)
             assert ofmsgs
             for ofmsg in ofmsgs:
                 ofmsg.datapath = null_dp
                 ofmsg.set_xid(0)
                 ofmsg.serialize()
         except (AddrFormatError, KeyError, ValueError) as err:
             raise InvalidConfigError(err)
         for port_no in mirror_destinations:
             port = self.ports[port_no]
             port.output_only = True
示例#5
0
文件: port.py 项目: MrCocoaCat/faucet
    def check_config(self):
        super(Port, self).check_config()
        test_config_condition(not (isinstance(self.number, int) and self.number > 0 and (
            not valve_of.ignore_port(self.number))), ('Port number invalid: %s' % self.number))
        test_config_condition(
            self.hairpin and self.hairpin_unicast,
            'Cannot have both hairpin and hairpin_unicast enabled')
        if self.dot1x:
            test_config_condition(self.number > 65535, (
                '802.1x not supported on ports > 65535'))
        if self.dot1x_acl:
            test_config_condition(not self.dot1x, (
                '802.1x_ACL requires dot1x to be enabled also'))
        if self.mirror:
            test_config_condition(self.tagged_vlans or self.native_vlan, (
                'mirror port %s cannot have any VLANs assigned' % self))
        if self.stack:
            self._check_conf_types(self.stack, self.stack_defaults_types)
            for stack_config in list(self.stack_defaults_types.keys()):
                test_config_condition(stack_config not in self.stack, (
                    'stack %s must be defined' % stack_config))
            # LLDP always enabled for stack ports.
            self.receive_lldp = True
            if not self.lldp_beacon_enabled():
                self.lldp_beacon.update({'enable': True})

        if self.lldp_beacon:
            self._check_conf_types(
                self.lldp_beacon, self.lldp_beacon_defaults_types)
            self.lldp_beacon = self._set_unknown_conf(
                self.lldp_beacon, self.lldp_beacon_defaults_types)
            if self.lldp_beacon_enabled():
                if self.lldp_beacon['port_descr'] is None:
                    self.lldp_beacon['port_descr'] = self.description

                org_tlvs = []
                for org_tlv in self.lldp_beacon['org_tlvs']:
                    self._check_conf_types(org_tlv, self.lldp_org_tlv_defaults_types)
                    test_config_condition(len(org_tlv) != len(self.lldp_org_tlv_defaults_types), (
                        'missing org_tlv config'))
                    if not isinstance(org_tlv['info'], bytearray):
                        try:
                            org_tlv['info'] = bytearray.fromhex(
                                org_tlv['info']) # pytype: disable=missing-parameter
                        except ValueError:
                            org_tlv['info'] = org_tlv['info'].encode('utf-8')
                    if not isinstance(org_tlv['oui'], bytearray):
                        org_tlv['oui'] = bytearray.fromhex(
                            '%6.6x' % org_tlv['oui']) # pytype: disable=missing-parameter
                    org_tlvs.append(org_tlv)
                self.lldp_beacon['org_tlvs'] = org_tlvs
        if self.acl_in and self.acls_in:
            raise InvalidConfigError('found both acl_in and acls_in, use only acls_in')
        if self.acl_in and not isinstance(self.acl_in, list):
            self.acls_in = [self.acl_in,]
            self.acl_in = None
        if self.acls_in:
            for acl in self.acls_in:
                test_config_condition(not isinstance(acl, (int, str)),
                                      'ACL names must be int or str')
示例#6
0
def _dp_parser_v2(dps_conf, acls_conf, meters_conf, routers_conf, vlans_conf,
                  meta_dp_state):

    dps = []
    for dp_key, dp_conf in dps_conf.items():
        try:
            dps.append(
                _parse_dp(dp_key, dp_conf, acls_conf, meters_conf,
                          routers_conf, vlans_conf))
        except InvalidConfigError as err:
            raise InvalidConfigError('DP %s: %s' % (dp_key, err))

    for dp in dps:
        dp.finalize_config(dps)
    for dp in dps:
        dp.resolve_stack_topology(dps, meta_dp_state)
    for dp in dps:
        dp.finalize()

    dpid_refs = set()
    for dp in dps:
        test_config_condition(dp.dp_id in dpid_refs,
                              ('DPID %u is duplicated' % dp.dp_id))
        dpid_refs.add(dp.dp_id)

    routers_referenced = set()
    for dp in dps:
        routers_referenced.update(dp.routers.keys())
    for router in routers_conf:
        test_config_condition(
            router not in routers_referenced,
            ('router %s configured but not used by any DP' % router))

    return dps
示例#7
0
def _config_parser_v2(config_file, logname, meta_dp_state):
    config_path = config_parser_util.dp_config_path(config_file)
    top_confs = {top_conf: {} for top_conf in V2_TOP_CONFS}
    config_hashes = {}
    config_contents = {}
    dps = None

    if not config_parser_util.dp_include(
            config_hashes, config_contents, config_path, logname, top_confs):
        raise InvalidConfigError('Error found while loading config file: %s' % config_path)

    if not top_confs['dps']:
        raise InvalidConfigError('DPs not configured in file: %s' % config_path)

    dps = dp_preparsed_parser(top_confs, meta_dp_state)
    return (config_hashes, config_contents, dps, top_confs)
示例#8
0
文件: acl.py 项目: vmastar/faucet
 def __init__(self, _id, dp_id, conf):
     self.rules = []
     self.exact_match = None
     self.meter = False
     self.matches = {}
     self.set_fields = set()
     for match_fields in (MATCH_FIELDS, OLD_MATCH_FIELDS):
         self.rule_types.update(
             {match: (str, int)
              for match in match_fields.keys()})
     conf = copy.deepcopy(conf)
     if isinstance(conf, dict):
         rules = conf.get('rules', [])
     elif isinstance(conf, list):
         rules = conf
         conf = {}
     else:
         raise InvalidConfigError('ACL conf is an invalid type %s' % _id)
     conf['rules'] = []
     for rule in rules:
         normalized_rule = rule
         if isinstance(rule, dict):
             normalized_rule = rule.get('rule', rule)
             if normalized_rule is None:
                 normalized_rule = {
                     k: v
                     for k, v in rule.items() if v is not None
                 }
         test_config_condition(not isinstance(normalized_rule, dict),
                               ('ACL rule is %s not %s (%s)' %
                                (type(normalized_rule), dict, rules)))
         conf['rules'].append(normalized_rule)
     super(ACL, self).__init__(_id, dp_id, conf)
示例#9
0
文件: acl.py 项目: girishprb/faucet
 def __init__(self, _id, dp_id, conf):
     self.rules = []
     self.exact_match = None
     self.meter = False
     self.matches = {}
     self.set_fields = set()
     conf = copy.deepcopy(conf)
     if isinstance(conf, dict):
         rules = conf.get('rules', [])
     elif isinstance(conf, list):
         rules = conf
         conf = {}
     else:
         raise InvalidConfigError('ACL conf is an invalid type %s' %
                                  self._id)
     conf['rules'] = []
     for rule in rules:
         test_config_condition(not isinstance(rule, dict),
                               ('ACL rule is %s not %s' %
                                (type(rule), dict)))
         if 'rule' in rule:
             conf['rules'].append(rule['rule'])
         else:
             conf['rules'].append(rule)
     super(ACL, self).__init__(_id, dp_id, conf)
示例#10
0
def build_tunnel_ofmsgs(rule_conf, acl_table, priority,
                        port_num=None, vlan_vid=None, flowdel=False,
                        reverse=False):
    """Build a specific tunnel only ofmsgs"""
    ofmsgs = []
    acl_inst = []
    acl_match = []
    acl_match_dict = {}
    _, output_actions, output_ofmsgs, output_inst = build_output_actions(acl_table, rule_conf)
    ofmsgs.extend(output_ofmsgs)
    acl_inst.extend(output_inst)
    acl_inst.append(valve_of.apply_actions(output_actions))
    if port_num is not None:
        acl_match_dict['in_port'] = port_num
    if vlan_vid is not None:
        acl_match_dict['vlan_vid'] = valve_of.vid_present(vlan_vid)
    if reverse:
        acl_match_dict['vlan_pcp'] = valve_of.PCP_TUNNEL_REVERSE_DIRECTION_FLAG
    else:
        acl_match_dict['vlan_pcp'] = valve_of.PCP_TUNNEL_FLAG
    try:
        acl_match = valve_of.match_from_dict(acl_match_dict)
    except TypeError as type_error:
        raise InvalidConfigError('invalid match type in ACL') from type_error
    flowmod = acl_table.flowmod(acl_match, priority=priority, inst=tuple(acl_inst))
    if flowdel:
        ofmsgs.append(acl_table.flowdel(match=acl_match, priority=priority, strict=False))
    ofmsgs.append(flowmod)
    return ofmsgs
示例#11
0
文件: vlan.py 项目: trungdtbk/faucet
    def check_config(self):
        super(VLAN, self).check_config()
        test_config_condition(not self.vid_valid(self.vid), 'invalid VID %s' % self.vid)
        test_config_condition(not netaddr.valid_mac(self.faucet_mac), (
            'invalid MAC address %s' % self.faucet_mac))

        test_config_condition(
            self.acl_in and self.acls_in, 'found both acl_in and acls_in, use only acls_in')
        test_config_condition(
            self.acl_out and self.acls_out, 'found both acl_out and acls_out, use only acls_out')
        if self.acl_in and not isinstance(self.acl_in, list):
            self.acls_in = [self.acl_in,]
            self.acl_in = None
        if self.acl_out and not isinstance(self.acl_out, list):
            self.acls_out = [self.acl_out,]
            self.acl_out = None
        all_acls = []
        if self.acls_in:
            all_acls.extend(self.acls_in)
        if self.acls_out:
            all_acls.extend(self.acls_out)
        for acl in all_acls:
            test_config_condition(
                not isinstance(acl, (int, str)), 'acl names must be int or str')

        if self.max_hosts:
            if not self.proactive_arp_limit:
                self.proactive_arp_limit = 2 * self.max_hosts
            if not self.proactive_nd_limit:
                self.proactive_nd_limit = 2 * self.max_hosts

        if self.faucet_vips:
            self.faucet_vips = frozenset([
                self._check_ip_str(ip_str, ip_method=ipaddress.ip_interface)
                for ip_str in self.faucet_vips])
            for faucet_vip in self.faucet_vips:
                test_config_condition(
                    faucet_vip.network.prefixlen == faucet_vip.max_prefixlen,
                    'VIP cannot be a host address')

        if self.routes:
            test_config_condition(not isinstance(self.routes, list), 'invalid VLAN routes format')
            try:
                self.routes = [route['route'] for route in self.routes]
            except TypeError:
                raise InvalidConfigError('%s is not a valid routes value' % self.routes)
            except KeyError:
                pass
            for route in self.routes:
                test_config_condition(not isinstance(route, dict), 'invalid VLAN route format')
                test_config_condition('ip_gw' not in route, 'missing ip_gw in VLAN route')
                test_config_condition('ip_dst' not in route, 'missing ip_dst in VLAN route')
                ip_gw = self._check_ip_str(route['ip_gw'])
                ip_dst = self._check_ip_str(route['ip_dst'], ip_method=ipaddress.ip_network)
                test_config_condition(
                    ip_gw.version != ip_dst.version,
                    'ip_gw version does not match the ip_dst version')
                self.add_route(ip_dst, ip_gw)
示例#12
0
文件: dp.py 项目: lantz/faucet2
 def build_acl(acl, vid):
     """Check that ACL can be built from config and mark mirror destinations."""
     matches = {}
     set_fields = set()
     meter = False
     if acl.rules:
         try:
             ofmsgs = valve_acl.build_acl_ofmsgs(
                 [acl],
                 self.wildcard_table,
                 valve_of.goto_table(self.wildcard_table),
                 valve_of.goto_table(self.wildcard_table),
                 2**16 - 1,
                 self.meters,
                 acl.exact_match,
                 vlan_vid=vid)
         except (netaddr.core.AddrFormatError, KeyError,
                 ValueError) as err:
             raise InvalidConfigError(err)
         test_config_condition(not ofmsgs, 'OF messages is empty')
         for ofmsg in ofmsgs:
             ofmsg.datapath = NullRyuDatapath()
             ofmsg.set_xid(0)
             try:
                 ofmsg.serialize()
             except (KeyError, ValueError) as err:
                 raise InvalidConfigError(err)
             if valve_of.is_flowmod(ofmsg):
                 apply_actions = []
                 for inst in ofmsg.instructions:
                     if valve_of.is_apply_actions(inst):
                         apply_actions.extend(inst.actions)
                     elif valve_of.is_meter(inst):
                         meter = True
                 for action in apply_actions:
                     if valve_of.is_set_field(action):
                         set_fields.add(action.key)
                 for match, value in list(ofmsg.match.items()):
                     has_mask = isinstance(value, (tuple, list))
                     if has_mask or match not in matches:
                         matches[match] = has_mask
         for port_no in mirror_destinations:
             port = self.ports[port_no]
             port.output_only = True
     return (matches, set_fields, meter)
示例#13
0
 def _map_port_num_to_port(ports_conf):
     port_num_to_port_conf = {}
     for port_key, port_conf in ports_conf.items():
         test_config_condition(not isinstance(port_conf, dict), 'Invalid syntax in port config')
         port_num = port_conf.get('number', port_key)
         try:
             port_num_to_port_conf[port_num] = (port_key, port_conf)
         except TypeError as type_error:
             raise InvalidConfigError('Invalid syntax in port config') from type_error
     return port_num_to_port_conf
示例#14
0
    def check_config(self):
        super(Port, self).check_config()
        test_config_condition(
            not (isinstance(self.number, int) and self.number > 0 and
                 (not valve_of.ignore_port(self.number))),
            ('Port number invalid: %s' % self.number))
        if self.mirror:
            test_config_condition(
                self.tagged_vlans or self.native_vlan,
                ('mirror port %s cannot have any VLANs assigned' % self))
        if self.stack:
            self._check_conf_types(self.stack, self.stack_defaults_types)
            for stack_config in list(self.stack_defaults_types.keys()):
                test_config_condition(
                    stack_config not in self.stack,
                    ('stack %s must be defined' % stack_config))
        if self.lldp_beacon:
            self._check_conf_types(self.lldp_beacon,
                                   self.lldp_beacon_defaults_types)
            self.lldp_beacon = self._set_unknown_conf(
                self.lldp_beacon, self.lldp_beacon_defaults_types)
            if self.lldp_beacon_enabled():
                if self.lldp_beacon['port_descr'] is None:
                    self.lldp_beacon['port_descr'] = self.description

                org_tlvs = []
                for org_tlv in self.lldp_beacon['org_tlvs']:
                    self._check_conf_types(org_tlv,
                                           self.lldp_org_tlv_defaults_types)
                    test_config_condition(
                        len(org_tlv) != len(self.lldp_org_tlv_defaults_types),
                        ('missing org_tlv config'))
                    if not isinstance(org_tlv['info'], bytearray):
                        try:
                            org_tlv['info'] = bytearray.fromhex(
                                org_tlv['info'])  # pytype: disable=missing-parameter
                        except ValueError:
                            org_tlv['info'] = org_tlv['info'].encode('utf-8')
                    if not isinstance(org_tlv['oui'], bytearray):
                        org_tlv['oui'] = bytearray.fromhex(
                            '%6.6x' % org_tlv['oui'])  # pytype: disable=missing-parameter
                    org_tlvs.append(org_tlv)
                self.lldp_beacon['org_tlvs'] = org_tlvs
        if self.acl_in and self.acls_in:
            raise InvalidConfigError(
                'found both acl_in and acls_in, use only acls_in')
        if self.acl_in and not isinstance(self.acl_in, list):
            self.acls_in = [
                self.acl_in,
            ]
            self.acl_in = None
        if self.acls_in:
            for acl in self.acls_in:
                test_config_condition(not isinstance(acl, (int, str)),
                                      'acl names must be int or')
示例#15
0
def _config_parser_v2(config_file, logname):
    config_path = config_parser_util.dp_config_path(config_file)
    top_confs = {}
    config_hashes = {}
    dps = None
    for top_conf in V2_TOP_CONFS:
        top_confs[top_conf] = {}

    if not config_parser_util.dp_include(config_hashes, config_path, logname,
                                         top_confs):
        raise InvalidConfigError('Error found while loading config file: %s' %
                                 config_path)
    elif not top_confs['dps']:
        raise InvalidConfigError('DPs not configured in file: %s' %
                                 config_path)
    else:
        dps = _dp_parser_v2(top_confs['acls'], top_confs['dps'],
                            top_confs['meters'], top_confs['routers'],
                            top_confs['vlans'])
    return (config_hashes, dps)
示例#16
0
def match_from_dict(match_dict):
    kwargs = {}
    for of_match, field in match_dict.items():
        of_match = OLD_MATCH_FIELDS.get(of_match, of_match)
        test_config_condition(of_match not in MATCH_FIELDS, 'Unknown match field: %s' % of_match)
        try:
            encoded_field = MATCH_FIELDS[of_match](field)
        except TypeError:
            raise InvalidConfigError('%s cannot be type %s' % (of_match, type(field)))
        kwargs[of_match] = encoded_field

    return parser.OFPMatch(**kwargs)
示例#17
0
文件: acl.py 项目: tweippert/faucet
    def __init__(self, _id, dp_id, conf):
        self.rules = []
        self.exact_match = None
        self.dot1x_assigned = None
        self.meter = False
        self.matches = {}
        self.set_fields = set()
        self._ports_resolved = False

        #TODO: Would be possible to save the names instead of the DP and port objects
        # TUNNEL:
        #   src_port: PORT object / port number
        #       source port
        #   src_dp: DP object
        #       source dp
        #   dst_port: PORT object / port number
        #       final destination port
        #   dst_dp: DP object
        #       final destination dp
        #   tunnel_id: int
        #       ID to represent the tunnel
        #   tunnel_type: str ('vlan')
        #       tunnel type specification
        self.tunnel_info = {}

        for match_fields in (MATCH_FIELDS, OLD_MATCH_FIELDS):
            self.rule_types.update(
                {match: (str, int)
                 for match in match_fields})
        conf = copy.deepcopy(conf)
        if isinstance(conf, dict):
            rules = conf.get('rules', [])
        elif isinstance(conf, list):
            rules = conf
            conf = {}
        else:
            raise InvalidConfigError('ACL conf is an invalid type %s' % _id)
        conf['rules'] = []
        for rule in rules:
            normalized_rule = rule
            if isinstance(rule, dict):
                normalized_rule = rule.get('rule', rule)
                if normalized_rule is None:
                    normalized_rule = {
                        k: v
                        for k, v in rule.items() if v is not None
                    }
            test_config_condition(not isinstance(normalized_rule, dict),
                                  ('ACL rule is %s not %s (%s)' %
                                   (type(normalized_rule), dict, rules)))
            conf['rules'].append(normalized_rule)
        super(ACL, self).__init__(_id, dp_id, conf)
示例#18
0
 def _dp_add_ports(dp, dp_conf, dp_id, vlans):
     ports_conf = dp_conf.get('interfaces', {})
     port_ranges_conf = dp_conf.get('interface_ranges', {})
     # as users can config port vlan by using vlan name, we store vid in
     # Port instance instead of vlan name for data consistency
     test_config_condition(not isinstance(ports_conf, dict),
                           ('Invalid syntax in interface config'))
     test_config_condition(not isinstance(port_ranges_conf, dict),
                           ('Invalid syntax in interface ranges config'))
     port_num_to_port_conf = {}
     for port_key, port_conf in list(ports_conf.items()):
         test_config_condition(not isinstance(port_conf, dict),
                               'Invalid syntax in port config')
         if 'number' in port_conf:
             port_num = port_conf['number']
         else:
             port_num = port_key
         try:
             port_num_to_port_conf[port_num] = (port_key, port_conf)
         except TypeError:
             raise InvalidConfigError('Invalid syntax in port config')
     for port_range, port_conf in list(port_ranges_conf.items()):
         # port range format: 1-6 OR 1-6,8-9 OR 1-3,5,7-9
         test_config_condition(not isinstance(port_conf, dict),
                               'Invalid syntax in port config')
         port_nums = set()
         if 'number' in port_conf:
             del port_conf['number']
         for range_ in re.findall(r'(\d+-\d+)', str(port_range)):
             start_num, end_num = [int(num) for num in range_.split('-')]
             test_config_condition(start_num >= end_num,
                                   ('Incorrect port range (%d - %d)' %
                                    (start_num, end_num)))
             port_nums.update(list(range(start_num, end_num + 1)))
             port_range = re.sub(range_, '', port_range)
         other_nums = [int(p) for p in re.findall(r'\d+', str(port_range))]
         port_nums.update(other_nums)
         test_config_condition(not port_nums,
                               'interface-ranges contain invalid config')
         for port_num in port_nums:
             if port_num in port_num_to_port_conf:
                 # port range config has lower priority than individual port config
                 for attr, value in list(port_conf.items()):
                     port_num_to_port_conf[port_num][1].setdefault(
                         attr, value)
             else:
                 port_num_to_port_conf[port_num] = (port_num, port_conf)
     for port_num, port_conf in list(port_num_to_port_conf.values()):
         port = _dp_parse_port(dp_id, port_num, port_conf, vlans)
         dp.add_port(port)
     dp.reset_refs(vlans=vlans)
示例#19
0
def _get_vlan_by_key(dp_id, vlan_key, vlans):
    try:
        if vlan_key in vlans:
            return vlans[vlan_key]
    except TypeError as err:
        raise InvalidConfigError(err) from err
    for vlan in vlans.values():
        if vlan_key == vlan.vid:
            return vlan
    test_config_condition(not isinstance(vlan_key, int), (
        'Implicitly created VLAN %s must be an int (not %s)' % (
            vlan_key, type(vlan_key))))
    # Create VLAN with VID, if not defined.
    return vlans.setdefault(vlan_key, VLAN(vlan_key, dp_id))
示例#20
0
def _parse_dps_for_watchers(conf, logname, meta_dp_state=None):
    all_dps_list = []
    faucet_conf_hashes = {}

    if not isinstance(conf, dict):
        raise InvalidConfigError('Gauge config not valid')

    faucet_config_files = conf.get('faucet_configs', [])
    for faucet_config_file in faucet_config_files:
        conf_hashes, _, dp_list, _ = dp_parser(faucet_config_file, logname)
        if dp_list:
            faucet_conf_hashes[faucet_config_file] = conf_hashes
            all_dps_list.extend(dp_list)

    faucet_config = conf.get('faucet', None)
    if faucet_config:
        all_dps_list.extend(dp_preparsed_parser(faucet_config, meta_dp_state))

    dps = {dp.name: dp for dp in all_dps_list}
    if not dps:
        raise InvalidConfigError(
            'Gauge configured without any FAUCET configuration')
    return faucet_config_files, faucet_conf_hashes, dps
示例#21
0
 def build_acl(acl, vid=None):
     """Check that ACL can be built from config and mark mirror destinations."""
     if acl.rules:
         try:
             assert valve_acl.build_acl_ofmsgs(
                 [acl], self.wildcard_table,
                 valve_of.goto_table(self.wildcard_table),
                 2**16, self.meters, acl.exact_match,
                 vlan_vid=vid)
         except (AddrFormatError, ValueError) as err:
             raise InvalidConfigError(err)
         for port_no in acl.mirror_destinations:
             port = self.ports[port_no]
             port.mirror_destination = True
示例#22
0
def match_from_dict(match_dict):
    for old_match, new_match in list(OLD_MATCH_FIELDS.items()):
        if old_match in match_dict:
            match_dict[new_match] = match_dict[old_match]
            del match_dict[old_match]

    kwargs = {}
    for of_match, field in list(match_dict.items()):
        test_config_condition(of_match not in MATCH_FIELDS, 'Unknown match field: %s' % of_match)
        try:
            encoded_field = MATCH_FIELDS[of_match](field)
        except TypeError:
            raise InvalidConfigError('%s cannot be type %s' % (of_match, type(field)))
        kwargs[of_match] = encoded_field

    return parser.OFPMatch(**kwargs)
示例#23
0
def _dp_parser_v2(dps_conf, acls_conf, meters_conf, routers_conf, vlans_conf,
                  meta_dp_state):
    # pylint: disable=invalid-name
    dp_vlans = []
    for dp_key, dp_conf in dps_conf.items():
        try:
            dp, vlans = _parse_dp(dp_key, dp_conf, acls_conf, meters_conf,
                                  routers_conf, vlans_conf)
            dp_vlans.append((dp, vlans))
        except InvalidConfigError as err:
            raise InvalidConfigError('DP %s: %s' % (dp_key, err))

    # Some VLANs are created implicitly just by referencing them in tagged/native,
    # so we must make them available to all DPs.
    implicit_vids = set()
    for dp, vlans in dp_vlans:
        implicit_vids.update(set(vlans.keys()) - set(vlans_conf.keys()))
    dps = []
    for dp, vlans in dp_vlans:
        for vlan_key in implicit_vids:
            if vlan_key not in vlans:
                vlans[vlan_key] = VLAN(vlan_key, dp.dp_id)
        dp.reset_refs(vlans=vlans)
        dps.append(dp)

    for dp in dps:
        dp.finalize_config(dps)
    for dp in dps:
        dp.resolve_stack_topology(dps, meta_dp_state)
    for dp in dps:
        dp.finalize()

    dpid_refs = set()
    for dp in dps:
        test_config_condition(dp.dp_id in dpid_refs,
                              ('DPID %u is duplicated' % dp.dp_id))
        dpid_refs.add(dp.dp_id)

    routers_referenced = set()
    for dp in dps:
        routers_referenced.update(dp.routers.keys())
    for router in routers_conf:
        test_config_condition(
            router not in routers_referenced,
            ('router %s configured but not used by any DP' % router))

    return dps
示例#24
0
def dp_parser(config_file, logname):
    conf = config_parser_util.read_config(config_file, logname)
    config_hashes = None
    dps = None

    try:
        assert conf is not None, 'Config file is empty'
        assert isinstance(conf, dict), 'Config file does not have valid syntax'
        version = conf.pop('version', 2)
        assert version == 2, 'Only config version 2 is supported'
        config_hashes, dps = _config_parser_v2(config_file, logname)
        assert dps is not None, 'no DPs are not defined'

    except AssertionError as err:
        raise InvalidConfigError(err)

    return config_hashes, dps
示例#25
0
    def __init__(self, _id, dp_id, conf):
        self.rules = []
        self.exact_match = None
        self.dot1x_assigned = None
        self.meter = False
        self.matches = {}
        self.set_fields = set()
        self._ports_resolved = False

        # Tunnel info maintains the tunnel output information for each tunnel rule
        self.tunnel_dests = {}
        # Tunnel sources is a list of the sources in the network for this ACL
        self.tunnel_sources = {}
        # Tunnel rules is the rules for each tunnel in the ACL for each source
        self.dyn_tunnel_rules = {}
        self.dyn_reverse_tunnel_rules = {}

        for match_fields in (MATCH_FIELDS, OLD_MATCH_FIELDS):
            self.rule_types.update(
                {match: (str, int)
                 for match in match_fields})
        conf = copy.deepcopy(conf)
        if isinstance(conf, dict):
            rules = conf.get('rules', [])
        elif isinstance(conf, list):
            rules = conf
            conf = {}
        else:
            raise InvalidConfigError('ACL conf is an invalid type %s' % _id)
        conf['rules'] = []
        for rule in rules:
            normalized_rule = rule
            if isinstance(rule, dict):
                normalized_rule = rule.get('rule', rule)
                if normalized_rule is None:
                    normalized_rule = {
                        k: v
                        for k, v in rule.items() if v is not None
                    }
            test_config_condition(not isinstance(normalized_rule, dict),
                                  ('ACL rule is %s not %s (%s)' %
                                   (type(normalized_rule), dict, rules)))
            conf['rules'].append(normalized_rule)
        super().__init__(_id, dp_id, conf)
 def _validate_faucet_config(self, config_dir):
     logname = os.devnull
     try:
         root_config = os.path.join(config_dir, self.default_config)
         _, _, dps, top_confs = dp_parser(root_config, logname)
         dps_conf = None
         valve_cls = None
         acls_conf = None
         if dps is not None:
             dps_conf = {dp.name: dp for dp in dps}
             valve_cls = [valve.valve_factory(dp) for dp in dps]
             acls_conf = top_confs.get('acls', {})
         if dps_conf:
             if not valve_cls:
                 raise InvalidConfigError('no valid DPs defined')
         else:
             dps_conf = {}
         return (dps_conf, acls_conf)
     except InvalidConfigError as err:
         raise _ServerError(f'Invalid config: {err}')  # pylint: disable=raise-missing-from
示例#27
0
def _parse_dps_for_watchers(conf, logname, meta_dp_state=None):
    dps = {}
    if 'faucet_configs' in conf:
        for faucet_file in conf['faucet_configs']:
            _, dp_list, _ = dp_parser(faucet_file, logname)
            if dp_list:
                for dp in dp_list:
                    dps[dp.name] = dp

    if 'faucet' in conf:
        faucet_conf = conf['faucet']
        dps = {
            dp.name: dp
            for dp in dp_preparsed_parser(faucet_conf, meta_dp_state)
        }

    if not dps:
        raise InvalidConfigError(
            'Gauge configured without any FAUCET configuration')
    return dps
示例#28
0
def _watcher_parser_v2(conf, logname, prom_client):
    logger = config_parser_util.get_logger(logname)
    result = []

    dps = {}
    for faucet_file in conf['faucet_configs']:
        _, dp_list = dp_parser(faucet_file, logname)
        if dp_list:
            for dp in dp_list:
                dps[dp.name] = dp

    dbs = conf.pop('dbs')

    for watcher_name, watcher_conf in list(conf['watchers'].items()):
        if watcher_conf.get('all_dps', False):
            watcher_dps = list(dps.keys())
        else:
            watcher_dps = watcher_conf['dps']
        # Watcher config has a list of DPs, but actually a WatcherConf is
        # created for each DP.
        # TODO: refactor watcher_conf as a container.
        for dp_name in watcher_dps:
            if dp_name not in dps:
                logger.error('DP %s in Gauge but not configured in FAUCET', dp_name)
                continue
            dp = dps[dp_name]
            if 'dbs' in watcher_conf:
                watcher_dbs = watcher_conf['dbs']
            elif 'db' in watcher_conf:
                watcher_dbs = [watcher_conf['db']]
            else:
                raise InvalidConfigError('Watcher configured without DB')
            for db in watcher_dbs:
                watcher = WatcherConf(watcher_name, dp.dp_id, watcher_conf, prom_client)
                watcher.add_db(dbs[db])
                watcher.add_dp(dp)
                result.append(watcher)

    return result
示例#29
0
def _watcher_parser_v2(conf, logname, prom_client):
    logger = config_parser_util.get_logger(logname)

    if conf is None:
        conf = {}
    faucet_config_files, faucet_conf_hashes, dps = _parse_dps_for_watchers(
        conf, logname)
    dbs = conf.pop('dbs')

    result = []
    # pylint: disable=fixme
    for watcher_name, watcher_conf in conf['watchers'].items():
        if watcher_conf.get('all_dps', False):
            watcher_dps = dps.keys()
        else:
            watcher_dps = watcher_conf['dps']
        # Watcher config has a list of DPs, but actually a WatcherConf is
        # created for each DP.
        # TODO: refactor watcher_conf as a container.
        for dp_name in watcher_dps:
            if dp_name not in dps:
                logger.error('DP %s in Gauge but not configured in FAUCET',
                             dp_name)
                continue
            dp = dps[dp_name]
            if 'dbs' in watcher_conf:
                watcher_dbs = watcher_conf['dbs']
            elif 'db' in watcher_conf:
                watcher_dbs = [watcher_conf['db']]
            else:
                raise InvalidConfigError('Watcher configured without DB')
            for db in watcher_dbs:
                watcher = WatcherConf(watcher_name, dp.dp_id, watcher_conf,
                                      prom_client)
                watcher.add_db(dbs[db])
                watcher.add_dp(dp)
                result.append(watcher)

    return faucet_config_files, faucet_conf_hashes, result
示例#30
0
def _parse_dps_for_watchers(conf, logname):
    dps = {}
    if 'faucet_configs' in conf:
        for faucet_file in conf['faucet_configs']:
            _, dp_list = dp_parser(faucet_file, logname)
            if dp_list:
                for dp in dp_list:
                    dps[dp.name] = dp

    if 'faucet' in conf:
        faucet_conf = conf['faucet']
        acls = faucet_conf.get('acls', {})
        fct_dps = faucet_conf.get('dps', {})
        meters = faucet_conf.get('meters', {})
        routers = faucet_conf.get('routers', {})
        vlans = faucet_conf.get('vlans', {})
        for dp in _dp_parser_v2(acls, fct_dps, meters, routers, vlans):
            dps[dp.name] = dp

    if not dps:
        raise InvalidConfigError(
            'Gauge configured without any FAUCET configuration')
    return dps