diff --git a/src/common/type_checkers/Checkers.py b/src/common/type_checkers/Checkers.py
index 694f1410212137347badbba759cac1a64b1e1c92..e797d64414847aabb402f0bbec17dd65f9c7ec6b 100644
--- a/src/common/type_checkers/Checkers.py
+++ b/src/common/type_checkers/Checkers.py
@@ -140,6 +140,15 @@ def chk_address_ipv4(ip_addr : str):
     except ValueError:
         return False
 
+def chk_prefix_len_ipv4(ip_prefix_len : int):
+    """
+    Check whether input integer is a valid IPv4 address prefix length.
+
+    :param ip_prefix_len: IPv4 address prefix length
+    :return: boolean status
+    """
+    return 0 <= ip_prefix_len <= 32
+
 def chk_address_ipv6(ip_addr : str):
     """
     Check whether input string is a valid IPv6 address or not.
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 4b60f91185aa739fbf182bdf070516389c409e5b..a97bce07fb77cfda222eb2485018b944e6569f4c 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
@@ -24,19 +24,37 @@ SD-Fabric docs: https://docs.sd-fabric.org/master/index.html
 import time
 import logging
 import struct
-from common.proto.context_pb2 import ConfigActionEnum, ConfigRule
-from common.tools.object_factory.ConfigRule import json_config_rule
-from common.type_checkers.Checkers import chk_address_mac, chk_vlan_id, \
-    chk_address_ipv4, chk_transport_port
 from random import randint
 from typing import List, Tuple
+from common.proto.context_pb2 import ConfigActionEnum, ConfigRule, Device, EndPoint
+from common.tools.object_factory.ConfigRule import json_config_rule
+from common.type_checkers.Checkers import chk_address_mac, chk_vlan_id, \
+    chk_address_ipv4, chk_prefix_len_ipv4, chk_transport_port
+from service.service.task_scheduler.TaskExecutor import TaskExecutor
 
 LOGGER = logging.getLogger(__name__)
 
 # Common service handler settings
-TARGET_P4_ARCH = "target_p4_arch"
-SWITCH_DATAPLANE_ID_MAP = "switch_dataplane_id_map"
+SWITCH_INFO = "switch_info"
+ARCH = "arch"
+DPID = "dpid"
+MAC = "mac"
+IP = "ip"
+PORT = "port"                        # Dataplane port
+PORT_ID = "port_id"
+PORT_TYPE = "port_type"
 VLAN_ID = "vlan_id"
+RECIRCULATION_PORT_LIST = "recirculation_port_list"
+PORT_LIST = "port_list"
+PORT_PREFIX = "port-"
+ROUTING_LIST = "routing_list"
+MAC_SRC = "mac_src"
+MAC_DST = "mac_dst"
+IPV4_SRC = "ipv4_src"
+IPV4_DST = "ipv4_dst"
+IPV4_PREFIX_LEN = "ipv4_prefix_len"
+TRN_PORT_SRC = "trn_port_src"        # Transport network port (TCP, UDP)
+TRN_PORT_DST = "trn_port_dst"
 
 # P4 architectures
 TARGET_ARCH_TNA = "tna"
@@ -140,7 +158,7 @@ def generate_random_mac() -> str:
 
     return mac_str
 
-def prefix_to_hex_mask(prefix_len):
+def prefix_to_hex_mask(prefix_len : int) -> str:
     # Calculate the binary mask
     binary_mask = (1 << 32) - (1 << (32 - prefix_len))
 
@@ -156,6 +174,30 @@ def sleep_for(time_sec : int) -> None:
     assert time_sec > 0, "Invalid sleep period in seconds"
     time.sleep(time_sec)
 
+def find_port_id_in_endpoint(endpoint : EndPoint, target_endpoint_uuid : str) -> int: # type: ignore
+    assert endpoint, "Invalid device endpoint"
+    endpoint_uuid = endpoint.endpoint_id.endpoint_uuid.uuid
+    assert endpoint_uuid, "Invalid device endpoint UUID"
+    if endpoint_uuid == target_endpoint_uuid:
+        try:
+            dpid = int(endpoint.name)  # P4 devices have integer dataplane port IDs
+            assert dpid > 0, "Invalid device endpoint DPID"
+        except Exception as ex:
+            LOGGER.error(ex)
+            return -1
+        return dpid
+
+    return -1
+
+def find_port_id_in_endpoint_list(endpoint_list : List, target_endpoint_uuid : str) -> int:
+    assert endpoint_list, "Invalid device endpoint list"
+    for endpoint in endpoint_list:
+        result = find_port_id_in_endpoint(endpoint, target_endpoint_uuid)
+        if result != -1:
+            return result
+
+    return -1
+
 ################################################################################################################
 ### Rule generation methods
 ################################################################################################################
@@ -173,6 +215,9 @@ def rules_set_up_port_ingress(
     assert port_type.lower() in PORT_TYPES_STR_VALID, "Invalid port type to configure ingress port"
     assert chk_vlan_id(vlan_id), "Invalid VLAN ID to configure ingress port"
 
+    # VLAN support if 1
+    vlan_is_valid = 1 if vlan_id != VLAN_DEF else 0
+
     rule_no = cache_rule(TABLE_INGRESS_VLAN, action)
 
     port_type_int = PORT_TYPE_MAP[port_type.lower()]
@@ -192,7 +237,7 @@ def rules_set_up_port_ingress(
                     },
                     {
                         'match-field': 'vlan_is_valid',
-                        'match-value': '0'
+                        'match-value': str(vlan_is_valid)
                     }
                 ],
                 'action-name': 'FabricIngress.filtering.permit_with_internal_vlan',
@@ -270,7 +315,7 @@ def rules_set_up_fwd_classifier(
                         'match-value': str(ingress_port)
                     },
                     {
-                        'match-field': 'eth_type',
+                        'match-field': 'ip_eth_type',
                         'match-value': eth_type
                     }
                 ],
@@ -278,10 +323,10 @@ def rules_set_up_fwd_classifier(
                 'action-params': [
                     {
                         'action-param': 'fwd_type',
-                        'action-value': str(FORWARDING_TYPE_UNICAST_IPV4)
+                        'action-value': str(fwd_type)
                     },
                 ],
-                'priority': 10
+                'priority': 1
             }
         )
     )
@@ -294,7 +339,7 @@ def rules_set_up_port(
         fwd_type : int,
         vlan_id : int,
         action : ConfigActionEnum, # type: ignore
-        eth_type=ETHER_TYPE_IPV4):
+        eth_type=ETHER_TYPE_IPV4) -> List [Tuple]:
     rules_list = []
 
     rules_list.extend(
@@ -377,12 +422,8 @@ def rules_set_up_fwd_bridging(
 
 def rules_set_up_next_output_simple(
         egress_port : int,
-        eth_src : str,
-        eth_dst : str,
         action : ConfigActionEnum) -> List [Tuple]: # type: ignore
     assert egress_port >= 0, "Invalid outport to configure next output simple"
-    assert chk_address_mac(eth_src), "Invalid source Ethernet address to configure next output simple"
-    assert chk_address_mac(eth_dst), "Invalid destination Ethernet address to configure next output simple"
 
     rule_no = cache_rule(TABLE_NEXT_SIMPLE, action)
 
@@ -478,9 +519,11 @@ def rules_set_up_next_output_hashed(
 
 def rules_set_up_routing(
         ipv4_dst : str,
+        ipv4_prefix_len : int,
         egress_port : int,
         action : ConfigActionEnum) -> List [Tuple]: # type: ignore
     assert chk_address_ipv4(ipv4_dst), "Invalid destination IPv4 address to configure routing"
+    assert chk_prefix_len_ipv4(ipv4_prefix_len), "Invalid IPv4 prefix length"
     assert egress_port >= 0, "Invalid outport to configure routing"
 
     rule_no = cache_rule(TABLE_ROUTING_V4, action)
@@ -495,7 +538,7 @@ def rules_set_up_routing(
                 'match-fields': [
                     {
                         'match-field': 'ipv4_dst',
-                        'match-value': ipv4_dst
+                        'match-value': ipv4_dst + "/" + str(ipv4_prefix_len)
                     }
                 ],
                 'action-name': 'FabricIngress.forwarding.set_next_id_routing_v4',
@@ -694,11 +737,14 @@ def rules_set_up_acl_filter_host(
         ingress_port : int,
         ip_address : str,
         prefix_len : int,
+        ip_direction : str,
         action : ConfigActionEnum) -> List [Tuple]: # type: ignore
     assert ingress_port >= 0, "Invalid ingress port to configure ACL"
     assert chk_address_ipv4(ip_address), "Invalid IP address to configure ACL"
     assert 0 < prefix_len <= 32, "Invalid IP address prefix length to configure ACL"
 
+    ip_match = "ipv4_src" if ip_direction == "src" else "ipv4_dst"
+
     prefix_len_hex = prefix_to_hex_mask(prefix_len)
 
     rule_no = cache_rule(TABLE_ACL, action)
@@ -716,7 +762,7 @@ def rules_set_up_acl_filter_host(
                         'match-value': str(ingress_port)
                     },
                     {
-                        'match-field': 'ipv4_src',
+                        'match-field': ip_match,
                         'match-value': '%s&&&%s' % (ip_address, prefix_len_hex)
                     }
                 ],
@@ -732,10 +778,13 @@ def rules_set_up_acl_filter_host(
 def rules_set_up_acl_filter_port(
         ingress_port : int,
         transport_port : int,
+        transport_direction : str,
         action : ConfigActionEnum) -> List [Tuple]: # type: ignore
     assert ingress_port >= 0, "Invalid ingress port to configure ACL"
     assert chk_transport_port(transport_port), "Invalid transport port to configure ACL"
 
+    trn_match = "l4_sport" if transport_direction == "src" else "l4_dport"
+
     rule_no = cache_rule(TABLE_ACL, action)
 
     rules_acl = []
@@ -751,7 +800,7 @@ def rules_set_up_acl_filter_port(
                         'match-value': str(ingress_port)
                     },
                     {
-                        'match-field': 'l4_dport',
+                        'match-field': trn_match,
                         'match-value': str(transport_port)
                     }
                 ],
@@ -772,7 +821,10 @@ def rules_set_up_acl_filter_port(
 ### Rule management methods
 ################################################################################################################
 
-def apply_rules(task_executor, device_obj, json_config_rules):
+def apply_rules(
+        task_executor : TaskExecutor,
+        device_obj : Device,       # type: ignore
+        json_config_rules : List): # type: ignore
     applied_rules = 0
     failed_rules = 0
     total_rules = len(json_config_rules)
@@ -802,9 +854,9 @@ def apply_rules(task_executor, device_obj, json_config_rules):
         except Exception as ex:
             LOGGER.error("Error while applying rule #{}: {}".format(i, ex))
             failed_rules += 1
+            raise Exception(ex)
 
-    LOGGER.info("Batch rules: {}/{} applied".format(applied_rules, total_rules))
-    LOGGER.info("Batch rules: {}/{} failed".format(failed_rules, total_rules))
+    LOGGER.debug("Batch rules: {}/{} applied".format(applied_rules, total_rules))
 
     return applied_rules, failed_rules
 
diff --git a/src/service/service/task_scheduler/TaskExecutor.py b/src/service/service/task_scheduler/TaskExecutor.py
index 51fc42a5a5ea06d5abaa49946a154d0c38f6de8b..8f797882f86f4d53c61da22964909ab1a808ba53 100644
--- a/src/service/service/task_scheduler/TaskExecutor.py
+++ b/src/service/service/task_scheduler/TaskExecutor.py
@@ -203,7 +203,7 @@ class TaskExecutor:
         self, service_id : ServiceId, config_key : str, config_value : str
     ):
         service_configRule = ServiceConfigRule()
-        service_configRule.service_id.CopyFrom( service_id)
+        service_configRule.service_id.CopyFrom(service_id)
         service_configRule.configrule_custom.resource_key = config_key
         service_configRule.configrule_custom.resource_value = config_value
         try:
diff --git a/src/tests/tools/test_tools_p4.py b/src/tests/tools/test_tools_p4.py
index 4557fef61e1f495706a28a5b5646ff97edcfaa54..65257aefc0e0a52e2b1df4753c7ecef1416581d1 100644
--- a/src/tests/tools/test_tools_p4.py
+++ b/src/tests/tools/test_tools_p4.py
@@ -28,9 +28,9 @@ P4_DEV_NB = 1
 CONNECTION_RULES = 3
 ENDPOINT_RULES = 3
 INT_RULES = 19
-L2_RULES = 8
-L3_RULES = 8
-ACL_RULES = 1
+L2_RULES = 10
+L3_RULES = 4
+ACL_RULES = 2
 
 DATAPLANE_RULES_NB_INT_B1 = 5
 DATAPLANE_RULES_NB_INT_B2 = 6