def remove_interface(ctx, interface_name): """Remove interface related NAT configuration""" config_db = ConfigDBConnector() config_db.connect() if nat_interface_name_is_valid(interface_name) is False: ctx.fail( "Interface name is invalid. Please enter a valid interface name!!" ) if interface_name.startswith("Ethernet"): interface_table_type = "INTERFACE" elif interface_name.startswith("PortChannel"): interface_table_type = "PORTCHANNEL_INTERFACE" elif interface_name.startswith("Vlan"): interface_table_type = "VLAN_INTERFACE" elif interface_name.startswith("Loopback"): interface_table_type = "LOOPBACK_INTERFACE" interface_table_dict = config_db.get_table(interface_table_type) if not interface_table_dict or interface_name not in interface_table_dict: ctx.fail( "Interface table is not present. Ignoring the nat zone configuration" ) config_db.mod_entry(interface_table_type, interface_name, {"nat_zone": "0"})
def udp_timeout(ctx): """Reset NAT UDP timeout configuration to default value (300 seconds)""" config_db = ConfigDBConnector() config_db.connect() seconds = 300 config_db.mod_entry("NAT_GLOBAL", "Values", {"nat_udp_timeout": seconds})
def add_interface(ctx, interface_name, nat_zone): """Add interface related nat configuration""" config_db = ConfigDBConnector() config_db.connect() if nat_interface_name_is_valid(interface_name) is False: ctx.fail( "Interface name is invalid. Please enter a valid interface name!!" ) if interface_name.startswith("Ethernet"): interface_table_type = "INTERFACE" elif interface_name.startswith("PortChannel"): interface_table_type = "PORTCHANNEL_INTERFACE" elif interface_name.startswith("Vlan"): interface_table_type = "VLAN_INTERFACE" elif interface_name.startswith("Loopback"): interface_table_type = "LOOPBACK_INTERFACE" interface_table_dict = config_db.get_table(interface_table_type) if not interface_table_dict or interface_name not in interface_table_dict: ctx.fail( "Interface table is not present. Please configure ip-address on {} and apply the nat zone !!" .format(interface_name)) config_db.mod_entry(interface_table_type, interface_name, {"nat_zone": nat_zone})
def _change_bgp_session_status_by_addr(ipaddress, status, verbose): """Start up or shut down BGP session by IP address """ verb = 'Starting' if status == 'up' else 'Shutting' click.echo("{} {} BGP session with neighbor {}...".format(verb, status, ipaddress)) config_db = ConfigDBConnector() config_db.connect() config_db.mod_entry('bgp_neighbor', ipaddress, {'admin_status': status})
def _change_bgp_session_status_by_addr(ipaddress, status, verbose): """Start up or shut down BGP session by IP address """ verb = 'Starting' if status == 'up' else 'Shutting' click.echo("{} {} BGP session with neighbor {}...".format(verb, status, ipaddress)) config_db = ConfigDBConnector() config_db.connect() config_db.mod_entry('bgp_neighbor', ipaddress, {'admin_status': status})
def _update_kube_server(field, val): config_db = ConfigDBConnector() config_db.connect() table = "KUBERNETES_MASTER" key = "SERVER" db_data = Db().get_data(table, key) def_data = {"IP": "", "insecure": "False", "disable": "False"} for f in def_data: if db_data and f in db_data: if f == field and db_data[f] != val: config_db.mod_entry(table, key, {field: val}) log.log_info("modify kubernetes server entry {}={}".format( field, val)) else: # Missing field. Set to default or given value v = val if f == field else def_data[f] config_db.mod_entry(table, key, {f: v}) log.log_info("set kubernetes server entry {}={}".format(f, v))
def udp_timeout(ctx, seconds): """Set NAT UDP timeout configuration""" config_db = ConfigDBConnector() config_db.connect() config_db.mod_entry("NAT_GLOBAL", "Values", {"nat_udp_timeout": seconds})
def disable(ctx): """Disable the NAT feature """ config_db = ConfigDBConnector() config_db.connect() config_db.mod_entry("NAT_GLOBAL", "Values", {"admin_mode": "disabled"})
port_ds_entry = {} for key in raw_data: port_ds_entry = {} port_ds_entry["port-number"] = key.replace("PTP_PORT|GLOBAL|", "") state_data = db.get_all(db.STATE_DB, key) port_ds_entry["port-state"] = port_state_to_str(state_data["port-state"]) port_ds_list.append(port_ds_entry) port_ds_dict['port-ds-list'] = port_ds_list api_response_list.append(port_ds_dict) api_response['ietf-ptp:instance_list'] = api_response_list show_cli_output(sys.argv[3], api_response) elif sys.argv[1] == 'patch_ietf_ptp_ptp_instance_list_default_ds_domain_number': data = {} data['domain-number'] = sys.argv[3] config_db.mod_entry(PTP_CLOCK, PTP_GLOBAL, data) elif sys.argv[1] == 'patch_ietf_ptp_ptp_instance_list_default_ds_priority1': data = {} data['priority1'] = sys.argv[3] config_db.mod_entry(PTP_CLOCK, PTP_GLOBAL, data) elif sys.argv[1] == 'patch_ietf_ptp_ptp_instance_list_default_ds_priority2': data = {} data['priority2'] = sys.argv[3] config_db.mod_entry(PTP_CLOCK, PTP_GLOBAL, data) elif sys.argv[1] == 'patch_ietf_ptp_ptp_instance_list_default_ds_two_step_flag': data = {} if sys.argv[3] == "enable": data['two-step-flag'] = '1' else: data['two-step-flag'] = '0' config_db.mod_entry(PTP_CLOCK, PTP_GLOBAL, data)
def memory(kdump_memory): """Set memory allocated for kdump capture kernel""" config_db = ConfigDBConnector() if config_db is not None: config_db.connect() config_db.mod_entry("KDUMP", "config", {"memory": kdump_memory})
class AclLoader(object): ACL_TABLE = "ACL_TABLE" ACL_RULE = "ACL_RULE" ACL_TABLE_TYPE_MIRROR = "MIRROR" ACL_TABLE_TYPE_CTRLPLANE = "CTRLPLANE" MIRROR_SESSION = "MIRROR_SESSION" SESSION_PREFIX = "everflow" min_priority = 1 max_priority = 10000 ethertype_map = { "ETHERTYPE_LLDP": 0x88CC, "ETHERTYPE_VLAN": 0x8100, "ETHERTYPE_ROCE": 0x8915, "ETHERTYPE_ARP": 0x0806, "ETHERTYPE_IPV4": 0x0800, "ETHERTYPE_IPV6": 0x86DD, "ETHERTYPE_MPLS": 0x8847 } ip_protocol_map = { "IP_TCP": 6, "IP_ICMP": 1, "IP_UDP": 17, "IP_IGMP": 2, "IP_PIM": 103, "IP_RSVP": 46, "IP_GRE": 47, "IP_AUTH": 51, "IP_L2TP": 115 } def __init__(self): self.yang_acl = None self.requested_session = None self.current_table = None self.tables_db_info = {} self.rules_db_info = {} self.rules_info = {} self.sessions_db_info = {} self.configdb = ConfigDBConnector() self.configdb.connect() self.statedb = SonicV2Connector(host="127.0.0.1") self.statedb.connect(self.statedb.STATE_DB) self.read_tables_info() self.read_rules_info() self.read_sessions_info() def read_tables_info(self): """ Read ACL tables information from Config DB :return: """ self.tables_db_info = self.configdb.get_table(self.ACL_TABLE) def get_tables_db_info(self): return self.tables_db_info def read_rules_info(self): """ Read rules information from Config DB :return: """ self.rules_db_info = self.configdb.get_table(self.ACL_RULE) def get_rules_db_info(self): return self.rules_db_info def read_sessions_info(self): """ Read ACL tables information from Config DB :return: """ self.sessions_db_info = self.configdb.get_table(self.MIRROR_SESSION) for key in self.sessions_db_info.keys(): state_db_info = self.statedb.get_all( self.statedb.STATE_DB, "{}|{}".format(self.MIRROR_SESSION, key)) if state_db_info: status = state_db_info.get("status", "inactive") else: status = "error" self.sessions_db_info[key]["status"] = status def get_sessions_db_info(self): """ Read mirror session information from Config DB :return: """ return self.sessions_db_info def get_session_name(self): """ Read mirror session name from Config DB :return: Mirror session name """ if self.requested_session: return self.requested_session for key in self.get_sessions_db_info(): if key.startswith(self.SESSION_PREFIX): return key return None def set_table_name(self, table_name): """ Set table name to restrict the table to be modified :param table_name: Table name :return: """ self.current_table = table_name def set_session_name(self, session_name): """ Set session name to be used in ACL rule action :param session_name: Mirror session name :return: """ if session_name not in self.get_sessions_db_info(): raise AclLoaderException("Session %s does not exist" % session_name) self.requested_session = session_name def set_max_priority(self, priority): """ Set rules max priority :param priority: Rules max priority :return: """ self.max_priority = int(priority) def is_table_valid(self, tname): return self.tables_db_info.get(tname) def is_table_mirror(self, tname): """ Check if ACL table type is ACL_TABLE_TYPE_MIRROR :param tname: ACL table name :return: True if table type is ACL_TABLE_TYPE_MIRROR else False """ return self.tables_db_info[tname]['type'].upper( ) == self.ACL_TABLE_TYPE_MIRROR def is_table_control_plane(self, tname): """ Check if ACL table type is ACL_TABLE_TYPE_CTRLPLANE :param tname: ACL table name :return: True if table type is ACL_TABLE_TYPE_CTRLPLANE else False """ return self.tables_db_info[tname]['type'].upper( ) == self.ACL_TABLE_TYPE_CTRLPLANE @staticmethod def parse_acl_json(filename): yang_acl = pybindJSON.load(filename, openconfig_acl, "openconfig_acl") # Check pybindJSON parsing # pybindJSON.load will silently return an empty json object if input invalid with open(filename, 'r') as f: plain_json = json.load(f) if len(plain_json['acl']['acl-sets']['acl-set']) != len( yang_acl.acl.acl_sets.acl_set): raise AclLoaderException("Invalid input file %s" % filename) return yang_acl def load_rules_from_file(self, filename): """ Load file with ACL rules configuration in openconfig ACL format. Convert rules to Config DB schema. :param filename: File in openconfig ACL format :return: """ self.yang_acl = AclLoader.parse_acl_json(filename) self.convert_rules() def convert_action(self, table_name, rule_idx, rule): rule_props = {} if rule.actions.config.forwarding_action == "ACCEPT": if self.is_table_control_plane(table_name): rule_props["PACKET_ACTION"] = "ACCEPT" elif self.is_table_mirror(table_name): session_name = self.get_session_name() if not session_name: raise AclLoaderException( "Mirroring session does not exist") rule_props["MIRROR_ACTION"] = session_name else: rule_props["PACKET_ACTION"] = "FORWARD" elif rule.actions.config.forwarding_action == "DROP": rule_props["PACKET_ACTION"] = "DROP" elif rule.actions.config.forwarding_action == "REJECT": rule_props["PACKET_ACTION"] = "DROP" else: raise AclLoaderException( "Unknown rule action %s in table %s, rule %d" % (rule.actions.config.forwarding_action, table_name, rule_idx)) return rule_props def convert_l2(self, table_name, rule_idx, rule): rule_props = {} if rule.l2.config.ethertype: if rule.l2.config.ethertype in self.ethertype_map: rule_props["ETHER_TYPE"] = self.ethertype_map[ rule.l2.config.ethertype] else: try: rule_props["ETHER_TYPE"] = int(rule.l2.config.ethertype) except: raise AclLoaderException( "Failed to convert ethertype %s table %s rule %s" % (rule.l2.config.ethertype, table_name, rule_idx)) return rule_props def convert_ip(self, table_name, rule_idx, rule): rule_props = {} if rule.ip.config.protocol: if self.ip_protocol_map.has_key(rule.ip.config.protocol): rule_props["IP_PROTOCOL"] = self.ip_protocol_map[ rule.ip.config.protocol] else: try: int(rule.ip.config.protocol) except: raise AclLoaderException( "Unknown rule protocol %s in table %s, rule %d!" % (rule.ip.config.protocol, table_name, rule_idx)) rule_props["IP_PROTOCOL"] = rule.ip.config.protocol if rule.ip.config.source_ip_address: source_ip_address = rule.ip.config.source_ip_address.encode( "ascii") if ipaddr.IPNetwork(source_ip_address).version == 4: rule_props["SRC_IP"] = source_ip_address else: rule_props["SRC_IPV6"] = source_ip_address if rule.ip.config.destination_ip_address: destination_ip_address = rule.ip.config.destination_ip_address.encode( "ascii") if ipaddr.IPNetwork(destination_ip_address).version == 4: rule_props["DST_IP"] = destination_ip_address else: rule_props["DST_IPV6"] = destination_ip_address # NOTE: DSCP is available only for MIRROR table if self.is_table_mirror(table_name): if rule.ip.config.dscp: rule_props["DSCP"] = rule.ip.config.dscp return rule_props def convert_port(self, port): """ Convert port field format from openconfig ACL to Config DB schema :param port: String, ACL port number or range in openconfig format :return: Tuple, first value is converted port string, second value is boolean, True if value is a port range, False if it is a single port value """ # OpenConfig port range is of the format "####..####", whereas # Config DB format is "####-####" if ".." in port: return port.replace("..", "-"), True else: return port, False def convert_transport(self, table_name, rule_idx, rule): rule_props = {} if rule.transport.config.source_port: port, is_range = self.convert_port( str(rule.transport.config.source_port)) rule_props[ "L4_SRC_PORT_RANGE" if is_range else "L4_SRC_PORT"] = port if rule.transport.config.destination_port: port, is_range = self.convert_port( str(rule.transport.config.destination_port)) rule_props[ "L4_DST_PORT_RANGE" if is_range else "L4_DST_PORT"] = port tcp_flags = 0x00 for flag in rule.transport.config.tcp_flags: if flag == "TCP_FIN": tcp_flags |= 0x01 if flag == "TCP_SYN": tcp_flags |= 0x02 if flag == "TCP_RST": tcp_flags |= 0x04 if flag == "TCP_PSH": tcp_flags |= 0x08 if flag == "TCP_ACK": tcp_flags |= 0x10 if flag == "TCP_URG": tcp_flags |= 0x20 if flag == "TCP_ECE": tcp_flags |= 0x40 if flag == "TCP_CWR": tcp_flags |= 0x80 if tcp_flags: rule_props["TCP_FLAGS"] = '0x{:02x}/0x{:02x}'.format( tcp_flags, tcp_flags) return rule_props def convert_input_interface(self, table_name, rule_idx, rule): rule_props = {} if rule.input_interface.interface_ref.config.interface: rule_props[ "IN_PORTS"] = rule.input_interface.interface_ref.config.interface return rule_props def convert_rule_to_db_schema(self, table_name, rule): """ Convert rules format from openconfig ACL to Config DB schema :param table_name: ACL table name to which rule belong :param rule: ACL rule in openconfig format :return: dict with Config DB schema """ rule_idx = int(rule.config.sequence_id) rule_props = {} rule_data = {(table_name, "RULE_" + str(rule_idx)): rule_props} rule_props["PRIORITY"] = str(self.max_priority - rule_idx) deep_update(rule_props, self.convert_action(table_name, rule_idx, rule)) deep_update(rule_props, self.convert_l2(table_name, rule_idx, rule)) deep_update(rule_props, self.convert_ip(table_name, rule_idx, rule)) deep_update(rule_props, self.convert_transport(table_name, rule_idx, rule)) deep_update(rule_props, self.convert_input_interface(table_name, rule_idx, rule)) return rule_data def deny_rule(self, table_name): """ Create default deny rule in Config DB format :param table_name: ACL table name to which rule belong :return: dict with Config DB schema """ rule_props = {} rule_data = {(table_name, "DEFAULT_RULE"): rule_props} rule_props["PRIORITY"] = str(self.min_priority) rule_props["ETHER_TYPE"] = str(self.ethertype_map["ETHERTYPE_IPV4"]) rule_props["PACKET_ACTION"] = "DROP" return rule_data def convert_rules(self): """ Convert rules in openconfig ACL format to Config DB schema :return: """ for acl_set_name in self.yang_acl.acl.acl_sets.acl_set: table_name = acl_set_name.replace(" ", "_").replace( "-", "_").upper().encode('ascii') acl_set = self.yang_acl.acl.acl_sets.acl_set[acl_set_name] if not self.is_table_valid(table_name): warning("%s table does not exist" % (table_name)) continue if self.current_table is not None and self.current_table != table_name: continue for acl_entry_name in acl_set.acl_entries.acl_entry: acl_entry = acl_set.acl_entries.acl_entry[acl_entry_name] try: rule = self.convert_rule_to_db_schema( table_name, acl_entry) deep_update(self.rules_info, rule) except AclLoaderException as ex: error("Error processing rule %s: %s. Skipped." % (acl_entry_name, ex)) if not self.is_table_mirror(table_name): deep_update(self.rules_info, self.deny_rule(table_name)) def full_update(self): """ Perform full update of ACL rules configuration. All existing rules will be removed. New rules loaded from file will be installed. If the current_table is not empty, only rules within that table will be removed and new rules in that table will be installed. :return: """ for key in self.rules_db_info.keys(): if self.current_table is None or self.current_table == key[0]: self.configdb.mod_entry(self.ACL_RULE, key, None) self.configdb.mod_config({self.ACL_RULE: self.rules_info}) def incremental_update(self): """ Perform incremental ACL rules configuration update. Get existing rules from Config DB. Compare with rules specified in file and perform corresponding modifications. :return: """ # TODO: Until we test ASIC behavior, we cannot assume that we can insert # dataplane ACLs and shift existing ACLs. Therefore, we perform a full # update on dataplane ACLs, and only perform an incremental update on # control plane ACLs. new_rules = set(self.rules_info.iterkeys()) new_dataplane_rules = set() new_controlplane_rules = set() current_rules = set(self.rules_db_info.iterkeys()) current_dataplane_rules = set() current_controlplane_rules = set() for key in new_rules: table_name = key[0] if self.tables_db_info[table_name]['type'].upper( ) == self.ACL_TABLE_TYPE_CTRLPLANE: new_controlplane_rules.add(key) else: new_dataplane_rules.add(key) for key in current_rules: table_name = key[0] if self.tables_db_info[table_name]['type'].upper( ) == self.ACL_TABLE_TYPE_CTRLPLANE: current_controlplane_rules.add(key) else: current_dataplane_rules.add(key) # Remove all existing dataplane rules for key in current_dataplane_rules: self.configdb.mod_entry(self.ACL_RULE, key, None) # Add all new dataplane rules for key in new_dataplane_rules: self.configdb.mod_entry(self.ACL_RULE, key, self.rules_info[key]) added_controlplane_rules = new_controlplane_rules.difference( current_controlplane_rules) removed_controlplane_rules = current_controlplane_rules.difference( new_controlplane_rules) existing_controlplane_rules = new_rules.intersection( current_controlplane_rules) for key in added_controlplane_rules: self.configdb.mod_entry(self.ACL_RULE, key, self.rules_info[key]) for key in removed_controlplane_rules: self.configdb.mod_entry(self.ACL_RULE, key, None) for key in existing_controlplane_rules: if cmp(self.rules_info[key], self.rules_db_info[key]) != 0: self.configdb.set_entry(self.ACL_RULE, key, self.rules_info[key]) def delete(self, table=None, rule=None): """ :param table: :param rule: :return: """ for key in self.rules_db_info.iterkeys(): if not table or table == key[0]: if not rule or rule == key[1]: self.configdb.set_entry(self.ACL_RULE, key, None) def show_table(self, table_name): """ Show ACL table configuration. :param table_name: Optional. ACL table name. Filter tables by specified name. :return: """ header = ("Name", "Type", "Binding", "Description") data = [] for key, val in self.get_tables_db_info().iteritems(): if table_name and key != table_name: continue if val["type"] == AclLoader.ACL_TABLE_TYPE_CTRLPLANE: services = natsorted(val["services"]) data.append( [key, val["type"], services[0], val["policy_desc"]]) if len(services) > 1: for service in services[1:]: data.append(["", "", service, ""]) else: if not val["ports"]: data.append([key, val["type"], "", val["policy_desc"]]) else: ports = natsorted(val["ports"]) data.append( [key, val["type"], ports[0], val["policy_desc"]]) if len(ports) > 1: for port in ports[1:]: data.append(["", "", port, ""]) print( tabulate.tabulate(data, headers=header, tablefmt="simple", missingval="")) def show_session(self, session_name): """ Show mirror session configuration. :param session_name: Optional. Mirror session name. Filter sessions by specified name. :return: """ header = ("Name", "Status", "SRC IP", "DST IP", "GRE", "DSCP", "TTL", "Queue") data = [] for key, val in self.get_sessions_db_info().iteritems(): if session_name and key != session_name: continue data.append([ key, val["status"], val["src_ip"], val["dst_ip"], val.get("gre_type", ""), val.get("dscp", ""), val.get("ttl", ""), val.get("queue", "") ]) print( tabulate.tabulate(data, headers=header, tablefmt="simple", missingval="")) def show_rule(self, table_name, rule_id): """ Show ACL rules configuration. :param table_name: Optional. ACL table name. Filter rules by specified table name. :param rule_id: Optional. ACL rule name. Filter rule by specified rule name. :return: """ header = ("Table", "Rule", "Priority", "Action", "Match") ignore_list = ["PRIORITY", "PACKET_ACTION", "MIRROR_ACTION"] raw_data = [] for (tname, rid), val in self.get_rules_db_info().iteritems(): if table_name and table_name != tname: continue if rule_id and rule_id != rid: continue priority = val["PRIORITY"] action = "" if "PACKET_ACTION" in val: action = val["PACKET_ACTION"] elif "MIRROR_ACTION" in val: action = "MIRROR: %s" % val["MIRROR_ACTION"] else: continue matches = [ "%s: %s" % (k, v) for k, v in val.iteritems() if k not in ignore_list ] matches.sort() rule_data = [[tname, rid, priority, action, matches[0]]] if len(matches) > 1: for m in matches[1:]: rule_data.append(["", "", "", "", m]) raw_data.append([priority, rule_data]) def cmp_rules(a, b): return cmp(a[0], b[0]) raw_data.sort(cmp_rules) raw_data.reverse() data = [] for _, d in raw_data: data += d print( tabulate.tabulate(data, headers=header, tablefmt="simple", missingval=""))
class AclLoader(object): ACL_TABLE = "ACL_TABLE" ACL_RULE = "ACL_RULE" MIRROR_SESSION = "MIRROR_SESSION" SESSION_PREFIX = "everflow" min_priority = 1 max_priority = 10000 ethertype_map = { "ETHERTYPE_LLDP": 0x88CC, "ETHERTYPE_VLAN": 0x8100, "ETHERTYPE_ROCE": 0x8915, "ETHERTYPE_ARP": 0x0806, "ETHERTYPE_IPV4": 0x0800, "ETHERTYPE_IPV6": 0x86DD, "ETHERTYPE_MPLS": 0x8847 } ip_protocol_map = { "IP_TCP": 6, "IP_ICMP": 1, "IP_UDP": 17, "IP_IGMP": 2, "IP_PIM": 103, "IP_RSVP": 46, "IP_GRE": 47, "IP_AUTH": 51, "IP_L2TP": 115 } def __init__(self): self.yang_acl = None self.requested_session = None self.tables_db_info = {} self.rules_db_info = {} self.rules_info = {} self.sessions_db_info = {} self.configdb = ConfigDBConnector() self.configdb.connect() self.read_tables_info() self.read_rules_info() self.read_sessions_info() def read_tables_info(self): """ Read ACL tables information from Config DB :return: """ self.tables_db_info = self.configdb.get_table(self.ACL_TABLE) def get_tables_db_info(self): return self.tables_db_info def read_rules_info(self): """ Read rules information from Config DB :return: """ self.rules_db_info = self.configdb.get_table(self.ACL_RULE) def get_rules_db_info(self): return self.rules_db_info def read_sessions_info(self): """ Read ACL tables information from Config DB :return: """ self.sessions_db_info = self.configdb.get_table(self.MIRROR_SESSION) def get_sessions_db_info(self): """ Read mirror session information from Config DB :return: """ return self.sessions_db_info def get_session_name(self): """ Read mirror session name from Config DB :return: Mirror session name """ if self.requested_session: return self.requested_session for key in self.get_sessions_db_info(): if key.startswith(self.SESSION_PREFIX): return key return None def set_session_name(self, session_name): """ Set session name to se used in ACL rule action. :param session_name: Mirror session name """ if session_name not in self.get_sessions_db_info(): raise AclLoaderException("Session %s does not exist" % session_name) self.requested_session = session_name def set_max_priority(self, priority): """ Set rules max priority :param priority: Rules max priority :return: """ self.max_priority = int(priority) def is_table_valid(self, tname): return self.tables_db_info.get(tname) def is_table_mirror(self, tname): """ Check if ACL table type is MIRROR :param tname: ACL table name :return: True if table type is MIRROR else False """ return self.tables_db_info[tname]['type'].upper() == "MIRROR" def load_rules_from_file(self, filename): """ Load file with ACL rules configuration in openconfig ACL format. Convert rules to Config DB schema. :param filename: File in openconfig ACL format :return: """ self.yang_acl = pybindJSON.load(filename, openconfig_acl, "openconfig_acl") self.convert_rules() def convert_action(self, table_name, rule_idx, rule): rule_props = {} if rule.actions.config.forwarding_action == "ACCEPT": if self.is_table_mirror(table_name): session_name = self.get_session_name() if not session_name: raise AclLoaderException("Mirroring session does not exist") rule_props["MIRROR_ACTION"] = session_name else: rule_props["PACKET_ACTION"] = "FORWARD" elif rule.actions.config.forwarding_action == "DROP": rule_props["PACKET_ACTION"] = "DROP" elif rule.actions.config.forwarding_action == "REJECT": rule_props["PACKET_ACTION"] = "DROP" else: raise AclLoaderException("Unknown rule action %s in table %s, rule %d" % ( rule.actions.config.forwarding_action, table_name, rule_idx)) return rule_props def convert_l2(self, table_name, rule_idx, rule): rule_props = {} if rule.l2.config.ethertype: if rule.l2.config.ethertype in self.ethertype_map: rule_props["ETHER_TYPE"] = self.ethertype_map[rule.l2.config.ethertype] else: try: rule_props["ETHER_TYPE"] = int(rule.l2.config.ethertype) except: raise AclLoaderException("Failed to convert ethertype %s table %s rule %s" % ( rule.l2.config.ethertype, table_name, rule_idx)) return rule_props def convert_ipv4(self, table_name, rule_idx, rule): rule_props = {} if rule.ip.config.protocol: if self.ip_protocol_map.has_key(rule.ip.config.protocol): rule_props["IP_PROTOCOL"] = self.ip_protocol_map[rule.ip.config.protocol] else: try: int(rule.ip.config.protocol) except: raise AclLoaderException("Unknown rule protocol %s in table %s, rule %d!" % ( rule.ip.config.protocol, table_name, rule_idx)) rule_props["IP_PROTOCOL"] = rule.ip.config.protocol if rule.ip.config.source_ip_address: rule_props["SRC_IP"] = rule.ip.config.source_ip_address if rule.ip.config.destination_ip_address: rule_props["DST_IP"] = rule.ip.config.destination_ip_address # NOTE: DSCP is available only for MIRROR table if self.is_table_mirror(table_name): if rule.ip.config.dscp: rule_props["DSCP"] = rule.ip.config.dscp return rule_props def convert_port(self, port): if ".." in port: return port.replace("..", "-"), True else: return port, False def convert_transport(self, table_name, rule_idx, rule): rule_props = {} if rule.transport.config.source_port: port, is_range = self.convert_port(str(rule.transport.config.source_port)) rule_props["L4_SRC_PORT_RANGE" if is_range else "L4_SRC_PORT"] = port if rule.transport.config.destination_port: port, is_range = self.convert_port(str(rule.transport.config.destination_port)) rule_props["L4_DST_PORT_RANGE" if is_range else "L4_DST_PORT"] = port tcp_flags = 0x00 for flag in rule.transport.config.tcp_flags: if flag == "TCP_FIN": tcp_flags = tcp_flags | 0x01 if flag == "TCP_SYN": tcp_flags = tcp_flags | 0x02 if flag == "TCP_RST": tcp_flags = tcp_flags | 0x04 if flag == "TCP_PSH": tcp_flags = tcp_flags | 0x08 if flag == "TCP_ACK": tcp_flags = tcp_flags | 0x10 if flag == "TCP_URG": tcp_flags = tcp_flags | 0x20 if flag == "TCP_ECE": tcp_flags = tcp_flags | 0x40 if flag == "TCP_CWR": tcp_flags = tcp_flags | 0x80 if tcp_flags: rule_props["TCP_FLAGS"] = '0x{:02x}/0x{:02x}'.format(tcp_flags, tcp_flags) return rule_props def convert_rule_to_db_schema(self, table_name, rule): """ Convert rules format from openconfig ACL to Config DB schema :param table_name: ACL table name to which rule belong :param rule: ACL rule in openconfig format :return: dict with Config DB schema """ rule_idx = int(rule.config.sequence_id) rule_props = {} rule_data = {(table_name, "RULE_" + str(rule_idx)): rule_props} rule_props["PRIORITY"] = self.max_priority - rule_idx deep_update(rule_props, self.convert_action(table_name, rule_idx, rule)) deep_update(rule_props, self.convert_l2(table_name, rule_idx, rule)) deep_update(rule_props, self.convert_ipv4(table_name, rule_idx, rule)) deep_update(rule_props, self.convert_transport(table_name, rule_idx, rule)) return rule_data def deny_rule(self, table_name): """ Create default deny rule in Config DB format :param table_name: ACL table name to which rule belong :return: dict with Config DB schema """ rule_props = {} rule_data = {(table_name, "DEFAULT_RULE"): rule_props} rule_props["PRIORITY"] = self.min_priority rule_props["ETHER_TYPE"] = "0x0800" rule_props["PACKET_ACTION"] = "DROP" return rule_data def convert_rules(self): """ Convert rules in openconfig ACL format to Config DB schema :return: """ for acl_set_name in self.yang_acl.acl.acl_sets.acl_set: table_name = acl_set_name.replace(" ", "_").replace("-", "_").upper() acl_set = self.yang_acl.acl.acl_sets.acl_set[acl_set_name] if not self.is_table_valid(table_name): warning("%s table does not exist" % (table_name)) continue for acl_entry_name in acl_set.acl_entries.acl_entry: acl_entry = acl_set.acl_entries.acl_entry[acl_entry_name] rule = self.convert_rule_to_db_schema(table_name, acl_entry) deep_update(self.rules_info, rule) if not self.is_table_mirror(table_name): deep_update(self.rules_info, self.deny_rule(table_name)) def full_update(self): """ Perform full update of ACL rules configuration. All existing rules will be removed. New rules loaded from file will be installed. :return: """ for key in self.rules_db_info.keys(): self.configdb.mod_entry(self.ACL_RULE, key, None) self.configdb.mod_config({self.ACL_RULE: self.rules_info}) def incremental_update(self): """ Perform incremental ACL rules configuration update. Get existing rules from Config DB. Compare with rules specified in file and perform corresponding modifications. :return: """ new_rules = set(self.rules_info.iterkeys()) current_rules = set(self.rules_db_info.iterkeys()) added_rules = new_rules.difference(current_rules) removed_rules = current_rules.difference(new_rules) existing_rules = new_rules.intersection(current_rules) for key in removed_rules: self.configdb.mod_entry(self.ACL_RULE, key, None) for key in added_rules: self.configdb.mod_entry(self.ACL_RULE, key, self.rules_info[key]) for key in existing_rules: if cmp(self.rules_info[key], self.rules_db_info[key]): self.configdb.mod_entry(self.ACL_RULE, key, None) self.configdb.mod_entry(self.ACL_RULE, key, self.rules_info[key]) def show_table(self, table_name): """ Show ACL table configuration. :param table_name: Optional. ACL table name. Filter tables by specified name. :return: """ header = ("Name", "Type", "Ports", "Description") data = [] for key, val in self.get_tables_db_info().iteritems(): if table_name and key != table_name: continue if not val["ports"]: data.append([key, val["type"], "", val["policy_desc"]]) else: ports = natsorted(val["ports"]) data.append([key, val["type"], ports[0], val["policy_desc"]]) if len(ports) > 1: for port in ports[1:]: data.append(["", "", port, ""]) print(tabulate.tabulate(data, headers=header, tablefmt="simple", missingval="")) def show_session(self, session_name): """ Show mirror session configuration. :param session_name: Optional. Mirror session name. Filter sessions by specified name. :return: """ header = ("Name", "SRC IP", "DST IP", "GRE", "DSCP", "TTL", "Queue") data = [] for key, val in self.get_sessions_db_info().iteritems(): if session_name and key != session_name: continue data.append([key, val["src_ip"], val["dst_ip"], val.get("gre_type", ""), val.get("dscp", ""), val.get("ttl", ""), val.get("queue", "")]) print(tabulate.tabulate(data, headers=header, tablefmt="simple", missingval="")) def show_rule(self, table_name, rule_id): """ Show ACL rules configuration. :param table_name: Optional. ACL table name. Filter rules by specified table name. :param rule_id: Optional. ACL rule name. Filter rule by specified rule name. :return: """ header = ("Rule ID", "Table Name", "Priority", "Action", "Match") ignore_list = ["PRIORITY", "PACKET_ACTION", "MIRROR_ACTION"] raw_data = [] for (tname, rid), val in self.get_rules_db_info().iteritems(): if table_name and table_name != tname: continue if rule_id and rule_id != rid: continue priority = val["PRIORITY"] action = "" if "PACKET_ACTION" in val: action = val["PACKET_ACTION"] elif "MIRROR_ACTION" in val: action = "MIRROR: %s" % val["MIRROR_ACTION"] else: continue matches = ["%s: %s" % (k, v) for k, v in val.iteritems() if k not in ignore_list] matches.sort() rule_data = [[tname, rid, priority, action, matches[0]]] if len(matches) > 1: for m in matches[1:]: rule_data.append(["", "", "", "", m]) raw_data.append([priority, rule_data]) def cmp_rules(a, b): return cmp(a[0], b[0]) raw_data.sort(cmp_rules) raw_data.reverse() data = [] for _, d in raw_data: data += d print(tabulate.tabulate(data, headers=header, tablefmt="simple", missingval=""))
class DropMon(object): def __init__(self): # connect CONFIG DB self.config_db = ConfigDBConnector() self.config_db.connect() # connect COUNTERS_DB self.counters_db = ConfigDBConnector() self.counters_db.db_connect('COUNTERS_DB') # connect APPL DB self.app_db = ConfigDBConnector() self.app_db.db_connect('APPL_DB') def config_drop_mon(self, args): self.config_db.mod_entry( TAM_DROP_MONITOR_FLOW_TABLE, args.flowname, { 'acl-table': args.acl_table, 'acl-rule': args.acl_rule, 'collector': args.dropcollector, 'sample': args.dropsample }) return def config_drop_mon_aging(self, args): self.config_db.mod_entry(TAM_DROP_MONITOR_AGING_INTERVAL_TABLE, "aging", {'aging-interval': args.aginginterval}) return def config_drop_mon_sample(self, args): self.config_db.mod_entry(SAMPLE_RATE_TABLE, args.samplename, {'sampling-rate': args.rate}) return def clear_single_drop_mon_flow(self, key): entry = self.config_db.get_entry(TAM_DROP_MONITOR_FLOW_TABLE, key) if entry: self.config_db.set_entry(TAM_DROP_MONITOR_FLOW_TABLE, key, None) else: return False return def clear_drop_mon_flow(self, args): key = args.flowname if key == "all": # Get all the flow keys table_data = self.config_db.get_keys(TAM_DROP_MONITOR_FLOW_TABLE) if not table_data: return True # Clear each flow key for key in table_data: self.clear_single_drop_mon_flow(key) else: # Clear the specified flow entry self.clear_single_drop_mon_flow(key) return def clear_drop_mon_sample(self, args): key = args.samplename entry = self.config_db.get_entry(SAMPLE_RATE_TABLE, key) if entry: self.config_db.set_entry(SAMPLE_RATE_TABLE, key, None) else: print "Entry Not Found" return False return def clear_drop_mon_aging_int(self, args): key = "aging" entry = self.config_db.get_entry(TAM_DROP_MONITOR_AGING_INTERVAL_TABLE, key) if entry: self.config_db.set_entry(TAM_DROP_MONITOR_AGING_INTERVAL_TABLE, key, None) else: return False return def show_flow(self, args): self.get_print_all_dropmon_flows(args.flowname) return def get_dropmon_flow_stat(self, flowname): api_response_stat = {} api_response, entryfound = self.get_dropmon_flow_info(flowname) api_response_stat['flow-name'] = flowname if entryfound is not None: for k in api_response: if k == "ietf-ts:each-flow-data": acl_rule = api_response['ietf-ts:each-flow-data'][ 'acl-rule'] acl_table = api_response['ietf-ts:each-flow-data'][ 'acl-table'] api_response_stat['rule-name'] = acl_rule api_response_stat['table-name'] = acl_table acl_rule_keys = self.config_db.get_keys(ACL_RULE_TABLE_PREFIX) for acl_rule_key in acl_rule_keys: if acl_rule_key[1] == acl_rule: acl_counter_key = 'COUNTERS:' + acl_rule_key[ 0] + ':' + acl_rule_key[1] raw_dropmon_stats = self.counters_db.get_all( self.counters_db.COUNTERS_DB, acl_counter_key) api_response_stat['ietf-ts:dropmon-stats'] = raw_ifa_stats return api_response_stat, entryfound def get_print_all_dropmon_stats(self, name): stat_dict = {} stat_list = [] if name != 'all': api_response, entryfound = self.get_dropmon_flow_stat(name) if entryfound is not None: stat_list.append(api_response) else: table_data = self.config_db.get_keys(TAM_DROP_MONITOR_FLOW_TABLE) # Get data for all keys for k in table_data: api_each_stat_response, entryfound = self.get_dropmon_flow_stat( k) if entryfound is not None: stat_list.append(api_each_stat_response) stat_dict['stat-list'] = stat_list show_cli_output("show_statistics_flow.j2", stat_dict) return def show_statistics(self, args): self.get_print_all_dropmon_stats(args.flowname) return def show_aging_interval(self, args): key = "aging" entry = self.config_db.get_entry(TAM_DROP_MONITOR_AGING_INTERVAL_TABLE, key) if entry: print "Aging interval : {}".format(entry['aging-interval']) return def show_sample(self, args): self.get_print_all_sample(args.samplename) return def get_dropmon_flow_info(self, k): flow_data = {} flow_data['acl-table-name'] = '' flow_data['sampling-rate'] = '' flow_data['collector'] = '' api_response = {} key = TAM_DROP_MONITOR_FLOW_TABLE + '|' + k raw_flow_data = self.config_db.get_all(self.config_db.CONFIG_DB, key) if raw_flow_data: sample = raw_flow_data['sample'] rate = self.config_db.get_entry(SAMPLE_RATE_TABLE, sample) raw_flow_data['sample'] = rate['sampling-rate'] api_response['ietf-ts:flow-key'] = k api_response['ietf-ts:each-flow-data'] = raw_flow_data return api_response, raw_flow_data def get_print_all_dropmon_flows(self, name): flow_dict = {} flow_list = [] if name != 'all': api_response, entryfound = self.get_dropmon_flow_info(name) if entryfound is not None: flow_list.append(api_response) else: table_data = self.config_db.get_keys(TAM_DROP_MONITOR_FLOW_TABLE) # Get data for all keys for k in table_data: api_each_flow_response, entryfound = self.get_dropmon_flow_info( k) if entryfound is not None: flow_list.append(api_each_flow_response) flow_dict['flow-list'] = flow_list show_cli_output("show_drop_monitor_flow.j2", flow_dict) return def get_sample_info(self, k): sample_data = {} sample_data['sampling-rate'] = '' api_response = {} key = SAMPLE_RATE_TABLE + '|' + k raw_sample_data = self.config_db.get_all(self.config_db.CONFIG_DB, key) api_response['ietf-ts:sample-key'] = k api_response['ietf-ts:each-sample-data'] = raw_sample_data return api_response, raw_sample_data def get_print_all_sample(self, name): sample_dict = {} sample_list = [] if name != 'all': api_response, entryfound = self.get_sample_info(name) if entryfound is not None: sample_list.append(api_response) else: table_data = self.config_db.get_keys(SAMPLE_RATE_TABLE) # Get data for all keys for k in table_data: api_each_flow_response, entryfound = self.get_sample_info(k) if entryfound is not None: sample_list.append(api_each_flow_response) sample_dict['sample-list'] = sample_list show_cli_output("show_sample.j2", sample_dict) return
def add_table_kv(table, entry, key, val): config_db = ConfigDBConnector() config_db.connect() config_db.mod_entry(table, entry, {key:val})
class Ts(object): def __init__(self): # connect CONFIG DB self.config_db = ConfigDBConnector() self.config_db.connect() # connect COUNTER DB self.counters_db = ConfigDBConnector() self.counters_db.db_connect('COUNTERS_DB') # connect APPL DB self.app_db = ConfigDBConnector() self.app_db.db_connect('APPL_DB') def config_enable(self, args): """ Enable ifa """ key = 'feature' self.config_db.set_entry(TAM_INT_IFA_TS_FEATURE_TABLE_PREFIX, key, {'enable': "true"}) print "Enabled IFA" return def config_disable(self, args): """ Disable ifa """ key = 'feature' self.config_db.set_entry(TAM_INT_IFA_TS_FEATURE_TABLE_PREFIX, key, {'enable': "false"}) print "Disabled IFA" return def config_flow(self, args): key = TAM_INT_IFA_FLOW_TS_TABLE_PREFIX + '|' + args.flowname entry = self.config_db.get_all(self.config_db.CONFIG_DB, key) if entry is None: if args.acl_table_name: self.config_db.mod_entry( TAM_INT_IFA_FLOW_TS_TABLE_PREFIX, args.flowname, {'acl-table-name': args.acl_table_name}) if args.acl_rule_name: self.config_db.mod_entry(TAM_INT_IFA_FLOW_TS_TABLE_PREFIX, args.flowname, {'acl-rule-name': args.acl_rule_name}) else: print "Entry Already Exists" return False return def clear_each_flow(self, flowname): entry = self.config_db.get_entry(TAM_INT_IFA_FLOW_TS_TABLE_PREFIX, flowname) if entry: self.config_db.set_entry(TAM_INT_IFA_FLOW_TS_TABLE_PREFIX, flowname, None) else: print "Entry Not Found" return False return def clear_flow(self, args): key = args.flowname if key == "all": # Get all the flow keys table_data = self.config_db.get_keys( TAM_INT_IFA_FLOW_TS_TABLE_PREFIX) if not table_data: return True # Clear each flow key for key in table_data: self.clear_each_flow(key) else: # Clear the specified flow entry self.clear_each_flow(key) return def show_flow(self, args): self.get_print_all_ifa_flows(args.flowname) return def show_status(self): # Get data for all keys flowtable_keys = self.config_db.get_keys( TAM_INT_IFA_FLOW_TS_TABLE_PREFIX) api_response = {} key = TAM_INT_IFA_TS_FEATURE_TABLE_PREFIX + '|' + 'feature' raw_data_feature = self.config_db.get_all(self.config_db.CONFIG_DB, key) api_response['ietf-ts:feature-data'] = raw_data_feature api_inner_response = {} api_inner_response["num-of-flows"] = len(flowtable_keys) api_response['ietf-ts:num-of-flows'] = api_inner_response key = TAM_DEVICE_TABLE_PREFIX + '|' + 'device' raw_data_device = self.config_db.get_all(self.config_db.CONFIG_DB, key) api_response['ietf-ts:device-data'] = raw_data_device show_cli_output("show_status.j2", api_response) return def get_ifa_flow_stat(self, flowname): api_response_stat = {} api_response, entryfound = self.get_ifa_flow_info(flowname) api_response_stat['flow-name'] = flowname if entryfound is not None: for k in api_response: if k == "ietf-ts:each-flow-data": acl_rule_name = api_response['ietf-ts:each-flow-data'][ 'acl-rule-name'] acl_table_name = api_response['ietf-ts:each-flow-data'][ 'acl-table-name'] api_response_stat['rule-name'] = acl_rule_name api_response_stat['table-name'] = acl_table_name acl_rule_keys = self.config_db.get_keys(ACL_RULE_TABLE_PREFIX) for acl_rule_key in acl_rule_keys: if acl_rule_key[1] == acl_rule_name: acl_counter_key = 'COUNTERS:' + acl_rule_key[ 0] + ':' + acl_rule_key[1] raw_ifa_stats = self.counters_db.get_all( self.counters_db.COUNTERS_DB, acl_counter_key) api_response_stat['ietf-ts:ifa-stats'] = raw_ifa_stats return api_response_stat, entryfound def get_print_all_ifa_stats(self, name): stat_dict = {} stat_list = [] if name != 'all': api_response, entryfound = self.get_ifa_flow_stat(name) if entryfound is not None: stat_list.append(api_response) else: table_data = self.config_db.get_keys( TAM_INT_IFA_FLOW_TS_TABLE_PREFIX) # Get data for all keys for k in table_data: api_each_stat_response, entryfound = self.get_ifa_flow_stat(k) if entryfound is not None: stat_list.append(api_each_stat_response) stat_dict['stat-list'] = stat_list show_cli_output("show_statistics_flow.j2", stat_dict) return def show_statistics(self, args): self.get_print_all_ifa_stats(args.flowname) return def get_ifa_flow_info(self, k): flow_data = {} flow_data['acl-table-name'] = '' flow_data['sampling-rate'] = '' flow_data['collector'] = '' api_response = {} key = TAM_INT_IFA_FLOW_TS_TABLE_PREFIX + '|' + k raw_flow_data = self.config_db.get_all(self.config_db.CONFIG_DB, key) api_response['ietf-ts:flow-key'] = k api_response['ietf-ts:each-flow-data'] = raw_flow_data return api_response, raw_flow_data def get_print_all_ifa_flows(self, name): flow_dict = {} flow_list = [] if name != 'all': api_response, entryfound = self.get_ifa_flow_info(name) if entryfound is not None: flow_list.append(api_response) else: table_data = self.config_db.get_keys( TAM_INT_IFA_FLOW_TS_TABLE_PREFIX) # Get data for all keys for k in table_data: api_each_flow_response, entryfound = self.get_ifa_flow_info(k) if entryfound is not None: flow_list.append(api_each_flow_response) flow_dict['flow-list'] = flow_list show_cli_output("show_flow.j2", flow_dict) return def get_ifa_supported_info(self): key = 'TAM_INT_IFA_TS_FEATURE_TABLE|feature' data = self.config_db.get_all(self.config_db.CONFIG_DB, key) if data is None: return if data['enable'] == "true": print "TAM INT IFA TS Supported - True" return True elif data['enable'] == "false": print "TAM INT IFA TS Supported - False " return False return def get_ifa_enabled_info(self): print "In get_ifa_enabled_info" key = 'SWITCH_TABLE:switch' data = self.app_db.get(self.app_db.APPL_DB, key, 'ifa_enabled') if data and data == 'True': return True return True
def add_table_kv(table, entry, key, val): config_db = ConfigDBConnector() config_db.connect() config_db.mod_entry(table, entry, {key: val})
def enable(): """Enable kdump operation""" config_db = ConfigDBConnector() if config_db is not None: config_db.connect() config_db.mod_entry("KDUMP", "config", {"enabled": "true"})
class AclLoader(object): ACL_TABLE = "ACL_TABLE" ACL_RULE = "ACL_RULE" ACL_TABLE_TYPE_MIRROR = "MIRROR" ACL_TABLE_TYPE_CTRLPLANE = "CTRLPLANE" CFG_MIRROR_SESSION_TABLE = "MIRROR_SESSION" STATE_MIRROR_SESSION_TABLE = "MIRROR_SESSION_TABLE" POLICER = "POLICER" SESSION_PREFIX = "everflow" SWITCH_CAPABILITY_TABLE = "SWITCH_CAPABILITY" ACL_ACTIONS_CAPABILITY_FIELD = "ACL_ACTIONS" ACL_ACTION_CAPABILITY_FIELD = "ACL_ACTION" min_priority = 1 max_priority = 10000 ethertype_map = { "ETHERTYPE_LLDP": 0x88CC, "ETHERTYPE_VLAN": 0x8100, "ETHERTYPE_ROCE": 0x8915, "ETHERTYPE_ARP": 0x0806, "ETHERTYPE_IPV4": 0x0800, "ETHERTYPE_IPV6": 0x86DD, "ETHERTYPE_MPLS": 0x8847 } ip_protocol_map = { "IP_TCP": 6, "IP_ICMP": 1, "IP_UDP": 17, "IP_IGMP": 2, "IP_PIM": 103, "IP_RSVP": 46, "IP_GRE": 47, "IP_AUTH": 51, "IP_L2TP": 115 } def __init__(self): self.yang_acl = None self.requested_session = None self.mirror_stage = None self.current_table = None self.tables_db_info = {} self.rules_db_info = {} self.rules_info = {} # Load global db config. This call is no-op in single npu platforms SonicDBConfig.load_sonic_global_db_config() self.sessions_db_info = {} self.configdb = ConfigDBConnector() self.configdb.connect() self.statedb = SonicV2Connector(host="127.0.0.1") self.statedb.connect(self.statedb.STATE_DB) # For multi-npu architecture we will have both global and per front asic namespace. # Global namespace will be used for Control plane ACL which are via IPTables. # Per ASIC namespace will be used for Data and Everflow ACL's. # Global Configdb will have all ACL information for both Ctrl and Data/Evereflow ACL's # and will be used as souurce of truth for ACL modification to config DB which will be done to both Global DB and # front asic namespace self.per_npu_configdb = {} # State DB are used for to get mirror Session monitor port. # For multi-npu platforms each asic namespace can have different monitor port # dependinding on which route to session destination ip. So for multi-npu # platforms we get state db for all front asic namespace in addition to self.per_npu_statedb = {} # Getting all front asic namespace and correspding config and state DB connector namespaces = device_info.get_all_namespaces() for front_asic_namespaces in namespaces['front_ns']: self.per_npu_configdb[front_asic_namespaces] = ConfigDBConnector( use_unix_socket_path=True, namespace=front_asic_namespaces) self.per_npu_configdb[front_asic_namespaces].connect() self.per_npu_statedb[front_asic_namespaces] = SonicV2Connector( use_unix_socket_path=True, namespace=front_asic_namespaces) self.per_npu_statedb[front_asic_namespaces].connect( self.per_npu_statedb[front_asic_namespaces].STATE_DB) self.read_tables_info() self.read_rules_info() self.read_sessions_info() self.read_policers_info() def read_tables_info(self): """ Read ACL_TABLE table from configuration database :return: """ self.tables_db_info = self.configdb.get_table(self.ACL_TABLE) def get_tables_db_info(self): return self.tables_db_info def read_rules_info(self): """ Read ACL_RULE table from configuration database :return: """ self.rules_db_info = self.configdb.get_table(self.ACL_RULE) def get_rules_db_info(self): return self.rules_db_info def read_policers_info(self): """ Read POLICER table from configuration database :return: """ # For multi-npu platforms we will read from any one of front asic namespace # config db as the information should be same across all config db if self.per_npu_configdb: namespace_configdb = list(self.per_npu_configdb.values())[0] self.policers_db_info = namespace_configdb.get_table(self.POLICER) else: self.policers_db_info = self.configdb.get_table(self.POLICER) def get_policers_db_info(self): return self.policers_db_info def read_sessions_info(self): """ Read MIRROR_SESSION table from configuration database :return: """ # For multi-npu platforms we will read from any one of front asic namespace # config db as the information should be same across all config db if self.per_npu_configdb: namespace_configdb = list(self.per_npu_configdb.values())[0] self.sessions_db_info = namespace_configdb.get_table( self.CFG_MIRROR_SESSION_TABLE) else: self.sessions_db_info = self.configdb.get_table( self.CFG_MIRROR_SESSION_TABLE) for key in self.sessions_db_info: if self.per_npu_statedb: # For multi-npu platforms we will read from all front asic name space # statedb as the monitor port will be differnt for each asic # and it's status also might be different (ideally should not happen) # We will store them as dict of 'asic' : value self.sessions_db_info[key]["status"] = {} self.sessions_db_info[key]["monitor_port"] = {} for namespace_key, namespace_statedb in self.per_npu_statedb.items( ): state_db_info = namespace_statedb.get_all( self.statedb.STATE_DB, "{}|{}".format(self.STATE_MIRROR_SESSION_TABLE, key)) self.sessions_db_info[key]["status"][ namespace_key] = state_db_info.get( "status", "inactive") if state_db_info else "error" self.sessions_db_info[key][ "monitor_port"][namespace_key] = state_db_info.get( "monitor_port", "") if state_db_info else "" else: state_db_info = self.statedb.get_all( self.statedb.STATE_DB, "{}|{}".format(self.STATE_MIRROR_SESSION_TABLE, key)) self.sessions_db_info[key]["status"] = state_db_info.get( "status", "inactive") if state_db_info else "error" self.sessions_db_info[key]["monitor_port"] = state_db_info.get( "monitor_port", "") if state_db_info else "" def get_sessions_db_info(self): return self.sessions_db_info def get_session_name(self): """ Get requested mirror session name or default session :return: Mirror session name """ if self.requested_session: return self.requested_session for key in self.get_sessions_db_info(): if key.startswith(self.SESSION_PREFIX): return key return None def set_table_name(self, table_name): """ Set table name to restrict the table to be modified :param table_name: Table name :return: """ if not self.is_table_valid(table_name): warning("Table \"%s\" not found" % table_name) self.current_table = table_name def set_session_name(self, session_name): """ Set session name to be used in ACL rule action :param session_name: Mirror session name :return: """ if session_name not in self.get_sessions_db_info(): raise AclLoaderException("Session %s does not exist" % session_name) self.requested_session = session_name def set_mirror_stage(self, stage): """ Set mirror stage to be used in ACL mirror rule action :param session_name: stage 'ingress'/'egress' :return: """ self.mirror_stage = stage.upper() def set_max_priority(self, priority): """ Set rules max priority :param priority: Rules max priority :return: """ self.max_priority = int(priority) def is_table_valid(self, tname): return self.tables_db_info.get(tname) def is_table_mirror(self, tname): """ Check if ACL table type is ACL_TABLE_TYPE_MIRROR or ACL_TABLE_TYPE_MIRRORV6 :param tname: ACL table name :return: True if table type is MIRROR or MIRRORV6 else False """ return self.tables_db_info[tname]['type'].upper().startswith( self.ACL_TABLE_TYPE_MIRROR) def is_table_control_plane(self, tname): """ Check if ACL table type is ACL_TABLE_TYPE_CTRLPLANE :param tname: ACL table name :return: True if table type is ACL_TABLE_TYPE_CTRLPLANE else False """ return self.tables_db_info[tname]['type'].upper( ) == self.ACL_TABLE_TYPE_CTRLPLANE @staticmethod def parse_acl_json(filename): yang_acl = pybindJSON.load(filename, openconfig_acl, "openconfig_acl") # Check pybindJSON parsing # pybindJSON.load will silently return an empty json object if input invalid with open(filename, 'r') as f: plain_json = json.load(f) if len(plain_json['acl']['acl-sets']['acl-set']) != len( yang_acl.acl.acl_sets.acl_set): raise AclLoaderException("Invalid input file %s" % filename) return yang_acl def load_rules_from_file(self, filename): """ Load file with ACL rules configuration in openconfig ACL format. Convert rules to Config DB schema. :param filename: File in openconfig ACL format :return: """ self.yang_acl = AclLoader.parse_acl_json(filename) self.convert_rules() def convert_action(self, table_name, rule_idx, rule): rule_props = {} if rule.actions.config.forwarding_action == "ACCEPT": if self.is_table_control_plane(table_name): rule_props[AclAction.PACKET] = PacketAction.ACCEPT elif self.is_table_mirror(table_name): session_name = self.get_session_name() if not session_name: raise AclLoaderException( "Mirroring session does not exist") if self.mirror_stage == Stage.INGRESS: mirror_action = AclAction.MIRROR_INGRESS elif self.mirror_stage == Stage.EGRESS: mirror_action = AclAction.MIRROR_EGRESS else: raise AclLoaderException( "Invalid mirror stage passed {}".format( self.mirror_stage)) rule_props[mirror_action] = session_name else: rule_props[AclAction.PACKET] = PacketAction.FORWARD elif rule.actions.config.forwarding_action == "DROP": rule_props[AclAction.PACKET] = PacketAction.DROP elif rule.actions.config.forwarding_action == "REJECT": rule_props[AclAction.PACKET] = PacketAction.DROP else: raise AclLoaderException( "Unknown rule action {} in table {}, rule {}".format( rule.actions.config.forwarding_action, table_name, rule_idx)) if not self.validate_actions(table_name, rule_props): raise AclLoaderException( "Rule action {} is not supported in table {}, rule {}".format( rule.actions.config.forwarding_action, table_name, rule_idx)) return rule_props def validate_actions(self, table_name, action_props): if self.is_table_control_plane(table_name): return True action_count = len(action_props) if table_name not in self.tables_db_info: raise AclLoaderException( "Table {} does not exist".format(table_name)) stage = self.tables_db_info[table_name].get("stage", Stage.INGRESS) # check if per npu state db is there then read using first state db # else read from global statedb if self.per_npu_statedb: # For multi-npu we will read using anyone statedb connector for front asic namespace. # Same information should be there in all state DB's # as it is static information about switch capability namespace_statedb = list(self.per_npu_statedb.values())[0] capability = namespace_statedb.get_all( self.statedb.STATE_DB, "{}|switch".format(self.SWITCH_CAPABILITY_TABLE)) else: capability = self.statedb.get_all( self.statedb.STATE_DB, "{}|switch".format(self.SWITCH_CAPABILITY_TABLE)) for action_key in dict(action_props): key = "{}|{}".format(self.ACL_ACTIONS_CAPABILITY_FIELD, stage.upper()) if key not in capability: del action_props[action_key] continue values = capability[key].split(",") if action_key.upper() not in values: del action_props[action_key] continue if action_key == AclAction.PACKET: # Check if action_value is supported action_value = action_props[action_key] key = "{}|{}".format(self.ACL_ACTION_CAPABILITY_FIELD, action_key.upper()) if key not in capability: del action_props[action_key] continue if action_value not in capability[key]: del action_props[action_key] continue return action_count == len(action_props) def convert_l2(self, table_name, rule_idx, rule): rule_props = {} if rule.l2.config.ethertype: if rule.l2.config.ethertype in self.ethertype_map: rule_props["ETHER_TYPE"] = self.ethertype_map[ rule.l2.config.ethertype] else: try: rule_props["ETHER_TYPE"] = int(rule.l2.config.ethertype) except: raise AclLoaderException( "Failed to convert ethertype %s table %s rule %s" % (rule.l2.config.ethertype, table_name, rule_idx)) return rule_props def convert_ip(self, table_name, rule_idx, rule): rule_props = {} # FIXME: 0 is a valid protocol number, but openconfig seems to use it as a default value, # so there isn't currently a good way to check if the user defined proto=0 or not. if rule.ip.config.protocol: if rule.ip.config.protocol in self.ip_protocol_map: rule_props["IP_PROTOCOL"] = self.ip_protocol_map[ rule.ip.config.protocol] else: try: int(rule.ip.config.protocol) except: raise AclLoaderException( "Unknown rule protocol %s in table %s, rule %d!" % (rule.ip.config.protocol, table_name, rule_idx)) rule_props["IP_PROTOCOL"] = rule.ip.config.protocol if rule.ip.config.source_ip_address: source_ip_address = rule.ip.config.source_ip_address.encode( "ascii") if ipaddress.ip_network(source_ip_address).version == 4: rule_props["SRC_IP"] = source_ip_address else: rule_props["SRC_IPV6"] = source_ip_address if rule.ip.config.destination_ip_address: destination_ip_address = rule.ip.config.destination_ip_address.encode( "ascii") if ipaddress.ip_network(destination_ip_address).version == 4: rule_props["DST_IP"] = destination_ip_address else: rule_props["DST_IPV6"] = destination_ip_address # NOTE: DSCP is available only for MIRROR table if self.is_table_mirror(table_name): if rule.ip.config.dscp: rule_props["DSCP"] = rule.ip.config.dscp return rule_props def convert_port(self, port): """ Convert port field format from openconfig ACL to Config DB schema :param port: String, ACL port number or range in openconfig format :return: Tuple, first value is converted port string, second value is boolean, True if value is a port range, False if it is a single port value """ # OpenConfig port range is of the format "####..####", whereas # Config DB format is "####-####" if ".." in port: return port.replace("..", "-"), True else: return port, False def convert_transport(self, table_name, rule_idx, rule): rule_props = {} if rule.transport.config.source_port: port, is_range = self.convert_port( str(rule.transport.config.source_port)) rule_props[ "L4_SRC_PORT_RANGE" if is_range else "L4_SRC_PORT"] = port if rule.transport.config.destination_port: port, is_range = self.convert_port( str(rule.transport.config.destination_port)) rule_props[ "L4_DST_PORT_RANGE" if is_range else "L4_DST_PORT"] = port tcp_flags = 0x00 for flag in rule.transport.config.tcp_flags: if flag == "TCP_FIN": tcp_flags |= 0x01 if flag == "TCP_SYN": tcp_flags |= 0x02 if flag == "TCP_RST": tcp_flags |= 0x04 if flag == "TCP_PSH": tcp_flags |= 0x08 if flag == "TCP_ACK": tcp_flags |= 0x10 if flag == "TCP_URG": tcp_flags |= 0x20 if flag == "TCP_ECE": tcp_flags |= 0x40 if flag == "TCP_CWR": tcp_flags |= 0x80 if tcp_flags: rule_props["TCP_FLAGS"] = '0x{:02x}/0x{:02x}'.format( tcp_flags, tcp_flags) return rule_props def convert_input_interface(self, table_name, rule_idx, rule): rule_props = {} if rule.input_interface.interface_ref.config.interface: rule_props[ "IN_PORTS"] = rule.input_interface.interface_ref.config.interface return rule_props def convert_rule_to_db_schema(self, table_name, rule): """ Convert rules format from openconfig ACL to Config DB schema :param table_name: ACL table name to which rule belong :param rule: ACL rule in openconfig format :return: dict with Config DB schema """ rule_idx = int(rule.config.sequence_id) rule_props = {} rule_data = {(table_name, "RULE_" + str(rule_idx)): rule_props} rule_props["PRIORITY"] = str(self.max_priority - rule_idx) deep_update(rule_props, self.convert_action(table_name, rule_idx, rule)) deep_update(rule_props, self.convert_l2(table_name, rule_idx, rule)) deep_update(rule_props, self.convert_ip(table_name, rule_idx, rule)) deep_update(rule_props, self.convert_transport(table_name, rule_idx, rule)) deep_update(rule_props, self.convert_input_interface(table_name, rule_idx, rule)) return rule_data def deny_rule(self, table_name): """ Create default deny rule in Config DB format :param table_name: ACL table name to which rule belong :return: dict with Config DB schema """ rule_props = {} rule_data = {(table_name, "DEFAULT_RULE"): rule_props} rule_props["PRIORITY"] = str(self.min_priority) rule_props["PACKET_ACTION"] = "DROP" if 'v6' in table_name.lower(): rule_props["ETHER_TYPE"] = str( self.ethertype_map["ETHERTYPE_IPV6"]) else: rule_props["ETHER_TYPE"] = str( self.ethertype_map["ETHERTYPE_IPV4"]) return rule_data def convert_rules(self): """ Convert rules in openconfig ACL format to Config DB schema :return: """ for acl_set_name in self.yang_acl.acl.acl_sets.acl_set: table_name = acl_set_name.replace(" ", "_").replace( "-", "_").upper().encode('ascii') acl_set = self.yang_acl.acl.acl_sets.acl_set[acl_set_name] if not self.is_table_valid(table_name): warning("%s table does not exist" % (table_name)) continue if self.current_table is not None and self.current_table != table_name: continue for acl_entry_name in acl_set.acl_entries.acl_entry: acl_entry = acl_set.acl_entries.acl_entry[acl_entry_name] try: rule = self.convert_rule_to_db_schema( table_name, acl_entry) deep_update(self.rules_info, rule) except AclLoaderException as ex: error("Error processing rule %s: %s. Skipped." % (acl_entry_name, ex)) if not self.is_table_mirror(table_name): deep_update(self.rules_info, self.deny_rule(table_name)) def full_update(self): """ Perform full update of ACL rules configuration. All existing rules will be removed. New rules loaded from file will be installed. If the current_table is not empty, only rules within that table will be removed and new rules in that table will be installed. :return: """ for key in self.rules_db_info: if self.current_table is None or self.current_table == key[0]: self.configdb.mod_entry(self.ACL_RULE, key, None) # Program for per front asic namespace also if present for namespace_configdb in self.per_npu_configdb.values(): namespace_configdb.mod_entry(self.ACL_RULE, key, None) self.configdb.mod_config({self.ACL_RULE: self.rules_info}) # Program for per front asic namespace also if present for namespace_configdb in self.per_npu_configdb.values(): namespace_configdb.mod_config({self.ACL_RULE: self.rules_info}) def incremental_update(self): """ Perform incremental ACL rules configuration update. Get existing rules from Config DB. Compare with rules specified in file and perform corresponding modifications. :return: """ # TODO: Until we test ASIC behavior, we cannot assume that we can insert # dataplane ACLs and shift existing ACLs. Therefore, we perform a full # update on dataplane ACLs, and only perform an incremental update on # control plane ACLs. new_rules = set(self.rules_info.keys()) new_dataplane_rules = set() new_controlplane_rules = set() current_rules = set(self.rules_db_info.keys()) current_dataplane_rules = set() current_controlplane_rules = set() for key in new_rules: table_name = key[0] if self.tables_db_info[table_name]['type'].upper( ) == self.ACL_TABLE_TYPE_CTRLPLANE: new_controlplane_rules.add(key) else: new_dataplane_rules.add(key) for key in current_rules: table_name = key[0] if self.tables_db_info[table_name]['type'].upper( ) == self.ACL_TABLE_TYPE_CTRLPLANE: current_controlplane_rules.add(key) else: current_dataplane_rules.add(key) # Remove all existing dataplane rules for key in current_dataplane_rules: self.configdb.mod_entry(self.ACL_RULE, key, None) # Program for per-asic namespace also if present for namespace_configdb in self.per_npu_configdb.values(): namespace_configdb.mod_entry(self.ACL_RULE, key, None) # Add all new dataplane rules for key in new_dataplane_rules: self.configdb.mod_entry(self.ACL_RULE, key, self.rules_info[key]) # Program for per-asic namespace corresponding to front asic also if present. for namespace_configdb in self.per_npu_configdb.values(): namespace_configdb.mod_entry(self.ACL_RULE, key, self.rules_info[key]) added_controlplane_rules = new_controlplane_rules.difference( current_controlplane_rules) removed_controlplane_rules = current_controlplane_rules.difference( new_controlplane_rules) existing_controlplane_rules = new_rules.intersection( current_controlplane_rules) for key in added_controlplane_rules: self.configdb.mod_entry(self.ACL_RULE, key, self.rules_info[key]) # Program for per-asic namespace corresponding to front asic also if present. # For control plane ACL it's not needed but to keep all db in sync program everywhere for namespace_configdb in self.per_npu_configdb.values(): namespace_configdb.mod_entry(self.ACL_RULE, key, self.rules_info[key]) for key in removed_controlplane_rules: self.configdb.mod_entry(self.ACL_RULE, key, None) # Program for per-asic namespace corresponding to front asic also if present. # For control plane ACL it's not needed but to keep all db in sync program everywhere for namespace_configdb in self.per_npu_configdb.values(): namespace_configdb.mod_entry(self.ACL_RULE, key, None) for key in existing_controlplane_rules: if cmp(self.rules_info[key], self.rules_db_info[key]) != 0: self.configdb.set_entry(self.ACL_RULE, key, self.rules_info[key]) # Program for per-asic namespace corresponding to front asic also if present. # For control plane ACL it's not needed but to keep all db in sync program everywhere for namespace_configdb in self.per_npu_configdb.values(): namespace_configdb.set_entry(self.ACL_RULE, key, self.rules_info[key]) def delete(self, table=None, rule=None): """ :param table: :param rule: :return: """ for key in self.rules_db_info: if not table or table == key[0]: if not rule or rule == key[1]: self.configdb.set_entry(self.ACL_RULE, key, None) # Program for per-asic namespace corresponding to front asic also if present. for namespace_configdb in self.per_npu_configdb.values(): namespace_configdb.set_entry(self.ACL_RULE, key, None) def show_table(self, table_name): """ Show ACL table configuration. :param table_name: Optional. ACL table name. Filter tables by specified name. :return: """ header = ("Name", "Type", "Binding", "Description", "Stage") data = [] for key, val in self.get_tables_db_info().items(): if table_name and key != table_name: continue stage = val.get("stage", Stage.INGRESS).lower() if val["type"] == AclLoader.ACL_TABLE_TYPE_CTRLPLANE: services = natsorted(val["services"]) data.append( [key, val["type"], services[0], val["policy_desc"], stage]) if len(services) > 1: for service in services[1:]: data.append(["", "", service, "", ""]) else: if not val["ports"]: data.append( [key, val["type"], "", val["policy_desc"], stage]) else: ports = natsorted(val["ports"]) data.append([ key, val["type"], ports[0], val["policy_desc"], stage ]) if len(ports) > 1: for port in ports[1:]: data.append(["", "", port, "", ""]) print( tabulate.tabulate(data, headers=header, tablefmt="simple", missingval="")) def show_session(self, session_name): """ Show mirror session configuration. :param session_name: Optional. Mirror session name. Filter sessions by specified name. :return: """ erspan_header = ("Name", "Status", "SRC IP", "DST IP", "GRE", "DSCP", "TTL", "Queue", "Policer", "Monitor Port", "SRC Port", "Direction") span_header = ("Name", "Status", "DST Port", "SRC Port", "Direction", "Queue", "Policer") erspan_data = [] span_data = [] for key, val in self.get_sessions_db_info().items(): if session_name and key != session_name: continue if val.get("type") == "SPAN": span_data.append([ key, val.get("status", ""), val.get("dst_port", ""), val.get("src_port", ""), val.get("direction", "").lower(), val.get("queue", ""), val.get("policer", "") ]) else: erspan_data.append([ key, val.get("status", ""), val.get("src_ip", ""), val.get("dst_ip", ""), val.get("gre_type", ""), val.get("dscp", ""), val.get("ttl", ""), val.get("queue", ""), val.get("policer", ""), val.get("monitor_port", ""), val.get("src_port", ""), val.get("direction", "").lower() ]) print("ERSPAN Sessions") print( tabulate.tabulate(erspan_data, headers=erspan_header, tablefmt="simple", missingval="")) print("\nSPAN Sessions") print( tabulate.tabulate(span_data, headers=span_header, tablefmt="simple", missingval="")) def show_policer(self, policer_name): """ Show policer configuration. :param policer_name: Optional. Policer name. Filter policers by specified name. :return: """ header = ("Name", "Type", "Mode", "CIR", "CBS") data = [] for key, val in self.get_policers_db_info().items(): if policer_name and key != policer_name: continue data.append([ key, val["meter_type"], val["mode"], val.get("cir", ""), val.get("cbs", "") ]) print( tabulate.tabulate(data, headers=header, tablefmt="simple", missingval="")) def show_rule(self, table_name, rule_id): """ Show ACL rules configuration. :param table_name: Optional. ACL table name. Filter rules by specified table name. :param rule_id: Optional. ACL rule name. Filter rule by specified rule name. :return: """ header = ("Table", "Rule", "Priority", "Action", "Match") def pop_priority(val): priority = "N/A" for key in dict(val): if (key.upper() == "PRIORITY"): priority = val.pop(key) return priority return priority def pop_action(val): action = "" for key in dict(val): key = key.upper() if key == AclAction.PACKET: action = val.pop(key) elif key == AclAction.REDIRECT: action = "REDIRECT: {}".format(val.pop(key)) elif key in (AclAction.MIRROR, AclAction.MIRROR_INGRESS): action = "MIRROR INGRESS: {}".format(val.pop(key)) elif key == AclAction.MIRROR_EGRESS: action = "MIRROR EGRESS: {}".format(val.pop(key)) else: continue return action def pop_matches(val): matches = list(sorted(["%s: %s" % (k, val[k]) for k in val])) if len(matches) == 0: matches.append("N/A") return matches raw_data = [] for (tname, rid), val in self.get_rules_db_info().items(): if table_name and table_name != tname: continue if rule_id and rule_id != rid: continue priority = pop_priority(val) action = pop_action(val) matches = pop_matches(val) rule_data = [[tname, rid, priority, action, matches[0]]] if len(matches) > 1: for m in matches[1:]: rule_data.append(["", "", "", "", m]) raw_data.append([priority, rule_data]) def cmp_rules(a, b): return cmp(a[0], b[0]) raw_data.sort(cmp_rules) raw_data.reverse() data = [] for _, d in raw_data: data += d print( tabulate.tabulate(data, headers=header, tablefmt="simple", missingval=""))
def num_dumps(kdump_num_dumps): """Set max number of dump files for kdump""" config_db = ConfigDBConnector() if config_db is not None: config_db.connect() config_db.mod_entry("KDUMP", "config", {"num_dumps": kdump_num_dumps})
class Tam(object): def __init__(self): # connect CONFIG DB self.config_db = ConfigDBConnector() self.config_db.connect() # connect APPL DB self.app_db = ConfigDBConnector() self.app_db.db_connect('APPL_DB') def get_tam_collector_info(self, k): api_response = {} key = TAM_COLLECTOR_TABLE_PREFIX + '|' + k raw_coll_data = self.config_db.get_all(self.config_db.CONFIG_DB, key) api_response['coll-key'] = k api_response['each-coll-data'] = raw_coll_data return api_response, raw_coll_data def get_print_all_tam_collectors(self, name): coll_dict = {} coll_list = [] if name != 'all': api_response, entryfound = self.get_tam_collector_info(name) if entryfound is not None: coll_list.append(api_response) else: table_data = self.config_db.get_keys(TAM_COLLECTOR_TABLE_PREFIX) # Get data for all keys for k in table_data: api_each_flow_response, entryfound = self.get_tam_collector_info( k) if entryfound is not None: coll_list.append(api_each_flow_response) coll_dict['flow-list'] = coll_list show_cli_output("show_collector.j2", coll_dict) return def config_device_id(self, args): key = 'device' entry = self.config_db.get_entry(TAM_DEVICE_TABLE_PREFIX, key) if entry is None: if args.deviceid: self.config_db.set_entry(TAM_DEVICE_TABLE_PREFIX, key, {'deviceid': args.deviceid}) else: if args.deviceid: entry_value = entry.get('deviceid', []) if entry_value != args.deviceid: self.config_db.mod_entry(TAM_DEVICE_TABLE_PREFIX, key, {'deviceid': args.deviceid}) return def config_collector(self, args): if args.iptype == 'ipv4': if args.ipaddr == "0.0.0.0": print "Collector IP should be non-zero ip address" return False if args.iptype == 'ipv6': print "IPv6 Collector type not supported" return False self.config_db.mod_entry( TAM_COLLECTOR_TABLE_PREFIX, args.collectorname, { 'ipaddress-type': args.iptype, 'ipaddress': args.ipaddr, 'port': args.port }) return def clear_device_id(self): key = 'device' entry = self.config_db.get_entry(TAM_DEVICE_TABLE_PREFIX, key) if entry: self.config_db.set_entry(TAM_DEVICE_TABLE_PREFIX, key, None) return def clear_collector(self, args): key = args.collectorname entry = self.config_db.get_entry(TAM_COLLECTOR_TABLE_PREFIX, key) if entry: self.config_db.set_entry(TAM_COLLECTOR_TABLE_PREFIX, key, None) else: print "Entry Not Found" return False return def show_device_id(self): key = TAM_DEVICE_TABLE_PREFIX + '|' + 'device' data = self.config_db.get_all(self.config_db.CONFIG_DB, key) print "TAM Device identifier" print "-------------------------------" if data: if 'deviceid' in data: print "Device Identifier - ", data['deviceid'] return def show_collector(self, args): self.get_print_all_tam_collectors(args.collectorname) return