Loading src/service/service/service_handlers/p4_fabric_tna_acl/p4_fabric_tna_acl_config.py +0 −4 Viewed Changes for src/service/service/service_handlers/p4_fabric_tna_acl/p4_fabric_tna_acl_config.py: 0 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -22,12 +22,8 @@ SD-Fabric repo: https://github.com/stratum/fabric-tna SD-Fabric docs: https://docs.sd-fabric.org/master/index.html """ import logging from service.service.service_handlers.p4_fabric_tna_commons.p4_fabric_tna_commons import * LOGGER = logging.getLogger(__name__) # ACL service handler settings ACL = "acl" ACTION = "action" Loading src/service/service/service_handlers/p4_fabric_tna_acl/p4_fabric_tna_acl_service_handler.py +36 −41 Viewed Changes for src/service/service/service_handlers/p4_fabric_tna_acl/p4_fabric_tna_acl_service_handler.py: 36 added lines, 41 removed lines. Original line number Diff line number Diff line Loading @@ -84,8 +84,7 @@ class P4FabricACLServiceHandler(_ServiceHandler): chk_type('endpoints', endpoints, list) if len(endpoints) == 0: return [] LOGGER.info("{} - Provision service configuration".format( self.__service_label)) LOGGER.info(f"{self.__service_label} - Provision service configuration") visited = set() results = [] Loading @@ -94,17 +93,17 @@ class P4FabricACLServiceHandler(_ServiceHandler): device = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) device_name = device.name LOGGER.info("Device {}".format(device_name)) LOGGER.info("\t | Service endpoint UUID: {}".format(endpoint_uuid)) LOGGER.info(f"Device {device_name}") LOGGER.info(f"\t | Service endpoint UUID: {endpoint_uuid}") port_id = find_port_id_in_endpoint_list(device.device_endpoints, endpoint_uuid) LOGGER.info("\t | Service port ID: {}".format(port_id)) LOGGER.info(f"\t | Service port ID: {port_id}") try: # Check if this port is part of the ACL configuration _ = self._get_switch_port_in_port_map(device_name, port_id) except Exception: LOGGER.warning("Switch {} endpoint {} is not part of the ACL configuration".format(device_name, port_id)) LOGGER.warning(f"Switch {device_name} endpoint {port_id} is not part of the ACL configuration") results.append(False) continue Loading @@ -129,15 +128,14 @@ class P4FabricACLServiceHandler(_ServiceHandler): json_config_rules=rules ) except Exception as ex: LOGGER.error("Failed to insert ACL rules on device {} due to {}".format(device.name, ex)) LOGGER.error(f"Failed to insert ACL rules on device {device.name} due to {ex}") results.append(ex) finally: rules.clear() # Ensure correct status if (failed_rules == 0) and (applied_rules == actual_rules): LOGGER.info("Installed {}/{} ACL rules on device {} and port {}".format( applied_rules, actual_rules, device_name, port_id)) LOGGER.info(f"Installed {applied_rules}/{actual_rules} ACL rules on device {device_name} and port {port_id}") results.append(True) # You should no longer visit this device port again Loading Loading @@ -169,8 +167,7 @@ class P4FabricACLServiceHandler(_ServiceHandler): chk_type('endpoints', endpoints, list) if len(endpoints) == 0: return [] LOGGER.info("{} - Deprovision service configuration".format( self.__service_label)) LOGGER.info(f"{self.__service_label} - Deprovision service configuration") visited = set() results = [] Loading @@ -179,17 +176,17 @@ class P4FabricACLServiceHandler(_ServiceHandler): device = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) device_name = device.name LOGGER.info("Device {}".format(device_name)) LOGGER.info("\t | Service endpoint UUID: {}".format(endpoint_uuid)) LOGGER.info(f"Device {device_name}") LOGGER.info(f"\t | Service endpoint UUID: {endpoint_uuid}") port_id = find_port_id_in_endpoint_list(device.device_endpoints, endpoint_uuid) LOGGER.info("\t | Service port ID: {}".format(port_id)) LOGGER.info(f"\t | Service port ID: {port_id}") try: # Check if this port is part of the ACL configuration _ = self._get_switch_port_in_port_map(device_name, port_id) except Exception as ex: LOGGER.warning("Switch {} endpoint {} is not part of the ACL configuration".format(device_name, port_id)) LOGGER.warning(f"Switch {device_name} endpoint {port_id} is not part of the ACL configuration") results.append(False) continue Loading @@ -214,15 +211,14 @@ class P4FabricACLServiceHandler(_ServiceHandler): json_config_rules=rules ) except Exception as ex: LOGGER.error("Failed to delete ACL rules from device {} due to {}".format(device.name, ex)) LOGGER.error(f"Failed to delete ACL rules from device {device.name} due to {ex}") results.append(ex) finally: rules.clear() # Ensure correct status if (failed_rules == 0) and (applied_rules == actual_rules): LOGGER.info("Deleted {}/{} ACL rules from device {} and port {}".format( applied_rules, actual_rules, device_name, port_id)) LOGGER.info(f"Deleted {applied_rules}/{actual_rules} ACL rules from device {device_name} and port {port_id}") results.append(True) # You should no longer visit this device port again Loading Loading @@ -333,37 +329,36 @@ class P4FabricACLServiceHandler(_ServiceHandler): try: self.__settings = self.__settings_handler.get('/settings') LOGGER.info("{} with settings: {}".format(self.__service_label, self.__settings)) LOGGER.info(f"{self.__service_label} with settings: {self.__settings}") except Exception as ex: LOGGER.error("Failed to retrieve service settings: {}".format(ex)) LOGGER.error(f"Failed to retrieve service settings: {ex}") raise Exception(ex) def _parse_settings(self): try: switch_info = self.__settings.value[SWITCH_INFO] except Exception as ex: LOGGER.error("Failed to parse service settings: {}".format(ex)) LOGGER.error(f"Failed to parse service settings: {ex}") raise Exception(ex) assert isinstance(switch_info, list), "Switch info object must be a list" for switch in switch_info: for switch_name, sw_info in switch.items(): assert switch_name, "Invalid P4 switch name" assert isinstance(sw_info, dict), "Switch {} info must be a map with arch, dpid, and fwd_list items)" assert isinstance(sw_info, dict), f"Switch {switch_name} info must be a map with arch, dpid, and fwd_list items)" assert sw_info[ARCH] in SUPPORTED_TARGET_ARCH_LIST, \ "Switch {} - Supported P4 architectures are: {}".format(switch_name, ','.join(SUPPORTED_TARGET_ARCH_LIST)) f"Switch {switch_name} - Supported P4 architectures are: {','.join(SUPPORTED_TARGET_ARCH_LIST)}" switch_dpid = sw_info[DPID] assert switch_dpid > 0, "Switch {} - P4 switch dataplane ID must be a positive integer".format(switch_name, sw_info[DPID]) assert switch_dpid > 0, f"Switch {switch_name} - P4 switch dataplane ID {sw_info[DPID]} must be a positive integer" # Access Control list acl = sw_info[ACL] assert isinstance(acl, list),\ "Switch {} access control list must be a list with port_id, [ipv4_dst/src, trn_post_dst/src], and action items)".\ format(switch_name) f"Switch {switch_name} access control list must be a list with port_id, [ipv4_dst/src, trn_post_dst/src], and action items)" for acl_entry in acl: LOGGER.info("ACL entry: {}".format(acl_entry)) LOGGER.info(f"ACL entry: {acl_entry}") port_id = acl_entry[PORT_ID] assert port_id >= 0, "Switch {} - Invalid P4 switch port ID".format(switch_name) assert port_id >= 0, f"Switch {switch_name} - Invalid P4 switch port ID" # Prepare the port map if switch_name not in self.__port_map: Loading @@ -380,35 +375,35 @@ class P4FabricACLServiceHandler(_ServiceHandler): ipv4_src = "" if IPV4_SRC in acl_entry: ipv4_src = acl_entry[IPV4_SRC] assert chk_address_ipv4(ipv4_src), "Invalid source IPv4 address {}".format(ipv4_dst) assert chk_address_ipv4(ipv4_src), f"Invalid source IPv4 address {ipv4_src}" map_entry[IPV4_SRC] = ipv4_src ipv4_dst = "" if IPV4_DST in acl_entry: ipv4_dst = acl_entry[IPV4_DST] assert chk_address_ipv4(ipv4_dst), "Invalid destination IPv4 address {}".format(ipv4_dst) assert chk_address_ipv4(ipv4_dst), f"Invalid destination IPv4 address {ipv4_dst}" map_entry[IPV4_DST] = ipv4_dst ipv4_prefix_len = -1 if ipv4_src or ipv4_dst: ipv4_prefix_len = acl_entry[IPV4_PREFIX_LEN] assert chk_prefix_len_ipv4(ipv4_prefix_len), "Invalid IPv4 address prefix length {}".format(ipv4_prefix_len) assert chk_prefix_len_ipv4(ipv4_prefix_len), f"Invalid IPv4 address prefix length {ipv4_prefix_len}" map_entry[IPV4_PREFIX_LEN] = ipv4_prefix_len trn_port_src = -1 if TRN_PORT_SRC in acl_entry: trn_port_src = acl_entry[TRN_PORT_SRC] assert chk_transport_port(trn_port_src), "Invalid source transport port {}".format(trn_port_src) assert chk_transport_port(trn_port_src), f"Invalid source transport port {trn_port_src}" map_entry[TRN_PORT_SRC] = trn_port_src trn_port_dst = -1 if TRN_PORT_DST in acl_entry: trn_port_dst = acl_entry[TRN_PORT_DST] assert chk_transport_port(trn_port_dst), "Invalid destination transport port {}".format(trn_port_dst) assert chk_transport_port(trn_port_dst), f"Invalid destination transport port {trn_port_dst}" map_entry[TRN_PORT_DST] = trn_port_dst action = acl_entry[ACTION] assert is_valid_acl_action(action), "Valid actions are: {}".format(','.join(ACTION_LIST)) assert is_valid_acl_action(action), f"Valid actions are: {','.join(ACTION_LIST)}" # Retrieve entry from the port map switch_port_entry = self._get_switch_port_in_port_map(switch_name, port_id) Loading @@ -419,22 +414,22 @@ class P4FabricACLServiceHandler(_ServiceHandler): self.__switch_info[switch_name] = sw_info def _print_settings(self): LOGGER.info("--------------- {} settings ---------------".format(self.__service.name)) LOGGER.info(f"--------------- {self.__service.name} settings ---------------") LOGGER.info("--- Topology info") for switch_name, switch_info in self.__switch_info.items(): LOGGER.info("\t Device {}".format(switch_name)) LOGGER.info("\t\t| Target P4 architecture: {}".format(switch_info[ARCH])) LOGGER.info("\t\t| Data plane ID: {}".format(switch_info[DPID])) LOGGER.info("\t\t| Port map: {}".format(self.__port_map[switch_name])) LOGGER.info(f"\t Device {switch_name}") LOGGER.info(f"\t\t| Target P4 architecture: {switch_info[ARCH]}") LOGGER.info(f"\t\t| Data plane ID: {switch_info[DPID]}") LOGGER.info(f"\t\t| Port map: {self.__port_map[switch_name]}") LOGGER.info("-------------------------------------------------------") def _get_switch_port_in_port_map(self, switch_name : str, port_id : int) -> Dict: assert switch_name, "A valid switch name must be used as a key to the port map" assert port_id > 0, "A valid switch port ID must be used as a key to a switch's port map" switch_entry = self.__port_map[switch_name] assert switch_entry, "Switch {} does not exist in the port map".format(switch_name) assert switch_entry, f"Switch {switch_name} does not exist in the port map" port_key = PORT_PREFIX + str(port_id) assert switch_entry[port_key], "Port with ID {} does not exist in the switch map".format(port_id) assert switch_entry[port_key], f"Port with ID {port_id} does not exist in the switch map" return switch_entry[port_key] Loading src/service/service/service_handlers/p4_fabric_tna_commons/p4_fabric_tna_commons.py +10 −11 Viewed Changes for src/service/service/service_handlers/p4_fabric_tna_commons/p4_fabric_tna_commons.py: 10 added lines, 11 removed lines. Original line number Diff line number Diff line Loading @@ -366,7 +366,7 @@ def rules_set_up_port( action=action ) ) LOGGER.debug("Port configured:{}".format(port)) LOGGER.debug(f"Port configured:{port}") return rules_list Loading Loading @@ -678,8 +678,7 @@ def rules_set_up_report_mirror_flow( rules_list = [] for i, mirror_id in enumerate(report_mirror_id_list): LOGGER.debug("Mirror ID:{} - Recirculation port: {}".format( mirror_id, recirculation_port_list[i])) LOGGER.debug(f"Mirror ID:{mirror_id} - Recirculation port: {recirculation_port_list[i]}") rules_list.extend( rules_set_up_clone_session( session_id=mirror_id, Loading Loading @@ -836,7 +835,7 @@ def apply_rules( # Provision rules one-by-one for i, json_config_rule in enumerate(json_config_rules): LOGGER.debug("Applying rule #{}: {}".format(i, json_config_rule)) LOGGER.debug(f"Applying rule #{i}: {json_config_rule}") try: # Cleanup the rules of this particular object del device_obj.device_config.config_rules[:] Loading @@ -853,11 +852,11 @@ def apply_rules( applied_rules += 1 except Exception as ex: LOGGER.error("Error while applying rule #{}: {}".format(i, ex)) LOGGER.error(f"Error while applying rule #{i}: {ex}") failed_rules += 1 raise Exception(ex) LOGGER.debug("Batch rules: {}/{} applied".format(applied_rules, total_rules)) LOGGER.debug(f"Batch rules: {applied_rules}/{total_rules} applied") return applied_rules, failed_rules Loading @@ -876,7 +875,7 @@ def cache_rule( else: assert True, "Invalid rule configuration action" assert rule_no > 0, "Invalid rule identifier to configure table {}".format(table_name) assert rule_no > 0, f"Invalid rule identifier to configure table {table_name}" return rule_no Loading @@ -889,8 +888,8 @@ def add_rule_to_map(table_name : str) -> int: # Get a new valid rule index new_index = find_minimum_available_rule_index(RULE_ENTRY_MAP[table_name]) LOGGER.debug("Minimum available rule index for table {} is: {}".format(table_name, new_index)) assert new_index > 0, "Invalid rule index for table {}".format(table_name) LOGGER.debug(f"Minimum available rule index for table {table_name} is: {new_index}") assert new_index > 0, f"Invalid rule index for table {table_name}" # New entry new_rule_entry = table_name+"["+str(new_index)+"]" Loading @@ -903,7 +902,7 @@ def add_rule_to_map(table_name : str) -> int: def delete_rule_from_map(table_name : str) -> int: if table_name not in RULE_ENTRY_MAP: LOGGER.error("Table {} has no entries".format(table_name)) LOGGER.error(f"Table {table_name} has no entries") return -1 # Current number of rules Loading Loading @@ -958,4 +957,4 @@ def find_minimum_available_rule_index(rule_entry_list : List) -> int: def print_rule_map() -> None: for k in RULE_ENTRY_MAP.keys(): LOGGER.info("Table {} entries: {}".format(k, RULE_ENTRY_MAP[k])) LOGGER.info(f"Table {k} entries: {RULE_ENTRY_MAP[k]}") src/service/service/service_handlers/p4_fabric_tna_int/p4_fabric_tna_int_config.py +0 −5 Viewed Changes for src/service/service/service_handlers/p4_fabric_tna_int/p4_fabric_tna_int_config.py: 0 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ SD-Fabric repo: https://github.com/stratum/fabric-tna SD-Fabric docs: https://docs.sd-fabric.org/master/index.html """ import logging from typing import List, Tuple from common.proto.context_pb2 import ConfigActionEnum from common.tools.object_factory.ConfigRule import json_config_rule Loading @@ -30,8 +29,6 @@ from common.type_checkers.Checkers import chk_address_ipv4, chk_transport_port from service.service.service_handlers.p4_fabric_tna_commons.p4_fabric_tna_commons import * LOGGER = logging.getLogger(__name__) # INT service handler settings INT_COLLECTOR_INFO = "int_collector_info" INT_REPORT_MIRROR_ID_LIST = "int_report_mirror_id_list" Loading Loading @@ -135,8 +132,6 @@ def rules_set_up_int_recirculation_ports( ) ) LOGGER.debug("INT recirculation ports configured:{}".format(recirculation_port_list)) return rules_list def rules_set_up_int_report_flow( Loading src/service/service/service_handlers/p4_fabric_tna_int/p4_fabric_tna_int_service_handler.py +62 −66 Viewed Changes for src/service/service/service_handlers/p4_fabric_tna_int/p4_fabric_tna_int_service_handler.py: 62 added lines, 66 removed lines. Original line number Diff line number Diff line Loading @@ -97,8 +97,7 @@ class P4FabricINTServiceHandler(_ServiceHandler): chk_type('endpoints', endpoints, list) if len(endpoints) == 0: return [] LOGGER.info("{} - Provision service configuration".format( self.__service_label)) LOGGER.info(f"{self.__service_label} - Provision service configuration") visited = set() results = [] Loading @@ -109,8 +108,7 @@ class P4FabricINTServiceHandler(_ServiceHandler): # Skip already visited devices if device.name in visited: continue LOGGER.info("Device {} - Setting up In-band Network Telemetry (INT) configuration".format( device.name)) LOGGER.info(f"Device {device.name} - Setting up In-band Network Telemetry (INT) configuration") rules = [] actual_rules = -1 Loading @@ -126,15 +124,14 @@ class P4FabricINTServiceHandler(_ServiceHandler): json_config_rules=rules ) except Exception as ex: LOGGER.error("Failed to insert INT rules on device {} due to {}".format(device.name, ex)) LOGGER.error(f"Failed to insert INT rules on device {device.name} due to {ex}") results.append(ex) finally: rules.clear() # Ensure correct status if (failed_rules == 0) and (applied_rules == actual_rules): LOGGER.info("Installed {}/{} INT rules on device {}".format( applied_rules, actual_rules, device.name)) LOGGER.info(f"Installed {applied_rules}/{actual_rules} INT rules on device {device.name}") results.append(True) # You should no longer visit this device again Loading Loading @@ -165,8 +162,7 @@ class P4FabricINTServiceHandler(_ServiceHandler): chk_type('endpoints', endpoints, list) if len(endpoints) == 0: return [] LOGGER.info("{} - Deprovision service configuration".format( self.__service_label)) LOGGER.info(f"{self.__service_label} - Deprovision service configuration") visited = set() results = [] Loading @@ -177,8 +173,7 @@ class P4FabricINTServiceHandler(_ServiceHandler): # Skip already visited devices if device.name in visited: continue LOGGER.info("Device {} - Removing In-band Network Telemetry (INT) configuration".format( device.name)) LOGGER.info(f"Device {device.name} - Removing In-band Network Telemetry (INT) configuration") rules = [] actual_rules = -1 Loading @@ -191,15 +186,14 @@ class P4FabricINTServiceHandler(_ServiceHandler): applied_rules, failed_rules = apply_rules( task_executor=self.__task_executor, device_obj=device, json_config_rules=rules) except Exception as ex: LOGGER.error("Failed to delete INT rules from device {} due to {}".format(device.name, ex)) LOGGER.error(f"Failed to delete INT rules from device {device.name} due to {ex}") results.append(ex) finally: rules.clear() # Ensure correct status if (failed_rules == 0) and (applied_rules == actual_rules): LOGGER.info("Deleted {}/{} INT rules from device {}".format( applied_rules, actual_rules, device.name)) LOGGER.info(f"Deleted {applied_rules}/{actual_rules} INT rules from device {device.name}") results.append(True) # You should no longer visit this device again Loading Loading @@ -317,9 +311,9 @@ class P4FabricINTServiceHandler(_ServiceHandler): try: self.__settings = self.__settings_handler.get('/settings') LOGGER.info("{} with settings: {}".format(self.__service_label, self.__settings)) LOGGER.info(f"{self.__service_label} with settings: {self.__settings}") except Exception as ex: LOGGER.error("Failed to retrieve service settings: {}".format(ex)) LOGGER.error(f"Failed to retrieve service settings: {ex}") raise Exception(ex) def _parse_settings(self): Loading @@ -327,32 +321,31 @@ class P4FabricINTServiceHandler(_ServiceHandler): switch_info = self.__settings.value[SWITCH_INFO] assert isinstance(switch_info, list), "Switch info object must be a list" except Exception as ex: LOGGER.error("Failed to parse service settings: {}".format(ex)) LOGGER.error(f"Failed to parse service settings: {ex}") raise Exception(ex) for switch in switch_info: for switch_name, sw_info in switch.items(): try: assert switch_name, "Invalid P4 switch name" assert isinstance(sw_info, dict), "Switch {} info must be a map with arch, dpid, mac, ip, and int_port items)" assert isinstance(sw_info, dict), f"Switch {switch_name} info must be a map with arch, dpid, mac, ip, and int_port items)" assert sw_info[ARCH] in SUPPORTED_TARGET_ARCH_LIST, \ "Switch {} - Supported P4 architectures are: {}".format(switch_name, ','.join(SUPPORTED_TARGET_ARCH_LIST)) assert sw_info[DPID] > 0, "Switch {} - P4 switch dataplane ID must be a positive integer".format(switch_name, sw_info[DPID]) assert chk_address_mac(sw_info[MAC]), "Switch {} - Invalid source Ethernet address".format(switch_name) assert chk_address_ipv4(sw_info[IP]), "Switch {} - Invalid source IP address".format(switch_name) assert isinstance(sw_info[PORT_INT], dict), "Switch {} - INT port object must be a map with port_id and port_type items".format(switch_name) assert sw_info[PORT_INT][PORT_ID] >= 0, "Switch {} - Invalid P4 switch port ID".format(switch_name) assert sw_info[PORT_INT][PORT_TYPE] in PORT_TYPES_STR_VALID, "Switch {} - Valid P4 switch port types are: {}".format( switch_name, ','.join(PORT_TYPES_STR_VALID)) f"Switch {switch_name} - Supported P4 architectures are: {','.join(SUPPORTED_TARGET_ARCH_LIST)}" assert sw_info[DPID] > 0, f"Switch {switch_name} - P4 switch dataplane ID {sw_info[DPID]} must be a positive integer" assert chk_address_mac(sw_info[MAC]), f"Switch {switch_name} - Invalid source Ethernet address" assert chk_address_ipv4(sw_info[IP]), f"Switch {switch_name} - Invalid source IP address" assert isinstance(sw_info[PORT_INT], dict), f"Switch {switch_name} - INT port object must be a map with port_id and port_type items" assert sw_info[PORT_INT][PORT_ID] >= 0, f"Switch {switch_name} - Invalid P4 switch port ID" assert sw_info[PORT_INT][PORT_TYPE] in PORT_TYPES_STR_VALID, f"Switch {switch_name} - Valid P4 switch port types are: {','.join(PORT_TYPES_STR_VALID)}" if arch_tna(sw_info[ARCH]): sw_info[RECIRCULATION_PORT_LIST] = RECIRCULATION_PORTS_TNA sw_info[INT_REPORT_MIRROR_ID_LIST] = INT_REPORT_MIRROR_ID_LIST_TNA else: sw_info[RECIRCULATION_PORT_LIST] = RECIRCULATION_PORTS_V1MODEL sw_info[INT_REPORT_MIRROR_ID_LIST] = INT_REPORT_MIRROR_ID_LIST_V1MODEL assert isinstance(sw_info[RECIRCULATION_PORT_LIST], list), "Switch {} - Recirculation ports must be described as a list".format(switch_name) assert isinstance(sw_info[RECIRCULATION_PORT_LIST], list), f"Switch {switch_name} - Recirculation ports must be described as a list" except Exception as ex: LOGGER.error("Failed to parse switch {} information".format(switch_name)) LOGGER.error(f"Failed to parse switch {switch_name} information") return self.__switch_info[switch_name] = sw_info Loading @@ -376,44 +369,41 @@ class P4FabricINTServiceHandler(_ServiceHandler): self.__int_vlan_id = self.__int_collector_info[VLAN_ID] assert chk_vlan_id(self.__int_vlan_id), "Invalid VLAN ID for INT" else: LOGGER.warning("No or invalid INT VLAN ID is provided. Default VLAN ID is set to {} (No VLAN)".\ format(self.__int_vlan_id)) LOGGER.warning(f"No or invalid INT VLAN ID is provided. Default VLAN ID is set to {self.__int_vlan_id} (No VLAN)") if self.__int_collector_info[DURATION_SEC] > 0: self.__int_collector_duration_s = self.__int_collector_info[DURATION_SEC] else: LOGGER.warning("No or invalid INT collection duration is provided. Default duration is set to {} seconds".\ format(self.__int_collector_duration_s)) LOGGER.warning(f"No or invalid INT collection duration is provided. Default duration is set to {self.__int_collector_duration_s} seconds") if self.__int_collector_info[INTERVAL_SEC] > 0: self.__int_collector_interval_s = self.__int_collector_info[INTERVAL_SEC] else: LOGGER.warning("No or invalid INT collection interval is provided. Default interval is set to {} seconds".\ format(self.__int_collector_interval_s)) LOGGER.warning(f"No or invalid INT collection interval is provided. Default interval is set to {self.__int_collector_interval_s} seconds") except Exception as ex: LOGGER.error("Failed to parse INT collector information") return def _print_settings(self): LOGGER.info("-------------------- {} settings --------------------".format(self.__service.name)) LOGGER.info(f"-------------------- {self.__service.name} settings --------------------") LOGGER.info("--- Topology info") for switch_name, switch_info in self.__switch_info.items(): LOGGER.info("\t Device {}".format(switch_name)) LOGGER.info("\t\t| Target P4 architecture: {}".format(switch_info[ARCH])) LOGGER.info("\t\t| Data plane ID: {}".format(switch_info[DPID])) LOGGER.info("\t\t| Source MAC address: {}".format(switch_info[MAC])) LOGGER.info("\t\t| Source IP address: {}".format(switch_info[IP])) LOGGER.info("\t\t| INT port ID: {}".format(switch_info[PORT_INT][PORT_ID])) LOGGER.info("\t\t| INT port type: {}".format(switch_info[PORT_INT][PORT_TYPE])) LOGGER.info("\t\t| Recirculation port list: {}".format(switch_info[RECIRCULATION_PORT_LIST])) LOGGER.info("\t\t| Report mirror ID list: {}".format(switch_info[INT_REPORT_MIRROR_ID_LIST])) LOGGER.info("--- INT collector interface: {}".format(self.__int_collector_iface)) LOGGER.info("--- INT collector MAC: {}".format(self.__int_collector_mac)) LOGGER.info("--- INT collector IP: {}".format(self.__int_collector_ip)) LOGGER.info("--- INT collector port: {}".format(self.__int_collector_port)) LOGGER.info("--- INT VLAN ID: {}".format(self.__int_vlan_id)) LOGGER.info("--- INT collector duration: {} sec".format(self.__int_collector_duration_s)) LOGGER.info("--- INT collector interval: {} sec".format(self.__int_collector_interval_s)) LOGGER.info(f"\t Device {switch_name}") LOGGER.info(f"\t\t| Target P4 architecture: {switch_info[ARCH]}") LOGGER.info(f"\t\t| Data plane ID: {switch_info[DPID]}") LOGGER.info(f"\t\t| Source MAC address: {switch_info[MAC]}") LOGGER.info(f"\t\t| Source IP address: {switch_info[IP]}") LOGGER.info(f"\t\t| INT port ID: {switch_info[PORT_INT][PORT_ID]}") LOGGER.info(f"\t\t| INT port type: {switch_info[PORT_INT][PORT_TYPE]}") LOGGER.info(f"\t\t| Recirculation port list: {switch_info[RECIRCULATION_PORT_LIST]}") LOGGER.info(f"\t\t| Report mirror ID list: {switch_info[INT_REPORT_MIRROR_ID_LIST]}") LOGGER.info(f"--- INT collector interface: {self.__int_collector_iface}") LOGGER.info(f"--- INT collector MAC: {self.__int_collector_mac}") LOGGER.info(f"--- INT collector IP: {self.__int_collector_ip}") LOGGER.info(f"--- INT collector port: {self.__int_collector_port}") LOGGER.info(f"--- INT VLAN ID: {self.__int_vlan_id}") LOGGER.info(f"--- INT collector duration: {self.__int_collector_duration_s} sec") LOGGER.info(f"--- INT collector interval: {self.__int_collector_interval_s} sec") LOGGER.info("-----------------------------------------------------------------") def _create_rules(self, device_obj : Device, action : ConfigActionEnum): # type: ignore Loading Loading @@ -529,11 +519,11 @@ class P4FabricINTServiceHandler(_ServiceHandler): # Get the context ctx_id = response.context_ids[0].context_uuid.uuid assert ctx_id, "Cannot create INT collector with invalid context ID" LOGGER.debug("Context ID: {}".format(ctx_id)) LOGGER.debug(f"Context ID: {ctx_id}") service_id = self.__service.service_id.service_uuid.uuid assert service_id, "Cannot create INT collector with invalid service ID" LOGGER.debug("Service ID: {}".format(service_id)) LOGGER.debug(f"Service ID: {service_id}") # Get a service endpoint svc_endpoints = self.__service.service_endpoint_ids[0] Loading @@ -542,14 +532,14 @@ class P4FabricINTServiceHandler(_ServiceHandler): # Get a P4 device associated with this endpoint dev_id = svc_endpoints.device_id.device_uuid.uuid assert dev_id, "Cannot create INT collector with invalid device ID" LOGGER.debug("Device ID: {}".format(dev_id)) LOGGER.debug(f"Device ID: {dev_id}") # Get the endpoint ID ep_id = svc_endpoints.endpoint_uuid.uuid assert ep_id, "Cannot create INT collector with invalid endpoint ID" LOGGER.debug("Endpoint ID: {}".format(ep_id)) LOGGER.debug(f"Endpoint ID: {ep_id}") except Exception as ex: LOGGER.error("Failed to retrieve context for starting the INT collector: {}".format(ex)) LOGGER.error(f"Failed to retrieve context for starting the INT collector: {ex}") raise ex return ctx_id, service_id, dev_id, ep_id Loading @@ -558,8 +548,8 @@ class P4FabricINTServiceHandler(_ServiceHandler): ctx_id = service_id = dev_id = ep_id = None try: ctx_id, service_id, dev_id, ep_id = self._retrieve_context_for_int_collector() except Exception: LOGGER.error("INT collector cannot be initialized due to missing information") except Exception as ex: LOGGER.error(f"INT collector cannot be initialized: Failed to retrieve context {ex}") return # Create a "virtual" INT KPI associated with this context and P4 dataplane Loading @@ -575,9 +565,9 @@ class P4FabricINTServiceHandler(_ServiceHandler): # Set this new KPI kpi_manager_client = KpiManagerClient() kpi_id_int: KpiId = kpi_manager_client.SetKpiDescriptor(kpi_descriptor_int) # type: ignore LOGGER.debug("INT KPI ID: {}".format(kpi_id_int)) LOGGER.debug(f"INT KPI ID: {kpi_id_int}") except Exception: LOGGER.error("INT collector cannot be initialized due to failed KPI initialization") LOGGER.error(f"INT collector cannot be initialized: Failed to initialize KPI {ex}") return # Initialize an INT collector object Loading @@ -591,13 +581,19 @@ class P4FabricINTServiceHandler(_ServiceHandler): collect_int.int_collector.transport_port = self.__int_collector_port collect_int.int_collector.service_id = service_id collect_int.int_collector.context_id = ctx_id LOGGER.info("INT Collector: {}".format(str(collect_int))) LOGGER.info(f"INT Collector: {str(collect_int)}") except Exception as ex: LOGGER.error(f"INT collector cannot be initialized: Failed to create collector object {ex}") return # Start the INT collector c_id = None try: telemetry_frontend_client = TelemetryFrontendClient() collect_id: CollectorId = telemetry_frontend_client.StartCollector(collect_int) # type: ignore assert collect_id.uuid, "INT collector failed to start" except Exception: LOGGER.error("INT collector cannot be initialized") c_id: CollectorId = telemetry_frontend_client.StartCollector(collect_int) # type: ignore assert c_id.collector_id.uuid, "INT collector failed to start" except Exception as ex: LOGGER.error(f"INT collector cannot be initialized: Failed to start the collector {ex}") return LOGGER.info("INT collector with ID {} is successfully invoked".format(collect_id)) LOGGER.info(f"INT collector with ID {c_id.collector_id.uuid} is successfully invoked") Loading
src/service/service/service_handlers/p4_fabric_tna_acl/p4_fabric_tna_acl_config.py +0 −4 Viewed Changes for src/service/service/service_handlers/p4_fabric_tna_acl/p4_fabric_tna_acl_config.py: 0 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -22,12 +22,8 @@ SD-Fabric repo: https://github.com/stratum/fabric-tna SD-Fabric docs: https://docs.sd-fabric.org/master/index.html """ import logging from service.service.service_handlers.p4_fabric_tna_commons.p4_fabric_tna_commons import * LOGGER = logging.getLogger(__name__) # ACL service handler settings ACL = "acl" ACTION = "action" Loading
src/service/service/service_handlers/p4_fabric_tna_acl/p4_fabric_tna_acl_service_handler.py +36 −41 Viewed Changes for src/service/service/service_handlers/p4_fabric_tna_acl/p4_fabric_tna_acl_service_handler.py: 36 added lines, 41 removed lines. Original line number Diff line number Diff line Loading @@ -84,8 +84,7 @@ class P4FabricACLServiceHandler(_ServiceHandler): chk_type('endpoints', endpoints, list) if len(endpoints) == 0: return [] LOGGER.info("{} - Provision service configuration".format( self.__service_label)) LOGGER.info(f"{self.__service_label} - Provision service configuration") visited = set() results = [] Loading @@ -94,17 +93,17 @@ class P4FabricACLServiceHandler(_ServiceHandler): device = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) device_name = device.name LOGGER.info("Device {}".format(device_name)) LOGGER.info("\t | Service endpoint UUID: {}".format(endpoint_uuid)) LOGGER.info(f"Device {device_name}") LOGGER.info(f"\t | Service endpoint UUID: {endpoint_uuid}") port_id = find_port_id_in_endpoint_list(device.device_endpoints, endpoint_uuid) LOGGER.info("\t | Service port ID: {}".format(port_id)) LOGGER.info(f"\t | Service port ID: {port_id}") try: # Check if this port is part of the ACL configuration _ = self._get_switch_port_in_port_map(device_name, port_id) except Exception: LOGGER.warning("Switch {} endpoint {} is not part of the ACL configuration".format(device_name, port_id)) LOGGER.warning(f"Switch {device_name} endpoint {port_id} is not part of the ACL configuration") results.append(False) continue Loading @@ -129,15 +128,14 @@ class P4FabricACLServiceHandler(_ServiceHandler): json_config_rules=rules ) except Exception as ex: LOGGER.error("Failed to insert ACL rules on device {} due to {}".format(device.name, ex)) LOGGER.error(f"Failed to insert ACL rules on device {device.name} due to {ex}") results.append(ex) finally: rules.clear() # Ensure correct status if (failed_rules == 0) and (applied_rules == actual_rules): LOGGER.info("Installed {}/{} ACL rules on device {} and port {}".format( applied_rules, actual_rules, device_name, port_id)) LOGGER.info(f"Installed {applied_rules}/{actual_rules} ACL rules on device {device_name} and port {port_id}") results.append(True) # You should no longer visit this device port again Loading Loading @@ -169,8 +167,7 @@ class P4FabricACLServiceHandler(_ServiceHandler): chk_type('endpoints', endpoints, list) if len(endpoints) == 0: return [] LOGGER.info("{} - Deprovision service configuration".format( self.__service_label)) LOGGER.info(f"{self.__service_label} - Deprovision service configuration") visited = set() results = [] Loading @@ -179,17 +176,17 @@ class P4FabricACLServiceHandler(_ServiceHandler): device = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) device_name = device.name LOGGER.info("Device {}".format(device_name)) LOGGER.info("\t | Service endpoint UUID: {}".format(endpoint_uuid)) LOGGER.info(f"Device {device_name}") LOGGER.info(f"\t | Service endpoint UUID: {endpoint_uuid}") port_id = find_port_id_in_endpoint_list(device.device_endpoints, endpoint_uuid) LOGGER.info("\t | Service port ID: {}".format(port_id)) LOGGER.info(f"\t | Service port ID: {port_id}") try: # Check if this port is part of the ACL configuration _ = self._get_switch_port_in_port_map(device_name, port_id) except Exception as ex: LOGGER.warning("Switch {} endpoint {} is not part of the ACL configuration".format(device_name, port_id)) LOGGER.warning(f"Switch {device_name} endpoint {port_id} is not part of the ACL configuration") results.append(False) continue Loading @@ -214,15 +211,14 @@ class P4FabricACLServiceHandler(_ServiceHandler): json_config_rules=rules ) except Exception as ex: LOGGER.error("Failed to delete ACL rules from device {} due to {}".format(device.name, ex)) LOGGER.error(f"Failed to delete ACL rules from device {device.name} due to {ex}") results.append(ex) finally: rules.clear() # Ensure correct status if (failed_rules == 0) and (applied_rules == actual_rules): LOGGER.info("Deleted {}/{} ACL rules from device {} and port {}".format( applied_rules, actual_rules, device_name, port_id)) LOGGER.info(f"Deleted {applied_rules}/{actual_rules} ACL rules from device {device_name} and port {port_id}") results.append(True) # You should no longer visit this device port again Loading Loading @@ -333,37 +329,36 @@ class P4FabricACLServiceHandler(_ServiceHandler): try: self.__settings = self.__settings_handler.get('/settings') LOGGER.info("{} with settings: {}".format(self.__service_label, self.__settings)) LOGGER.info(f"{self.__service_label} with settings: {self.__settings}") except Exception as ex: LOGGER.error("Failed to retrieve service settings: {}".format(ex)) LOGGER.error(f"Failed to retrieve service settings: {ex}") raise Exception(ex) def _parse_settings(self): try: switch_info = self.__settings.value[SWITCH_INFO] except Exception as ex: LOGGER.error("Failed to parse service settings: {}".format(ex)) LOGGER.error(f"Failed to parse service settings: {ex}") raise Exception(ex) assert isinstance(switch_info, list), "Switch info object must be a list" for switch in switch_info: for switch_name, sw_info in switch.items(): assert switch_name, "Invalid P4 switch name" assert isinstance(sw_info, dict), "Switch {} info must be a map with arch, dpid, and fwd_list items)" assert isinstance(sw_info, dict), f"Switch {switch_name} info must be a map with arch, dpid, and fwd_list items)" assert sw_info[ARCH] in SUPPORTED_TARGET_ARCH_LIST, \ "Switch {} - Supported P4 architectures are: {}".format(switch_name, ','.join(SUPPORTED_TARGET_ARCH_LIST)) f"Switch {switch_name} - Supported P4 architectures are: {','.join(SUPPORTED_TARGET_ARCH_LIST)}" switch_dpid = sw_info[DPID] assert switch_dpid > 0, "Switch {} - P4 switch dataplane ID must be a positive integer".format(switch_name, sw_info[DPID]) assert switch_dpid > 0, f"Switch {switch_name} - P4 switch dataplane ID {sw_info[DPID]} must be a positive integer" # Access Control list acl = sw_info[ACL] assert isinstance(acl, list),\ "Switch {} access control list must be a list with port_id, [ipv4_dst/src, trn_post_dst/src], and action items)".\ format(switch_name) f"Switch {switch_name} access control list must be a list with port_id, [ipv4_dst/src, trn_post_dst/src], and action items)" for acl_entry in acl: LOGGER.info("ACL entry: {}".format(acl_entry)) LOGGER.info(f"ACL entry: {acl_entry}") port_id = acl_entry[PORT_ID] assert port_id >= 0, "Switch {} - Invalid P4 switch port ID".format(switch_name) assert port_id >= 0, f"Switch {switch_name} - Invalid P4 switch port ID" # Prepare the port map if switch_name not in self.__port_map: Loading @@ -380,35 +375,35 @@ class P4FabricACLServiceHandler(_ServiceHandler): ipv4_src = "" if IPV4_SRC in acl_entry: ipv4_src = acl_entry[IPV4_SRC] assert chk_address_ipv4(ipv4_src), "Invalid source IPv4 address {}".format(ipv4_dst) assert chk_address_ipv4(ipv4_src), f"Invalid source IPv4 address {ipv4_src}" map_entry[IPV4_SRC] = ipv4_src ipv4_dst = "" if IPV4_DST in acl_entry: ipv4_dst = acl_entry[IPV4_DST] assert chk_address_ipv4(ipv4_dst), "Invalid destination IPv4 address {}".format(ipv4_dst) assert chk_address_ipv4(ipv4_dst), f"Invalid destination IPv4 address {ipv4_dst}" map_entry[IPV4_DST] = ipv4_dst ipv4_prefix_len = -1 if ipv4_src or ipv4_dst: ipv4_prefix_len = acl_entry[IPV4_PREFIX_LEN] assert chk_prefix_len_ipv4(ipv4_prefix_len), "Invalid IPv4 address prefix length {}".format(ipv4_prefix_len) assert chk_prefix_len_ipv4(ipv4_prefix_len), f"Invalid IPv4 address prefix length {ipv4_prefix_len}" map_entry[IPV4_PREFIX_LEN] = ipv4_prefix_len trn_port_src = -1 if TRN_PORT_SRC in acl_entry: trn_port_src = acl_entry[TRN_PORT_SRC] assert chk_transport_port(trn_port_src), "Invalid source transport port {}".format(trn_port_src) assert chk_transport_port(trn_port_src), f"Invalid source transport port {trn_port_src}" map_entry[TRN_PORT_SRC] = trn_port_src trn_port_dst = -1 if TRN_PORT_DST in acl_entry: trn_port_dst = acl_entry[TRN_PORT_DST] assert chk_transport_port(trn_port_dst), "Invalid destination transport port {}".format(trn_port_dst) assert chk_transport_port(trn_port_dst), f"Invalid destination transport port {trn_port_dst}" map_entry[TRN_PORT_DST] = trn_port_dst action = acl_entry[ACTION] assert is_valid_acl_action(action), "Valid actions are: {}".format(','.join(ACTION_LIST)) assert is_valid_acl_action(action), f"Valid actions are: {','.join(ACTION_LIST)}" # Retrieve entry from the port map switch_port_entry = self._get_switch_port_in_port_map(switch_name, port_id) Loading @@ -419,22 +414,22 @@ class P4FabricACLServiceHandler(_ServiceHandler): self.__switch_info[switch_name] = sw_info def _print_settings(self): LOGGER.info("--------------- {} settings ---------------".format(self.__service.name)) LOGGER.info(f"--------------- {self.__service.name} settings ---------------") LOGGER.info("--- Topology info") for switch_name, switch_info in self.__switch_info.items(): LOGGER.info("\t Device {}".format(switch_name)) LOGGER.info("\t\t| Target P4 architecture: {}".format(switch_info[ARCH])) LOGGER.info("\t\t| Data plane ID: {}".format(switch_info[DPID])) LOGGER.info("\t\t| Port map: {}".format(self.__port_map[switch_name])) LOGGER.info(f"\t Device {switch_name}") LOGGER.info(f"\t\t| Target P4 architecture: {switch_info[ARCH]}") LOGGER.info(f"\t\t| Data plane ID: {switch_info[DPID]}") LOGGER.info(f"\t\t| Port map: {self.__port_map[switch_name]}") LOGGER.info("-------------------------------------------------------") def _get_switch_port_in_port_map(self, switch_name : str, port_id : int) -> Dict: assert switch_name, "A valid switch name must be used as a key to the port map" assert port_id > 0, "A valid switch port ID must be used as a key to a switch's port map" switch_entry = self.__port_map[switch_name] assert switch_entry, "Switch {} does not exist in the port map".format(switch_name) assert switch_entry, f"Switch {switch_name} does not exist in the port map" port_key = PORT_PREFIX + str(port_id) assert switch_entry[port_key], "Port with ID {} does not exist in the switch map".format(port_id) assert switch_entry[port_key], f"Port with ID {port_id} does not exist in the switch map" return switch_entry[port_key] Loading
src/service/service/service_handlers/p4_fabric_tna_commons/p4_fabric_tna_commons.py +10 −11 Viewed Changes for src/service/service/service_handlers/p4_fabric_tna_commons/p4_fabric_tna_commons.py: 10 added lines, 11 removed lines. Original line number Diff line number Diff line Loading @@ -366,7 +366,7 @@ def rules_set_up_port( action=action ) ) LOGGER.debug("Port configured:{}".format(port)) LOGGER.debug(f"Port configured:{port}") return rules_list Loading Loading @@ -678,8 +678,7 @@ def rules_set_up_report_mirror_flow( rules_list = [] for i, mirror_id in enumerate(report_mirror_id_list): LOGGER.debug("Mirror ID:{} - Recirculation port: {}".format( mirror_id, recirculation_port_list[i])) LOGGER.debug(f"Mirror ID:{mirror_id} - Recirculation port: {recirculation_port_list[i]}") rules_list.extend( rules_set_up_clone_session( session_id=mirror_id, Loading Loading @@ -836,7 +835,7 @@ def apply_rules( # Provision rules one-by-one for i, json_config_rule in enumerate(json_config_rules): LOGGER.debug("Applying rule #{}: {}".format(i, json_config_rule)) LOGGER.debug(f"Applying rule #{i}: {json_config_rule}") try: # Cleanup the rules of this particular object del device_obj.device_config.config_rules[:] Loading @@ -853,11 +852,11 @@ def apply_rules( applied_rules += 1 except Exception as ex: LOGGER.error("Error while applying rule #{}: {}".format(i, ex)) LOGGER.error(f"Error while applying rule #{i}: {ex}") failed_rules += 1 raise Exception(ex) LOGGER.debug("Batch rules: {}/{} applied".format(applied_rules, total_rules)) LOGGER.debug(f"Batch rules: {applied_rules}/{total_rules} applied") return applied_rules, failed_rules Loading @@ -876,7 +875,7 @@ def cache_rule( else: assert True, "Invalid rule configuration action" assert rule_no > 0, "Invalid rule identifier to configure table {}".format(table_name) assert rule_no > 0, f"Invalid rule identifier to configure table {table_name}" return rule_no Loading @@ -889,8 +888,8 @@ def add_rule_to_map(table_name : str) -> int: # Get a new valid rule index new_index = find_minimum_available_rule_index(RULE_ENTRY_MAP[table_name]) LOGGER.debug("Minimum available rule index for table {} is: {}".format(table_name, new_index)) assert new_index > 0, "Invalid rule index for table {}".format(table_name) LOGGER.debug(f"Minimum available rule index for table {table_name} is: {new_index}") assert new_index > 0, f"Invalid rule index for table {table_name}" # New entry new_rule_entry = table_name+"["+str(new_index)+"]" Loading @@ -903,7 +902,7 @@ def add_rule_to_map(table_name : str) -> int: def delete_rule_from_map(table_name : str) -> int: if table_name not in RULE_ENTRY_MAP: LOGGER.error("Table {} has no entries".format(table_name)) LOGGER.error(f"Table {table_name} has no entries") return -1 # Current number of rules Loading Loading @@ -958,4 +957,4 @@ def find_minimum_available_rule_index(rule_entry_list : List) -> int: def print_rule_map() -> None: for k in RULE_ENTRY_MAP.keys(): LOGGER.info("Table {} entries: {}".format(k, RULE_ENTRY_MAP[k])) LOGGER.info(f"Table {k} entries: {RULE_ENTRY_MAP[k]}")
src/service/service/service_handlers/p4_fabric_tna_int/p4_fabric_tna_int_config.py +0 −5 Viewed Changes for src/service/service/service_handlers/p4_fabric_tna_int/p4_fabric_tna_int_config.py: 0 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ SD-Fabric repo: https://github.com/stratum/fabric-tna SD-Fabric docs: https://docs.sd-fabric.org/master/index.html """ import logging from typing import List, Tuple from common.proto.context_pb2 import ConfigActionEnum from common.tools.object_factory.ConfigRule import json_config_rule Loading @@ -30,8 +29,6 @@ from common.type_checkers.Checkers import chk_address_ipv4, chk_transport_port from service.service.service_handlers.p4_fabric_tna_commons.p4_fabric_tna_commons import * LOGGER = logging.getLogger(__name__) # INT service handler settings INT_COLLECTOR_INFO = "int_collector_info" INT_REPORT_MIRROR_ID_LIST = "int_report_mirror_id_list" Loading Loading @@ -135,8 +132,6 @@ def rules_set_up_int_recirculation_ports( ) ) LOGGER.debug("INT recirculation ports configured:{}".format(recirculation_port_list)) return rules_list def rules_set_up_int_report_flow( Loading
src/service/service/service_handlers/p4_fabric_tna_int/p4_fabric_tna_int_service_handler.py +62 −66 Viewed Changes for src/service/service/service_handlers/p4_fabric_tna_int/p4_fabric_tna_int_service_handler.py: 62 added lines, 66 removed lines. Original line number Diff line number Diff line Loading @@ -97,8 +97,7 @@ class P4FabricINTServiceHandler(_ServiceHandler): chk_type('endpoints', endpoints, list) if len(endpoints) == 0: return [] LOGGER.info("{} - Provision service configuration".format( self.__service_label)) LOGGER.info(f"{self.__service_label} - Provision service configuration") visited = set() results = [] Loading @@ -109,8 +108,7 @@ class P4FabricINTServiceHandler(_ServiceHandler): # Skip already visited devices if device.name in visited: continue LOGGER.info("Device {} - Setting up In-band Network Telemetry (INT) configuration".format( device.name)) LOGGER.info(f"Device {device.name} - Setting up In-band Network Telemetry (INT) configuration") rules = [] actual_rules = -1 Loading @@ -126,15 +124,14 @@ class P4FabricINTServiceHandler(_ServiceHandler): json_config_rules=rules ) except Exception as ex: LOGGER.error("Failed to insert INT rules on device {} due to {}".format(device.name, ex)) LOGGER.error(f"Failed to insert INT rules on device {device.name} due to {ex}") results.append(ex) finally: rules.clear() # Ensure correct status if (failed_rules == 0) and (applied_rules == actual_rules): LOGGER.info("Installed {}/{} INT rules on device {}".format( applied_rules, actual_rules, device.name)) LOGGER.info(f"Installed {applied_rules}/{actual_rules} INT rules on device {device.name}") results.append(True) # You should no longer visit this device again Loading Loading @@ -165,8 +162,7 @@ class P4FabricINTServiceHandler(_ServiceHandler): chk_type('endpoints', endpoints, list) if len(endpoints) == 0: return [] LOGGER.info("{} - Deprovision service configuration".format( self.__service_label)) LOGGER.info(f"{self.__service_label} - Deprovision service configuration") visited = set() results = [] Loading @@ -177,8 +173,7 @@ class P4FabricINTServiceHandler(_ServiceHandler): # Skip already visited devices if device.name in visited: continue LOGGER.info("Device {} - Removing In-band Network Telemetry (INT) configuration".format( device.name)) LOGGER.info(f"Device {device.name} - Removing In-band Network Telemetry (INT) configuration") rules = [] actual_rules = -1 Loading @@ -191,15 +186,14 @@ class P4FabricINTServiceHandler(_ServiceHandler): applied_rules, failed_rules = apply_rules( task_executor=self.__task_executor, device_obj=device, json_config_rules=rules) except Exception as ex: LOGGER.error("Failed to delete INT rules from device {} due to {}".format(device.name, ex)) LOGGER.error(f"Failed to delete INT rules from device {device.name} due to {ex}") results.append(ex) finally: rules.clear() # Ensure correct status if (failed_rules == 0) and (applied_rules == actual_rules): LOGGER.info("Deleted {}/{} INT rules from device {}".format( applied_rules, actual_rules, device.name)) LOGGER.info(f"Deleted {applied_rules}/{actual_rules} INT rules from device {device.name}") results.append(True) # You should no longer visit this device again Loading Loading @@ -317,9 +311,9 @@ class P4FabricINTServiceHandler(_ServiceHandler): try: self.__settings = self.__settings_handler.get('/settings') LOGGER.info("{} with settings: {}".format(self.__service_label, self.__settings)) LOGGER.info(f"{self.__service_label} with settings: {self.__settings}") except Exception as ex: LOGGER.error("Failed to retrieve service settings: {}".format(ex)) LOGGER.error(f"Failed to retrieve service settings: {ex}") raise Exception(ex) def _parse_settings(self): Loading @@ -327,32 +321,31 @@ class P4FabricINTServiceHandler(_ServiceHandler): switch_info = self.__settings.value[SWITCH_INFO] assert isinstance(switch_info, list), "Switch info object must be a list" except Exception as ex: LOGGER.error("Failed to parse service settings: {}".format(ex)) LOGGER.error(f"Failed to parse service settings: {ex}") raise Exception(ex) for switch in switch_info: for switch_name, sw_info in switch.items(): try: assert switch_name, "Invalid P4 switch name" assert isinstance(sw_info, dict), "Switch {} info must be a map with arch, dpid, mac, ip, and int_port items)" assert isinstance(sw_info, dict), f"Switch {switch_name} info must be a map with arch, dpid, mac, ip, and int_port items)" assert sw_info[ARCH] in SUPPORTED_TARGET_ARCH_LIST, \ "Switch {} - Supported P4 architectures are: {}".format(switch_name, ','.join(SUPPORTED_TARGET_ARCH_LIST)) assert sw_info[DPID] > 0, "Switch {} - P4 switch dataplane ID must be a positive integer".format(switch_name, sw_info[DPID]) assert chk_address_mac(sw_info[MAC]), "Switch {} - Invalid source Ethernet address".format(switch_name) assert chk_address_ipv4(sw_info[IP]), "Switch {} - Invalid source IP address".format(switch_name) assert isinstance(sw_info[PORT_INT], dict), "Switch {} - INT port object must be a map with port_id and port_type items".format(switch_name) assert sw_info[PORT_INT][PORT_ID] >= 0, "Switch {} - Invalid P4 switch port ID".format(switch_name) assert sw_info[PORT_INT][PORT_TYPE] in PORT_TYPES_STR_VALID, "Switch {} - Valid P4 switch port types are: {}".format( switch_name, ','.join(PORT_TYPES_STR_VALID)) f"Switch {switch_name} - Supported P4 architectures are: {','.join(SUPPORTED_TARGET_ARCH_LIST)}" assert sw_info[DPID] > 0, f"Switch {switch_name} - P4 switch dataplane ID {sw_info[DPID]} must be a positive integer" assert chk_address_mac(sw_info[MAC]), f"Switch {switch_name} - Invalid source Ethernet address" assert chk_address_ipv4(sw_info[IP]), f"Switch {switch_name} - Invalid source IP address" assert isinstance(sw_info[PORT_INT], dict), f"Switch {switch_name} - INT port object must be a map with port_id and port_type items" assert sw_info[PORT_INT][PORT_ID] >= 0, f"Switch {switch_name} - Invalid P4 switch port ID" assert sw_info[PORT_INT][PORT_TYPE] in PORT_TYPES_STR_VALID, f"Switch {switch_name} - Valid P4 switch port types are: {','.join(PORT_TYPES_STR_VALID)}" if arch_tna(sw_info[ARCH]): sw_info[RECIRCULATION_PORT_LIST] = RECIRCULATION_PORTS_TNA sw_info[INT_REPORT_MIRROR_ID_LIST] = INT_REPORT_MIRROR_ID_LIST_TNA else: sw_info[RECIRCULATION_PORT_LIST] = RECIRCULATION_PORTS_V1MODEL sw_info[INT_REPORT_MIRROR_ID_LIST] = INT_REPORT_MIRROR_ID_LIST_V1MODEL assert isinstance(sw_info[RECIRCULATION_PORT_LIST], list), "Switch {} - Recirculation ports must be described as a list".format(switch_name) assert isinstance(sw_info[RECIRCULATION_PORT_LIST], list), f"Switch {switch_name} - Recirculation ports must be described as a list" except Exception as ex: LOGGER.error("Failed to parse switch {} information".format(switch_name)) LOGGER.error(f"Failed to parse switch {switch_name} information") return self.__switch_info[switch_name] = sw_info Loading @@ -376,44 +369,41 @@ class P4FabricINTServiceHandler(_ServiceHandler): self.__int_vlan_id = self.__int_collector_info[VLAN_ID] assert chk_vlan_id(self.__int_vlan_id), "Invalid VLAN ID for INT" else: LOGGER.warning("No or invalid INT VLAN ID is provided. Default VLAN ID is set to {} (No VLAN)".\ format(self.__int_vlan_id)) LOGGER.warning(f"No or invalid INT VLAN ID is provided. Default VLAN ID is set to {self.__int_vlan_id} (No VLAN)") if self.__int_collector_info[DURATION_SEC] > 0: self.__int_collector_duration_s = self.__int_collector_info[DURATION_SEC] else: LOGGER.warning("No or invalid INT collection duration is provided. Default duration is set to {} seconds".\ format(self.__int_collector_duration_s)) LOGGER.warning(f"No or invalid INT collection duration is provided. Default duration is set to {self.__int_collector_duration_s} seconds") if self.__int_collector_info[INTERVAL_SEC] > 0: self.__int_collector_interval_s = self.__int_collector_info[INTERVAL_SEC] else: LOGGER.warning("No or invalid INT collection interval is provided. Default interval is set to {} seconds".\ format(self.__int_collector_interval_s)) LOGGER.warning(f"No or invalid INT collection interval is provided. Default interval is set to {self.__int_collector_interval_s} seconds") except Exception as ex: LOGGER.error("Failed to parse INT collector information") return def _print_settings(self): LOGGER.info("-------------------- {} settings --------------------".format(self.__service.name)) LOGGER.info(f"-------------------- {self.__service.name} settings --------------------") LOGGER.info("--- Topology info") for switch_name, switch_info in self.__switch_info.items(): LOGGER.info("\t Device {}".format(switch_name)) LOGGER.info("\t\t| Target P4 architecture: {}".format(switch_info[ARCH])) LOGGER.info("\t\t| Data plane ID: {}".format(switch_info[DPID])) LOGGER.info("\t\t| Source MAC address: {}".format(switch_info[MAC])) LOGGER.info("\t\t| Source IP address: {}".format(switch_info[IP])) LOGGER.info("\t\t| INT port ID: {}".format(switch_info[PORT_INT][PORT_ID])) LOGGER.info("\t\t| INT port type: {}".format(switch_info[PORT_INT][PORT_TYPE])) LOGGER.info("\t\t| Recirculation port list: {}".format(switch_info[RECIRCULATION_PORT_LIST])) LOGGER.info("\t\t| Report mirror ID list: {}".format(switch_info[INT_REPORT_MIRROR_ID_LIST])) LOGGER.info("--- INT collector interface: {}".format(self.__int_collector_iface)) LOGGER.info("--- INT collector MAC: {}".format(self.__int_collector_mac)) LOGGER.info("--- INT collector IP: {}".format(self.__int_collector_ip)) LOGGER.info("--- INT collector port: {}".format(self.__int_collector_port)) LOGGER.info("--- INT VLAN ID: {}".format(self.__int_vlan_id)) LOGGER.info("--- INT collector duration: {} sec".format(self.__int_collector_duration_s)) LOGGER.info("--- INT collector interval: {} sec".format(self.__int_collector_interval_s)) LOGGER.info(f"\t Device {switch_name}") LOGGER.info(f"\t\t| Target P4 architecture: {switch_info[ARCH]}") LOGGER.info(f"\t\t| Data plane ID: {switch_info[DPID]}") LOGGER.info(f"\t\t| Source MAC address: {switch_info[MAC]}") LOGGER.info(f"\t\t| Source IP address: {switch_info[IP]}") LOGGER.info(f"\t\t| INT port ID: {switch_info[PORT_INT][PORT_ID]}") LOGGER.info(f"\t\t| INT port type: {switch_info[PORT_INT][PORT_TYPE]}") LOGGER.info(f"\t\t| Recirculation port list: {switch_info[RECIRCULATION_PORT_LIST]}") LOGGER.info(f"\t\t| Report mirror ID list: {switch_info[INT_REPORT_MIRROR_ID_LIST]}") LOGGER.info(f"--- INT collector interface: {self.__int_collector_iface}") LOGGER.info(f"--- INT collector MAC: {self.__int_collector_mac}") LOGGER.info(f"--- INT collector IP: {self.__int_collector_ip}") LOGGER.info(f"--- INT collector port: {self.__int_collector_port}") LOGGER.info(f"--- INT VLAN ID: {self.__int_vlan_id}") LOGGER.info(f"--- INT collector duration: {self.__int_collector_duration_s} sec") LOGGER.info(f"--- INT collector interval: {self.__int_collector_interval_s} sec") LOGGER.info("-----------------------------------------------------------------") def _create_rules(self, device_obj : Device, action : ConfigActionEnum): # type: ignore Loading Loading @@ -529,11 +519,11 @@ class P4FabricINTServiceHandler(_ServiceHandler): # Get the context ctx_id = response.context_ids[0].context_uuid.uuid assert ctx_id, "Cannot create INT collector with invalid context ID" LOGGER.debug("Context ID: {}".format(ctx_id)) LOGGER.debug(f"Context ID: {ctx_id}") service_id = self.__service.service_id.service_uuid.uuid assert service_id, "Cannot create INT collector with invalid service ID" LOGGER.debug("Service ID: {}".format(service_id)) LOGGER.debug(f"Service ID: {service_id}") # Get a service endpoint svc_endpoints = self.__service.service_endpoint_ids[0] Loading @@ -542,14 +532,14 @@ class P4FabricINTServiceHandler(_ServiceHandler): # Get a P4 device associated with this endpoint dev_id = svc_endpoints.device_id.device_uuid.uuid assert dev_id, "Cannot create INT collector with invalid device ID" LOGGER.debug("Device ID: {}".format(dev_id)) LOGGER.debug(f"Device ID: {dev_id}") # Get the endpoint ID ep_id = svc_endpoints.endpoint_uuid.uuid assert ep_id, "Cannot create INT collector with invalid endpoint ID" LOGGER.debug("Endpoint ID: {}".format(ep_id)) LOGGER.debug(f"Endpoint ID: {ep_id}") except Exception as ex: LOGGER.error("Failed to retrieve context for starting the INT collector: {}".format(ex)) LOGGER.error(f"Failed to retrieve context for starting the INT collector: {ex}") raise ex return ctx_id, service_id, dev_id, ep_id Loading @@ -558,8 +548,8 @@ class P4FabricINTServiceHandler(_ServiceHandler): ctx_id = service_id = dev_id = ep_id = None try: ctx_id, service_id, dev_id, ep_id = self._retrieve_context_for_int_collector() except Exception: LOGGER.error("INT collector cannot be initialized due to missing information") except Exception as ex: LOGGER.error(f"INT collector cannot be initialized: Failed to retrieve context {ex}") return # Create a "virtual" INT KPI associated with this context and P4 dataplane Loading @@ -575,9 +565,9 @@ class P4FabricINTServiceHandler(_ServiceHandler): # Set this new KPI kpi_manager_client = KpiManagerClient() kpi_id_int: KpiId = kpi_manager_client.SetKpiDescriptor(kpi_descriptor_int) # type: ignore LOGGER.debug("INT KPI ID: {}".format(kpi_id_int)) LOGGER.debug(f"INT KPI ID: {kpi_id_int}") except Exception: LOGGER.error("INT collector cannot be initialized due to failed KPI initialization") LOGGER.error(f"INT collector cannot be initialized: Failed to initialize KPI {ex}") return # Initialize an INT collector object Loading @@ -591,13 +581,19 @@ class P4FabricINTServiceHandler(_ServiceHandler): collect_int.int_collector.transport_port = self.__int_collector_port collect_int.int_collector.service_id = service_id collect_int.int_collector.context_id = ctx_id LOGGER.info("INT Collector: {}".format(str(collect_int))) LOGGER.info(f"INT Collector: {str(collect_int)}") except Exception as ex: LOGGER.error(f"INT collector cannot be initialized: Failed to create collector object {ex}") return # Start the INT collector c_id = None try: telemetry_frontend_client = TelemetryFrontendClient() collect_id: CollectorId = telemetry_frontend_client.StartCollector(collect_int) # type: ignore assert collect_id.uuid, "INT collector failed to start" except Exception: LOGGER.error("INT collector cannot be initialized") c_id: CollectorId = telemetry_frontend_client.StartCollector(collect_int) # type: ignore assert c_id.collector_id.uuid, "INT collector failed to start" except Exception as ex: LOGGER.error(f"INT collector cannot be initialized: Failed to start the collector {ex}") return LOGGER.info("INT collector with ID {} is successfully invoked".format(collect_id)) LOGGER.info(f"INT collector with ID {c_id.collector_id.uuid} is successfully invoked")