diff --git a/src/service/service/service_handlers/p4_fabric_tna_acl/p4_fabric_tna_acl_service_handler.py b/src/service/service/service_handlers/p4_fabric_tna_acl/p4_fabric_tna_acl_service_handler.py index 2d2c0f3d928554e8876a06d0fad9abe1b6dd43e9..3182f9aa414db9913db4d2ab82e3b6870f67bea8 100644 --- a/src/service/service/service_handlers/p4_fabric_tna_acl/p4_fabric_tna_acl_service_handler.py +++ b/src/service/service/service_handlers/p4_fabric_tna_acl/p4_fabric_tna_acl_service_handler.py @@ -407,6 +407,8 @@ class P4FabricACLServiceHandler(_ServiceHandler): # Retrieve entry from the port map switch_port_entry = self._get_switch_port_in_port_map(switch_name, port_id) + if not switch_port_entry: + continue # Add routing entry switch_port_entry[ACL].append(map_entry) @@ -429,9 +431,9 @@ class P4FabricACLServiceHandler(_ServiceHandler): switch_entry = self.__port_map[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], f"Port with ID {port_id} does not exist in the switch map" - - return switch_entry[port_key] + if port_key in switch_entry: + return switch_entry[port_key] + return {} def _get_acl_of_switch_port(self, switch_name : str, port_id : int) -> List [Tuple]: switch_port_entry = self._get_switch_port_in_port_map(switch_name, port_id) diff --git a/src/service/service/service_handlers/p4_fabric_tna_commons/p4_fabric_tna_commons.py b/src/service/service/service_handlers/p4_fabric_tna_commons/p4_fabric_tna_commons.py index 56407d6d83f63e579e8c8a22f9ac7eebf1a51f71..01ae3a38364768dbe66ffcf8e63c74100dc5162f 100644 --- a/src/service/service/service_handlers/p4_fabric_tna_commons/p4_fabric_tna_commons.py +++ b/src/service/service/service_handlers/p4_fabric_tna_commons/p4_fabric_tna_commons.py @@ -44,11 +44,14 @@ IP = "ip" PORT = "port" # Dataplane port PORT_ID = "port_id" PORT_TYPE = "port_type" +NEXT_ID = "next_id" VLAN_ID = "vlan_id" RECIRCULATION_PORT_LIST = "recirculation_port_list" PORT_LIST = "port_list" PORT_PREFIX = "port-" +FORWARDING_TYPE = "fwd_type" FORWARDING_LIST = "fwd_list" +ROUTING_TYPE = "routing_type" ROUTING_LIST = "routing_list" HOST_LIST = "host_list" HOST_MAC = "host_mac" @@ -90,7 +93,7 @@ CLONE_SESSION = "/clone_sessions/clone_session" # Forwarding types FORWARDING_TYPE_BRIDGING = 0 FORWARDING_TYPE_MPLS = 1 -FORWARDING_TYPE_UNICAST_IPV4 = 2 +FORWARDING_TYPE_IPV4_UNICAST = 2 FORWARDING_TYPE_IPV4_MULTICAST = 3 FORWARDING_TYPE_IPV6_UNICAST = 4 FORWARDING_TYPE_IPV6_MULTICAST = 5 @@ -99,13 +102,50 @@ FORWARDING_TYPE_UNKNOWN = 7 FORWARDING_TYPES_VALID = [ FORWARDING_TYPE_BRIDGING, FORWARDING_TYPE_MPLS, - FORWARDING_TYPE_UNICAST_IPV4, + FORWARDING_TYPE_IPV4_UNICAST, FORWARDING_TYPE_IPV4_MULTICAST, FORWARDING_TYPE_IPV6_UNICAST, FORWARDING_TYPE_IPV6_MULTICAST, FORWARDING_TYPE_UNKNOWN ] +FORWARDING_TYPE_STR_BRIDGING = "bridging" +FORWARDING_TYPE_STR_MPLS = "mpls" +FORWARDING_TYPE_STR_IPV4_UNICAST = "ipv4-unicast" +FORWARDING_TYPE_STR_IPV4_MULTICAST = "ipv4-multicast" +FORWARDING_TYPE_STR_IPV6_UNICAST = "ipv6-unicast" +FORWARDING_TYPE_STR_IPV6_MULTICAST = "ipv6-multicast" +FORWARDING_TYPE_STR_UNKNOWN = "unknown" + +FORWARDING_TYPES_STR_VALID = [ + FORWARDING_TYPE_STR_BRIDGING, + FORWARDING_TYPE_STR_MPLS, + FORWARDING_TYPE_STR_IPV4_UNICAST, + FORWARDING_TYPE_STR_IPV4_MULTICAST, + FORWARDING_TYPE_STR_IPV6_UNICAST, + FORWARDING_TYPE_STR_IPV6_MULTICAST, + FORWARDING_TYPE_STR_UNKNOWN +] + +FWD_TYPE_MAP = { + FORWARDING_TYPE_STR_BRIDGING : FORWARDING_TYPE_BRIDGING, + FORWARDING_TYPE_STR_MPLS : FORWARDING_TYPE_MPLS, + FORWARDING_TYPE_STR_IPV4_UNICAST : FORWARDING_TYPE_IPV4_UNICAST, + FORWARDING_TYPE_STR_IPV4_MULTICAST : FORWARDING_TYPE_IPV4_MULTICAST, + FORWARDING_TYPE_STR_IPV6_UNICAST : FORWARDING_TYPE_IPV6_UNICAST, + FORWARDING_TYPE_STR_IPV6_MULTICAST : FORWARDING_TYPE_IPV6_MULTICAST, + FORWARDING_TYPE_STR_UNKNOWN : FORWARDING_TYPE_UNKNOWN +} + +# Routing types +ROUTING_TYPE_STR_SIMPLE = "simple" +ROUTING_TYPE_STR_HASHED = "hashed" + +ROUTING_TYPES_STR_VALID = [ + ROUTING_TYPE_STR_SIMPLE, + ROUTING_TYPE_STR_HASHED +] + # Port types PORT_TYPE_INT = "int" PORT_TYPE_HOST = "host" @@ -555,7 +595,7 @@ def rules_set_up_next_profile_hashed_output( 'action-params': [ { 'action-param': 'port_num', - 'action-value': str(next_id) + 'action-value': str(next_id) # TODO: Fix } ] } @@ -595,7 +635,7 @@ def rules_set_up_next_output_simple( 'action-params': [ { 'action-param': 'port_num', - 'action-value': str(next_id) + 'action-value': str(port_id) } ] } @@ -679,7 +719,7 @@ def rules_set_up_next_profile_hashed_routing( 'action-params': [ { 'action-param': 'port_num', - 'action-value': str(next_id) + 'action-value': str(next_id) # TODO: Fix }, { 'action-param': 'smac', @@ -778,7 +818,7 @@ def rules_set_up_next_routing_simple( 'action-params': [ { 'action-param': 'port_num', - 'action-value': str(next_id) + 'action-value': str(port_id) }, { 'action-param': 'smac', diff --git a/src/service/service/service_handlers/p4_fabric_tna_int/p4_fabric_tna_int_service_handler.py b/src/service/service/service_handlers/p4_fabric_tna_int/p4_fabric_tna_int_service_handler.py index a2681556ef00dd43b35a41dcde9b3242ec6b616f..ed7e78194bebe5171add5df7e00579ee13e04e71 100644 --- a/src/service/service/service_handlers/p4_fabric_tna_int/p4_fabric_tna_int_service_handler.py +++ b/src/service/service/service_handlers/p4_fabric_tna_int/p4_fabric_tna_int_service_handler.py @@ -332,11 +332,23 @@ class P4FabricINTServiceHandler(_ServiceHandler): assert sw_info[ARCH] in SUPPORTED_TARGET_ARCH_LIST, \ 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" + + fwd_type_str = sw_info[FORWARDING_TYPE] + assert fwd_type_str in FORWARDING_TYPES_STR_VALID, \ + f"Switch {switch_name} - Supported forwarding types are: {','.join(FORWARDING_TYPES_STR_VALID)}" + fwd_type_int = FWD_TYPE_MAP[fwd_type_str] + assert fwd_type_int in FORWARDING_TYPES_VALID, \ + f"Switch {switch_name} - Supported forwarding types are: {','.join(FORWARDING_TYPES_VALID)}" + routing_type_str = sw_info[ROUTING_TYPE] + assert routing_type_str in ROUTING_TYPES_STR_VALID, \ + f"Switch {switch_name} - Supported routing types are: {','.join(ROUTING_TYPES_STR_VALID)}" + 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)}" + assert sw_info[PORT_INT][NEXT_ID] >= 0, f"Switch {switch_name} - Invalid P4 switch next ID" 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 @@ -391,10 +403,13 @@ class P4FabricINTServiceHandler(_ServiceHandler): 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| Forwarding type: {switch_info[FORWARDING_TYPE]}") + LOGGER.info(f"\t\t| Routing type: {switch_info[ROUTING_TYPE]}") 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| INT port next: {switch_info[PORT_INT][NEXT_ID]}") 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}") @@ -406,12 +421,22 @@ class P4FabricINTServiceHandler(_ServiceHandler): LOGGER.info(f"--- INT collector interval: {self.__int_collector_interval_s} sec") LOGGER.info("-----------------------------------------------------------------") + def _get_fwd_type_of_switch(self, switch_name : str) -> int: + fwd_type_str = self.__switch_info[switch_name][FORWARDING_TYPE] + return FWD_TYPE_MAP[fwd_type_str] + + def _get_routing_type_of_switch(self, switch_name : str) -> int: + return self.__switch_info[switch_name][ROUTING_TYPE] + def _create_rules(self, device_obj : Device, action : ConfigActionEnum): # type: ignore dev_name = device_obj.name rules = [] + fwd_type = self._get_fwd_type_of_switch(dev_name) + routing_type = self._get_routing_type_of_switch(dev_name) + port_id = self.__switch_info[dev_name][PORT_INT][PORT_ID] - next_id = port_id + next_id = self.__switch_info[dev_name][PORT_INT][NEXT_ID] mac_src = self.__switch_info[dev_name][MAC] collector_mac_dst = self.__int_collector_mac collector_ip_dst = self.__int_collector_ip @@ -428,7 +453,7 @@ class P4FabricINTServiceHandler(_ServiceHandler): rules += rules_set_up_int_recirculation_ports( recirculation_port_list=self.__switch_info[dev_name][RECIRCULATION_PORT_LIST], port_type=PORT_TYPE_INT, - fwd_type=FORWARDING_TYPE_UNICAST_IPV4, + fwd_type=FORWARDING_TYPE_IPV4_UNICAST, # For INT packets, fwd type is fixed to IPv4 unicast vlan_id=vlan_id, action=action ) @@ -472,7 +497,7 @@ class P4FabricINTServiceHandler(_ServiceHandler): rules += rules_set_up_port( port_id=port_id, port_type=PORT_TYPE_HOST, - fwd_type=FORWARDING_TYPE_BRIDGING, + fwd_type=fwd_type, # Normally this is bridging vlan_id=vlan_id, action=action ) @@ -480,33 +505,81 @@ class P4FabricINTServiceHandler(_ServiceHandler): LOGGER.error("Error while creating INT port rules") raise Exception(ex) - ### INT port forwarding rules - try: - rules += rules_set_up_fwd_bridging( - port_id=port_id, - vlan_id=vlan_id, - eth_dst=collector_mac_dst, - next_id=next_id, - action=action - ) - rules += rules_set_up_next_profile_hashed_routing( - port_id=port_id, - next_id=next_id, - eth_src=mac_src, - eth_dst=collector_mac_dst, - action=action - ) - except Exception as ex: - LOGGER.error("Error while creating INT bridging rules") - raise Exception(ex) + ### INT forwarding rules + if fwd_type == FORWARDING_TYPE_BRIDGING: + try: + rules += rules_set_up_fwd_bridging( + port_id=port_id, + vlan_id=vlan_id, + eth_dst=collector_mac_dst, + next_id=next_id, + action=action + ) + except Exception as ex: + LOGGER.error("Error while creating INT bridging rule") + raise Exception(ex) + + if routing_type == ROUTING_TYPE_STR_HASHED: + try: + rules += rules_set_up_next_profile_hashed_routing( + port_id=port_id, + next_id=next_id, + eth_src=mac_src, + eth_dst=collector_mac_dst, + action=action + ) + except Exception as ex: + LOGGER.error("Error while creating INT next hashed profile rule") + raise Exception(ex) + elif routing_type == ROUTING_TYPE_STR_SIMPLE: + try: + rules += rules_set_up_pre_next_vlan( + port_id=port_id, + next_id=next_id, + vlan_id=vlan_id, + action=action + ) + except Exception as ex: + LOGGER.error("Error while creating INT pre-next VLAN rule") + raise Exception(ex) + + try: + rules += rules_set_up_next_output_simple( + port_id=port_id, + next_id=next_id, + action=action + ) + except Exception as ex: + LOGGER.error("Error while creating INT next output simple rule") + raise Exception(ex) ### INT packet routing rules + if routing_type == ROUTING_TYPE_STR_HASHED: + try: + rules += rules_set_up_next_hashed( + port_id=port_id, + next_id=next_id, + action=action + ) + except Exception as ex: + LOGGER.error("Error while creating INT next hashed routing rule") + raise Exception(ex) + elif routing_type == ROUTING_TYPE_STR_SIMPLE: + try: + ### Next routing simple + rules += rules_set_up_next_routing_simple( + port_id=port_id, + next_id=next_id, + eth_src=mac_src, + eth_dst=collector_mac_dst, + action=action + ) + except Exception as ex: + LOGGER.error("Error while creating INT next simple routing rule") + raise Exception(ex) + try: - rules += rules_set_up_next_hashed( - port_id=port_id, - next_id=next_id, - action=action - ) + # Routing destination rules += rules_set_up_routing( port_id=port_id, ipv4_dst=collector_ip_dst, @@ -515,7 +588,7 @@ class P4FabricINTServiceHandler(_ServiceHandler): action=action ) except Exception as ex: - LOGGER.error("Error while creating INT routing rules") + LOGGER.error("Error while creating static INT L3 routing rule") raise Exception(ex) return rules diff --git a/src/service/service/service_handlers/p4_fabric_tna_l2_simple/p4_fabric_tna_l2_simple_service_handler.py b/src/service/service/service_handlers/p4_fabric_tna_l2_simple/p4_fabric_tna_l2_simple_service_handler.py index 5f6c0874422f32ba4f9cae5fc37230056920a765..4fea06affdae87f658ba62ae54216b6a0955bcfe 100644 --- a/src/service/service/service_handlers/p4_fabric_tna_l2_simple/p4_fabric_tna_l2_simple_service_handler.py +++ b/src/service/service/service_handlers/p4_fabric_tna_l2_simple/p4_fabric_tna_l2_simple_service_handler.py @@ -102,6 +102,11 @@ class P4FabricL2SimpleServiceHandler(_ServiceHandler): if dev_port_key in visited: continue + # Skip device ports without associated rules + if not self._get_switch_port_in_port_map(device_name, port_id): + LOGGER.warning(f"No rules associated with port {port_id} on device {device.name}") + continue + rules = [] actual_rules = -1 applied_rules, failed_rules = 0, -1 @@ -177,6 +182,11 @@ class P4FabricL2SimpleServiceHandler(_ServiceHandler): if dev_port_key in visited: continue + # Skip device ports without associated rules + if not self._get_switch_port_in_port_map(device_name, port_id): + LOGGER.warning(f"No rules associated with port {port_id} on device {device.name}") + continue + rules = [] actual_rules = -1 applied_rules, failed_rules = 0, -1 @@ -331,6 +341,10 @@ class P4FabricL2SimpleServiceHandler(_ServiceHandler): f"Switch {switch_name} - Supported P4 architectures are: {','.join(SUPPORTED_TARGET_ARCH_LIST)}" switch_dpid = sw_info[DPID] assert switch_dpid > 0, f"Switch {switch_name} - P4 switch dataplane ID {sw_info[DPID]} must be a positive integer" + sw_info[FORWARDING_TYPE] = FORWARDING_TYPE_STR_BRIDGING + routing_type_str = sw_info[ROUTING_TYPE] + assert routing_type_str in ROUTING_TYPES_STR_VALID, \ + f"Switch {switch_name} - Supported routing types are: {','.join(ROUTING_TYPES_STR_VALID)}" # Port list port_list = sw_info[PORT_LIST] @@ -352,7 +366,7 @@ class P4FabricL2SimpleServiceHandler(_ServiceHandler): self.__port_map[switch_name][port_key][PORT_ID] = port_id self.__port_map[switch_name][port_key][PORT_TYPE] = port_type self.__port_map[switch_name][port_key][VLAN_ID] = vlan_id - self.__port_map[switch_name][port_key][FORWARDING_LIST] = [] + self.__port_map[switch_name][port_key][FORWARDING_LIST] = {} # Forwarding list fwd_list = sw_info[FORWARDING_LIST] @@ -360,15 +374,25 @@ class P4FabricL2SimpleServiceHandler(_ServiceHandler): for fwd_entry in fwd_list: port_id = fwd_entry[PORT_ID] assert port_id >= 0, f"Invalid port ID: {port_id}" + next_id = fwd_entry[NEXT_ID] + assert next_id >= 0, f"Invalid next ID: {next_id}" host_mac = fwd_entry[HOST_MAC] assert chk_address_mac(host_mac), f"Invalid host MAC address {host_mac}" # Retrieve entry from the port map switch_port_entry = self._get_switch_port_in_port_map(switch_name, port_id) + if not switch_port_entry: + continue host_facing_port = self._is_host_facing_port(switch_name, port_id) LOGGER.info(f"Switch {switch_name} - Port {port_id}: Is host facing: {"True" if host_facing_port else "False"}") - switch_port_entry[FORWARDING_LIST].append(host_mac) + switch_port_entry[FORWARDING_LIST].append( + { + PORT_ID: port_id, + NEXT_ID: next_id, + HOST_MAC: host_mac + } + ) self.__switch_info[switch_name] = sw_info def _print_settings(self): @@ -378,18 +402,27 @@ class P4FabricL2SimpleServiceHandler(_ServiceHandler): 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| Forwarding type: {switch_info[FORWARDING_TYPE]}") + LOGGER.info(f"\t\t| Routing type: {switch_info[ROUTING_TYPE]}") LOGGER.info(f"\t\t| Port map: {self.__port_map[switch_name]}") LOGGER.info("-------------------------------------------------------") + def _get_fwd_type_of_switch(self, switch_name : str) -> int: + fwd_type_str = self.__switch_info[switch_name][FORWARDING_TYPE] + return FWD_TYPE_MAP[fwd_type_str] + + def _get_routing_type_of_switch(self, switch_name : str) -> int: + return self.__switch_info[switch_name][ROUTING_TYPE] + 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, f"Switch {switch_name} does not exist in the port map" port_key = PORT_PREFIX + str(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] + if port_key in switch_entry: + return switch_entry[port_key] + return {} def _get_port_type_of_switch_port(self, switch_name : str, port_id : int) -> str: switch_port_entry = self._get_switch_port_in_port_map(switch_name, port_id) @@ -409,8 +442,10 @@ class P4FabricL2SimpleServiceHandler(_ServiceHandler): def _create_rules(self, device_obj : Device, port_id : int, action : ConfigActionEnum): # type: ignore dev_name = device_obj.name - # TODO: Fix - next_id = 2 if port_id == 1 else 1 + fwd_type = self._get_fwd_type_of_switch(dev_name) + routing_type = self._get_routing_type_of_switch(dev_name) + + vlan_id = self._get_vlan_id_of_switch_port(switch_name=dev_name, port_id=port_id) host_facing_port = self._is_host_facing_port(dev_name, port_id) LOGGER.info(f"\t | Service endpoint is host facing: {"True" if host_facing_port else "False"}") @@ -422,27 +457,32 @@ class P4FabricL2SimpleServiceHandler(_ServiceHandler): if host_facing_port: rules += rules_set_up_port_host( port=port_id, - vlan_id=self._get_vlan_id_of_switch_port(switch_name=dev_name, port_id=port_id), - action=action + vlan_id=vlan_id, + action=action, + fwd_type=fwd_type ) else: rules += rules_set_up_port_switch( port=port_id, - vlan_id=self._get_vlan_id_of_switch_port(switch_name=dev_name, port_id=port_id), - action=action + vlan_id=vlan_id, + action=action, + fwd_type=fwd_type ) except Exception as ex: LOGGER.error("Error while creating port setup rules") raise Exception(ex) - fwd_list = self._get_fwd_list_of_switch_port(switch_name=dev_name, port_id=next_id) - for mac_dst in fwd_list: - LOGGER.info(f"Switch {dev_name} - Port {port_id} - Creating rule for destination MAC: {mac_dst}") + fwd_list = self._get_fwd_list_of_switch_port(switch_name=dev_name, port_id=port_id) + for fwd_entry in fwd_list: + next_id = fwd_entry[NEXT_ID] + mac_dst = fwd_entry[HOST_MAC] + + LOGGER.info(f"Switch {dev_name} - Port {port_id} - Creating rule for destination MAC: {mac_dst} - Next ID: {next_id}") try: ### Bridging rules rules += rules_set_up_fwd_bridging( port_id=port_id, - vlan_id=self._get_vlan_id_of_switch_port(switch_name=dev_name, port_id=port_id), + vlan_id=vlan_id, eth_dst=mac_dst, next_id=next_id, action=action @@ -453,28 +493,51 @@ class P4FabricL2SimpleServiceHandler(_ServiceHandler): src_list = self._get_fwd_list_of_switch_port(switch_name=dev_name, port_id=port_id) for mac_src in src_list: + if routing_type == ROUTING_TYPE_STR_HASHED: + try: + ### Next profile for hashed routing + rules += rules_set_up_next_profile_hashed_routing( + port_id=port_id, + next_id=next_id, + eth_src=mac_src, + eth_dst=mac_dst, + action=action + ) + except Exception as ex: + LOGGER.error("Error while creating rule for next hashed profile") + raise Exception(ex) + elif routing_type == ROUTING_TYPE_STR_SIMPLE: + try: + rules += rules_set_up_pre_next_vlan( + port_id=port_id, + next_id=next_id, + vlan_id=vlan_id, + action=action + ) + except Exception as ex: + LOGGER.error("Error while creating pre-next VLAN rule") + raise Exception(ex) + + try: + rules += rules_set_up_next_output_simple( + port_id=port_id, + next_id=next_id, + action=action + ) + except Exception as ex: + LOGGER.error("Error while creating next output simple rule") + raise Exception(ex) + + if routing_type == ROUTING_TYPE_STR_HASHED: try: - ### Next profile for hashed routing - rules += rules_set_up_next_profile_hashed_routing( + ### Next hashed port + rules += rules_set_up_next_hashed( port_id=port_id, next_id=next_id, - eth_src=mac_src, - eth_dst=mac_dst, action=action ) except Exception as ex: - LOGGER.error("Error while creating rule for next hashed profile") + LOGGER.error("Error while creating rule for next hashed port") raise Exception(ex) - try: - ### Next hashed port - rules += rules_set_up_next_hashed( - port_id=port_id, - next_id=next_id, - action=action - ) - except Exception as ex: - LOGGER.error("Error while creating rule for next hashed port") - raise Exception(ex) - return rules diff --git a/src/service/service/service_handlers/p4_fabric_tna_l3/p4_fabric_tna_l3_service_handler.py b/src/service/service/service_handlers/p4_fabric_tna_l3/p4_fabric_tna_l3_service_handler.py index d9545b9acc7edb793e0f229d0b141c9474ccba8a..80c4e2721de3f4c19a9747e915e9c4d5c265d12c 100644 --- a/src/service/service/service_handlers/p4_fabric_tna_l3/p4_fabric_tna_l3_service_handler.py +++ b/src/service/service/service_handlers/p4_fabric_tna_l3/p4_fabric_tna_l3_service_handler.py @@ -102,6 +102,11 @@ class P4FabricL3ServiceHandler(_ServiceHandler): if dev_port_key in visited: continue + # Skip device ports without associated rules + if not self._get_switch_port_in_port_map(device_name, port_id): + LOGGER.warning(f"No rules associated with port {port_id} on device {device.name}") + continue + rules = [] actual_rules = -1 applied_rules, failed_rules = 0, -1 @@ -124,7 +129,7 @@ class P4FabricL3ServiceHandler(_ServiceHandler): # Ensure correct status if (failed_rules == 0) and (applied_rules == actual_rules): - LOGGER.info(f"Installed {applied_rules}/{actual_rules} ACL rules on device {device_name} and port {port_id}") + LOGGER.info(f"Installed {applied_rules}/{actual_rules} L3 rules on device {device_name} and port {port_id}") results.append(True) # You should no longer visit this device port again @@ -177,6 +182,11 @@ class P4FabricL3ServiceHandler(_ServiceHandler): if dev_port_key in visited: continue + # Skip device ports without associated rules + if not self._get_switch_port_in_port_map(device_name, port_id): + LOGGER.warning(f"No rules associated with port {port_id} on device {device.name}") + continue + rules = [] actual_rules = -1 applied_rules, failed_rules = 0, -1 @@ -331,6 +341,15 @@ class P4FabricL3ServiceHandler(_ServiceHandler): f"Switch {switch_name} - Supported P4 architectures are: {','.join(SUPPORTED_TARGET_ARCH_LIST)}" switch_dpid = sw_info[DPID] assert switch_dpid > 0, f"Switch {switch_name} - P4 switch dataplane ID {sw_info[DPID]} must be a positive integer" + fwd_type_str = sw_info[FORWARDING_TYPE] + assert fwd_type_str in FORWARDING_TYPES_STR_VALID, \ + f"Switch {switch_name} - Supported forwarding types are: {','.join(FORWARDING_TYPES_STR_VALID)}" + fwd_type_int = FWD_TYPE_MAP[fwd_type_str] + assert fwd_type_int in FORWARDING_TYPES_VALID, \ + f"Switch {switch_name} - Supported forwarding types are: {','.join(FORWARDING_TYPES_VALID)}" + routing_type_str = sw_info[ROUTING_TYPE] + assert routing_type_str in ROUTING_TYPES_STR_VALID, \ + f"Switch {switch_name} - Supported routing types are: {','.join(ROUTING_TYPES_STR_VALID)}" # Port list port_list = sw_info[PORT_LIST] @@ -360,6 +379,8 @@ class P4FabricL3ServiceHandler(_ServiceHandler): for rt_entry in routing_list: port_id = rt_entry[PORT_ID] assert port_id >= 0, f"Invalid port ID: {port_id}" + next_id = rt_entry[NEXT_ID] + assert next_id >= 0, f"Invalid next ID: {next_id}" ipv4_dst = rt_entry[IPV4_DST] assert chk_address_ipv4(ipv4_dst), f"Invalid destination IPv4 address {ipv4_dst}" ipv4_prefix_len = rt_entry[IPV4_PREFIX_LEN] @@ -371,11 +392,14 @@ class P4FabricL3ServiceHandler(_ServiceHandler): # Retrieve entry from the port map switch_port_entry = self._get_switch_port_in_port_map(switch_name, port_id) + if not switch_port_entry: + continue # Add routing entry switch_port_entry[ROUTING_LIST].append( { PORT_ID: port_id, + NEXT_ID: next_id, IPV4_DST: ipv4_dst, IPV4_PREFIX_LEN: ipv4_prefix_len, MAC_SRC: mac_src, @@ -391,18 +415,27 @@ class P4FabricL3ServiceHandler(_ServiceHandler): 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| Forwarding type: {switch_info[FORWARDING_TYPE]}") + LOGGER.info(f"\t\t| Routing type: {switch_info[ROUTING_TYPE]}") LOGGER.info(f"\t\t| Port map: {self.__port_map[switch_name]}") LOGGER.info("-------------------------------------------------------") + def _get_fwd_type_of_switch(self, switch_name : str) -> int: + fwd_type_str = self.__switch_info[switch_name][FORWARDING_TYPE] + return FWD_TYPE_MAP[fwd_type_str] + + def _get_routing_type_of_switch(self, switch_name : str) -> int: + return self.__switch_info[switch_name][ROUTING_TYPE] + 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, f"Switch {switch_name} does not exist in the port map" port_key = PORT_PREFIX + str(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] + if port_key in switch_entry: + return switch_entry[port_key] + return {} def _get_port_type_of_switch_port(self, switch_name : str, port_id : int) -> str: switch_port_entry = self._get_switch_port_in_port_map(switch_name, port_id) @@ -422,8 +455,8 @@ class P4FabricL3ServiceHandler(_ServiceHandler): def _create_rules(self, device_obj : Device, port_id : int, action : ConfigActionEnum): # type: ignore dev_name = device_obj.name - # TODO: Fix - next_id = 2 if port_id ==1 else 1 + fwd_type = self._get_fwd_type_of_switch(dev_name) + routing_type = self._get_routing_type_of_switch(dev_name) host_facing_port = self._is_host_facing_port(dev_name, port_id) LOGGER.info(f"\t | Service endpoint is host facing: {"True" if host_facing_port else "False"}") @@ -436,57 +469,75 @@ class P4FabricL3ServiceHandler(_ServiceHandler): rules += rules_set_up_port_host( port=port_id, vlan_id=self._get_vlan_id_of_switch_port(switch_name=dev_name, port_id=port_id), - action=action + action=action, + fwd_type=fwd_type ) else: rules += rules_set_up_port_switch( port=port_id, vlan_id=self._get_vlan_id_of_switch_port(switch_name=dev_name, port_id=port_id), - action=action + action=action, + fwd_type=fwd_type ) except Exception as ex: LOGGER.error("Error while creating port setup rules") raise Exception(ex) ### Static routing rules - routing_list = self._get_routing_list_of_switch_port(switch_name=dev_name, port_id=next_id) + routing_list = self._get_routing_list_of_switch_port(switch_name=dev_name, port_id=port_id) for rt_entry in routing_list: - try: - ### Bridging rules - rules += rules_set_up_fwd_bridging( - port_id=port_id, - vlan_id=self._get_vlan_id_of_switch_port(switch_name=dev_name, port_id=port_id), - eth_dst=rt_entry[MAC_DST], - next_id=next_id, - action=action - ) - except Exception as ex: - LOGGER.error("Error while creating rule for bridging") - raise Exception(ex) - - try: - ### Next profile for hashed routing - rules += rules_set_up_next_profile_hashed_routing( - port_id=port_id, - next_id=next_id, - eth_src=rt_entry[MAC_SRC], - eth_dst=rt_entry[MAC_DST], - action=action - ) - except Exception as ex: - LOGGER.error("Error while creating rule for next hashed profile") - raise Exception(ex) - - try: - ### Next hashed port - rules += rules_set_up_next_hashed( - port_id=port_id, - next_id=next_id, - action=action - ) - except Exception as ex: - LOGGER.error("Error while creating rule for next hashed port") - raise Exception(ex) + # Pass through the bridging table only if port is setup on bridging mode + if fwd_type == FORWARDING_TYPE_BRIDGING: + try: + ### Bridging rules + rules += rules_set_up_fwd_bridging( + port_id=port_id, + vlan_id=self._get_vlan_id_of_switch_port(switch_name=dev_name, port_id=port_id), + eth_dst=rt_entry[MAC_DST], + next_id=rt_entry[NEXT_ID], + action=action + ) + except Exception as ex: + LOGGER.error("Error while creating rule for bridging") + raise Exception(ex) + + if routing_type == ROUTING_TYPE_STR_SIMPLE: + try: + ### Next routing simple + rules += rules_set_up_next_routing_simple( + port_id=port_id, + next_id=rt_entry[NEXT_ID], + eth_src=rt_entry[MAC_SRC], + eth_dst=rt_entry[MAC_DST], + action=action + ) + except Exception as ex: + LOGGER.error("Error while creating rule for next simple") + raise Exception(ex) + elif routing_type == ROUTING_TYPE_STR_HASHED: + try: + ### Next profile for hashed routing + rules += rules_set_up_next_profile_hashed_routing( + port_id=port_id, + next_id=rt_entry[NEXT_ID], + eth_src=rt_entry[MAC_SRC], + eth_dst=rt_entry[MAC_DST], + action=action + ) + except Exception as ex: + LOGGER.error("Error while creating rule for next hashed profile") + raise Exception(ex) + + try: + ### Next hashed port + rules += rules_set_up_next_hashed( + port_id=port_id, + next_id=rt_entry[NEXT_ID], + action=action + ) + except Exception as ex: + LOGGER.error("Error while creating rule for next hashed port") + raise Exception(ex) try: # Routing destination @@ -494,7 +545,7 @@ class P4FabricL3ServiceHandler(_ServiceHandler): port_id=port_id, ipv4_dst=rt_entry[IPV4_DST], ipv4_prefix_len=rt_entry[IPV4_PREFIX_LEN], - next_id=next_id, + next_id=rt_entry[NEXT_ID], action=action ) except Exception as ex: diff --git a/src/service/service/service_handlers/p4_fabric_tna_upf/p4_fabric_tna_upf_service_handler.py b/src/service/service/service_handlers/p4_fabric_tna_upf/p4_fabric_tna_upf_service_handler.py index 8620739786477feb7ccd6c08f58940615d5afb4b..f7adb108bbd0a97e9443fca2d70481c3240e4f4c 100644 --- a/src/service/service/service_handlers/p4_fabric_tna_upf/p4_fabric_tna_upf_service_handler.py +++ b/src/service/service/service_handlers/p4_fabric_tna_upf/p4_fabric_tna_upf_service_handler.py @@ -415,6 +415,8 @@ class P4FabricUPFServiceHandler(_ServiceHandler): # Retrieve entry from the port map switch_port_entry = self._get_switch_port_in_port_map(switch_name, port_id) + if not switch_port_entry: + continue host_facing_port = self._is_host_facing_port(switch_name, port_id) LOGGER.info(f"Switch {switch_name} - Port {port_id}: Is host facing: {"True" if host_facing_port else "False"}") @@ -442,6 +444,8 @@ class P4FabricUPFServiceHandler(_ServiceHandler): # Retrieve entry from the port map switch_port_entry = self._get_switch_port_in_port_map(switch_name, port_id) + if not switch_port_entry: + continue # Add routing entry switch_port_entry[ROUTING_LIST].append( @@ -587,7 +591,7 @@ class P4FabricUPFServiceHandler(_ServiceHandler): LOGGER.info(f"\t\t\t| Ctr ID: {self.__upf[CTR_ID]}") LOGGER.info(f"\t\t\t| TC ID: {self.__upf[TC_ID]}") LOGGER.info(f"\t\t\t| Tunnel Peer ID: {self.__upf[TUNNEL_PEER_ID]}\n") - # LOGGER.info("\n") + LOGGER.info("\n") LOGGER.info("\t\t| 5G gNB Configuration:") LOGGER.info(f"\t\t\t| 5G gNB IP: {self.__gnb[IP]}") LOGGER.info(f"\t\t\t| 5G gNB MAC: {self.__gnb[MAC]}\n") @@ -624,9 +628,9 @@ class P4FabricUPFServiceHandler(_ServiceHandler): switch_entry = self.__port_map[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], f"Port with ID {port_id} does not exist in the switch map" - - return switch_entry[port_key] + if port_key in switch_entry: + return switch_entry[port_key] + return {} def _get_port_type_of_switch_port(self, switch_name : str, port_id : int) -> str: switch_port_entry = self._get_switch_port_in_port_map(switch_name, port_id)